podman

Форк
0
326 строк · 7.9 Кб
1
// Copyright 2015 go-swagger maintainers
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package strfmt
16

17
import (
18
	"encoding"
19
	"fmt"
20
	"reflect"
21
	"strings"
22
	"sync"
23
	"time"
24

25
	"github.com/go-openapi/errors"
26
	"github.com/mitchellh/mapstructure"
27
)
28

29
// Default is the default formats registry
30
var Default = NewSeededFormats(nil, nil)
31

32
// Validator represents a validator for a string format.
33
type Validator func(string) bool
34

35
// Format represents a string format.
36
//
37
// All implementations of Format provide a string representation and text
38
// marshaling/unmarshaling interface to be used by encoders (e.g. encoding/json).
39
type Format interface {
40
	String() string
41
	encoding.TextMarshaler
42
	encoding.TextUnmarshaler
43
}
44

45
// Registry is a registry of string formats, with a validation method.
46
type Registry interface {
47
	Add(string, Format, Validator) bool
48
	DelByName(string) bool
49
	GetType(string) (reflect.Type, bool)
50
	ContainsName(string) bool
51
	Validates(string, string) bool
52
	Parse(string, string) (interface{}, error)
53
	MapStructureHookFunc() mapstructure.DecodeHookFunc
54
}
55

56
type knownFormat struct {
57
	Name      string
58
	OrigName  string
59
	Type      reflect.Type
60
	Validator Validator
61
}
62

63
// NameNormalizer is a function that normalizes a format name.
64
type NameNormalizer func(string) string
65

66
// DefaultNameNormalizer removes all dashes
67
func DefaultNameNormalizer(name string) string {
68
	return strings.ReplaceAll(name, "-", "")
69
}
70

71
type defaultFormats struct {
72
	sync.Mutex
73
	data          []knownFormat
74
	normalizeName NameNormalizer
75
}
76

77
// NewFormats creates a new formats registry seeded with the values from the default
78
func NewFormats() Registry {
79
	//nolint:forcetypeassert
80
	return NewSeededFormats(Default.(*defaultFormats).data, nil)
81
}
82

83
// NewSeededFormats creates a new formats registry
84
func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry {
85
	if normalizer == nil {
86
		normalizer = DefaultNameNormalizer
87
	}
88
	// copy here, don't modify original
89
	d := append([]knownFormat(nil), seeds...)
90
	return &defaultFormats{
91
		data:          d,
92
		normalizeName: normalizer,
93
	}
94
}
95

96
// MapStructureHookFunc is a decode hook function for mapstructure
97
func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { //nolint:gocyclo,cyclop
98
	return func(from reflect.Type, to reflect.Type, obj interface{}) (interface{}, error) {
99
		if from.Kind() != reflect.String {
100
			return obj, nil
101
		}
102
		data, ok := obj.(string)
103
		if !ok {
104
			return nil, fmt.Errorf("failed to cast %+v to string", obj)
105
		}
106

107
		for _, v := range f.data {
108
			tpe, _ := f.GetType(v.Name)
109
			if to == tpe {
110
				switch v.Name {
111
				case "date":
112
					d, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation)
113
					if err != nil {
114
						return nil, err
115
					}
116
					return Date(d), nil
117
				case "datetime":
118
					input := data
119
					if len(input) == 0 {
120
						return nil, fmt.Errorf("empty string is an invalid datetime format")
121
					}
122
					return ParseDateTime(input)
123
				case "duration":
124
					dur, err := ParseDuration(data)
125
					if err != nil {
126
						return nil, err
127
					}
128
					return Duration(dur), nil
129
				case "uri":
130
					return URI(data), nil
131
				case "email":
132
					return Email(data), nil
133
				case "uuid":
134
					return UUID(data), nil
135
				case "uuid3":
136
					return UUID3(data), nil
137
				case "uuid4":
138
					return UUID4(data), nil
139
				case "uuid5":
140
					return UUID5(data), nil
141
				case "hostname":
142
					return Hostname(data), nil
143
				case "ipv4":
144
					return IPv4(data), nil
145
				case "ipv6":
146
					return IPv6(data), nil
147
				case "cidr":
148
					return CIDR(data), nil
149
				case "mac":
150
					return MAC(data), nil
151
				case "isbn":
152
					return ISBN(data), nil
153
				case "isbn10":
154
					return ISBN10(data), nil
155
				case "isbn13":
156
					return ISBN13(data), nil
157
				case "creditcard":
158
					return CreditCard(data), nil
159
				case "ssn":
160
					return SSN(data), nil
161
				case "hexcolor":
162
					return HexColor(data), nil
163
				case "rgbcolor":
164
					return RGBColor(data), nil
165
				case "byte":
166
					return Base64(data), nil
167
				case "password":
168
					return Password(data), nil
169
				case "ulid":
170
					ulid, err := ParseULID(data)
171
					if err != nil {
172
						return nil, err
173
					}
174
					return ulid, nil
175
				default:
176
					return nil, errors.InvalidTypeName(v.Name)
177
				}
178
			}
179
		}
180
		return data, nil
181
	}
182
}
183

184
// Add adds a new format, return true if this was a new item instead of a replacement
185
func (f *defaultFormats) Add(name string, strfmt Format, validator Validator) bool {
186
	f.Lock()
187
	defer f.Unlock()
188

189
	nme := f.normalizeName(name)
190

191
	tpe := reflect.TypeOf(strfmt)
192
	if tpe.Kind() == reflect.Ptr {
193
		tpe = tpe.Elem()
194
	}
195

196
	for i := range f.data {
197
		v := &f.data[i]
198
		if v.Name == nme {
199
			v.Type = tpe
200
			v.Validator = validator
201
			return false
202
		}
203
	}
204

205
	// turns out it's new after all
206
	f.data = append(f.data, knownFormat{Name: nme, OrigName: name, Type: tpe, Validator: validator})
207
	return true
208
}
209

210
// GetType gets the type for the specified name
211
func (f *defaultFormats) GetType(name string) (reflect.Type, bool) {
212
	f.Lock()
213
	defer f.Unlock()
214
	nme := f.normalizeName(name)
215
	for _, v := range f.data {
216
		if v.Name == nme {
217
			return v.Type, true
218
		}
219
	}
220
	return nil, false
221
}
222

223
// DelByName removes the format by the specified name, returns true when an item was actually removed
224
func (f *defaultFormats) DelByName(name string) bool {
225
	f.Lock()
226
	defer f.Unlock()
227

228
	nme := f.normalizeName(name)
229

230
	for i, v := range f.data {
231
		if v.Name == nme {
232
			f.data[i] = knownFormat{} // release
233
			f.data = append(f.data[:i], f.data[i+1:]...)
234
			return true
235
		}
236
	}
237
	return false
238
}
239

240
// DelByFormat removes the specified format, returns true when an item was actually removed
241
func (f *defaultFormats) DelByFormat(strfmt Format) bool {
242
	f.Lock()
243
	defer f.Unlock()
244

245
	tpe := reflect.TypeOf(strfmt)
246
	if tpe.Kind() == reflect.Ptr {
247
		tpe = tpe.Elem()
248
	}
249

250
	for i, v := range f.data {
251
		if v.Type == tpe {
252
			f.data[i] = knownFormat{} // release
253
			f.data = append(f.data[:i], f.data[i+1:]...)
254
			return true
255
		}
256
	}
257
	return false
258
}
259

260
// ContainsName returns true if this registry contains the specified name
261
func (f *defaultFormats) ContainsName(name string) bool {
262
	f.Lock()
263
	defer f.Unlock()
264
	nme := f.normalizeName(name)
265
	for _, v := range f.data {
266
		if v.Name == nme {
267
			return true
268
		}
269
	}
270
	return false
271
}
272

273
// ContainsFormat returns true if this registry contains the specified format
274
func (f *defaultFormats) ContainsFormat(strfmt Format) bool {
275
	f.Lock()
276
	defer f.Unlock()
277
	tpe := reflect.TypeOf(strfmt)
278
	if tpe.Kind() == reflect.Ptr {
279
		tpe = tpe.Elem()
280
	}
281

282
	for _, v := range f.data {
283
		if v.Type == tpe {
284
			return true
285
		}
286
	}
287
	return false
288
}
289

290
// Validates passed data against format.
291
//
292
// Note that the format name is automatically normalized, e.g. one may
293
// use "date-time" to use the "datetime" format validator.
294
func (f *defaultFormats) Validates(name, data string) bool {
295
	f.Lock()
296
	defer f.Unlock()
297
	nme := f.normalizeName(name)
298
	for _, v := range f.data {
299
		if v.Name == nme {
300
			return v.Validator(data)
301
		}
302
	}
303
	return false
304
}
305

306
// Parse a string into the appropriate format representation type.
307
//
308
// E.g. parsing a string a "date" will return a Date type.
309
func (f *defaultFormats) Parse(name, data string) (interface{}, error) {
310
	f.Lock()
311
	defer f.Unlock()
312
	nme := f.normalizeName(name)
313
	for _, v := range f.data {
314
		if v.Name == nme {
315
			nw := reflect.New(v.Type).Interface()
316
			if dec, ok := nw.(encoding.TextUnmarshaler); ok {
317
				if err := dec.UnmarshalText([]byte(data)); err != nil {
318
					return nil, err
319
				}
320
				return nw, nil
321
			}
322
			return nil, errors.InvalidTypeName(name)
323
		}
324
	}
325
	return nil, errors.InvalidTypeName(name)
326
}
327

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.