本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
7.8KB

  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. package strfmt
  15. import (
  16. "encoding"
  17. "fmt"
  18. "reflect"
  19. "strings"
  20. "sync"
  21. "time"
  22. "github.com/go-openapi/errors"
  23. "github.com/mitchellh/mapstructure"
  24. )
  25. // Default is the default formats registry
  26. var Default = NewSeededFormats(nil, nil)
  27. // Validator represents a validator for a string format.
  28. type Validator func(string) bool
  29. // Format represents a string format.
  30. //
  31. // All implementations of Format provide a string representation and text
  32. // marshaling/unmarshaling interface to be used by encoders (e.g. encoding/json).
  33. type Format interface {
  34. String() string
  35. encoding.TextMarshaler
  36. encoding.TextUnmarshaler
  37. }
  38. // Registry is a registry of string formats, with a validation method.
  39. type Registry interface {
  40. Add(string, Format, Validator) bool
  41. DelByName(string) bool
  42. GetType(string) (reflect.Type, bool)
  43. ContainsName(string) bool
  44. Validates(string, string) bool
  45. Parse(string, string) (interface{}, error)
  46. MapStructureHookFunc() mapstructure.DecodeHookFunc
  47. }
  48. type knownFormat struct {
  49. Name string
  50. OrigName string
  51. Type reflect.Type
  52. Validator Validator
  53. }
  54. // NameNormalizer is a function that normalizes a format name.
  55. type NameNormalizer func(string) string
  56. // DefaultNameNormalizer removes all dashes
  57. func DefaultNameNormalizer(name string) string {
  58. return strings.Replace(name, "-", "", -1)
  59. }
  60. type defaultFormats struct {
  61. sync.Mutex
  62. data []knownFormat
  63. normalizeName NameNormalizer
  64. }
  65. // NewFormats creates a new formats registry seeded with the values from the default
  66. func NewFormats() Registry {
  67. return NewSeededFormats(Default.(*defaultFormats).data, nil)
  68. }
  69. // NewSeededFormats creates a new formats registry
  70. func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry {
  71. if normalizer == nil {
  72. normalizer = DefaultNameNormalizer
  73. }
  74. // copy here, don't modify original
  75. d := append([]knownFormat(nil), seeds...)
  76. return &defaultFormats{
  77. data: d,
  78. normalizeName: normalizer,
  79. }
  80. }
  81. // MapStructureHookFunc is a decode hook function for mapstructure
  82. func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc {
  83. return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) {
  84. if from.Kind() != reflect.String {
  85. return data, nil
  86. }
  87. for _, v := range f.data {
  88. tpe, _ := f.GetType(v.Name)
  89. if to == tpe {
  90. switch v.Name {
  91. case "date":
  92. d, err := time.Parse(RFC3339FullDate, data.(string))
  93. if err != nil {
  94. return nil, err
  95. }
  96. return Date(d), nil
  97. case "datetime":
  98. input := data.(string)
  99. if len(input) == 0 {
  100. return nil, fmt.Errorf("empty string is an invalid datetime format")
  101. }
  102. return ParseDateTime(input)
  103. case "duration":
  104. dur, err := ParseDuration(data.(string))
  105. if err != nil {
  106. return nil, err
  107. }
  108. return Duration(dur), nil
  109. case "uri":
  110. return URI(data.(string)), nil
  111. case "email":
  112. return Email(data.(string)), nil
  113. case "uuid":
  114. return UUID(data.(string)), nil
  115. case "uuid3":
  116. return UUID3(data.(string)), nil
  117. case "uuid4":
  118. return UUID4(data.(string)), nil
  119. case "uuid5":
  120. return UUID5(data.(string)), nil
  121. case "hostname":
  122. return Hostname(data.(string)), nil
  123. case "ipv4":
  124. return IPv4(data.(string)), nil
  125. case "ipv6":
  126. return IPv6(data.(string)), nil
  127. case "cidr":
  128. return CIDR(data.(string)), nil
  129. case "mac":
  130. return MAC(data.(string)), nil
  131. case "isbn":
  132. return ISBN(data.(string)), nil
  133. case "isbn10":
  134. return ISBN10(data.(string)), nil
  135. case "isbn13":
  136. return ISBN13(data.(string)), nil
  137. case "creditcard":
  138. return CreditCard(data.(string)), nil
  139. case "ssn":
  140. return SSN(data.(string)), nil
  141. case "hexcolor":
  142. return HexColor(data.(string)), nil
  143. case "rgbcolor":
  144. return RGBColor(data.(string)), nil
  145. case "byte":
  146. return Base64(data.(string)), nil
  147. case "password":
  148. return Password(data.(string)), nil
  149. default:
  150. return nil, errors.InvalidTypeName(v.Name)
  151. }
  152. }
  153. }
  154. return data, nil
  155. }
  156. }
  157. // Add adds a new format, return true if this was a new item instead of a replacement
  158. func (f *defaultFormats) Add(name string, strfmt Format, validator Validator) bool {
  159. f.Lock()
  160. defer f.Unlock()
  161. nme := f.normalizeName(name)
  162. tpe := reflect.TypeOf(strfmt)
  163. if tpe.Kind() == reflect.Ptr {
  164. tpe = tpe.Elem()
  165. }
  166. for i := range f.data {
  167. v := &f.data[i]
  168. if v.Name == nme {
  169. v.Type = tpe
  170. v.Validator = validator
  171. return false
  172. }
  173. }
  174. // turns out it's new after all
  175. f.data = append(f.data, knownFormat{Name: nme, OrigName: name, Type: tpe, Validator: validator})
  176. return true
  177. }
  178. // GetType gets the type for the specified name
  179. func (f *defaultFormats) GetType(name string) (reflect.Type, bool) {
  180. f.Lock()
  181. defer f.Unlock()
  182. nme := f.normalizeName(name)
  183. for _, v := range f.data {
  184. if v.Name == nme {
  185. return v.Type, true
  186. }
  187. }
  188. return nil, false
  189. }
  190. // DelByName removes the format by the specified name, returns true when an item was actually removed
  191. func (f *defaultFormats) DelByName(name string) bool {
  192. f.Lock()
  193. defer f.Unlock()
  194. nme := f.normalizeName(name)
  195. for i, v := range f.data {
  196. if v.Name == nme {
  197. f.data[i] = knownFormat{} // release
  198. f.data = append(f.data[:i], f.data[i+1:]...)
  199. return true
  200. }
  201. }
  202. return false
  203. }
  204. // DelByFormat removes the specified format, returns true when an item was actually removed
  205. func (f *defaultFormats) DelByFormat(strfmt Format) bool {
  206. f.Lock()
  207. defer f.Unlock()
  208. tpe := reflect.TypeOf(strfmt)
  209. if tpe.Kind() == reflect.Ptr {
  210. tpe = tpe.Elem()
  211. }
  212. for i, v := range f.data {
  213. if v.Type == tpe {
  214. f.data[i] = knownFormat{} // release
  215. f.data = append(f.data[:i], f.data[i+1:]...)
  216. return true
  217. }
  218. }
  219. return false
  220. }
  221. // ContainsName returns true if this registry contains the specified name
  222. func (f *defaultFormats) ContainsName(name string) bool {
  223. f.Lock()
  224. defer f.Unlock()
  225. nme := f.normalizeName(name)
  226. for _, v := range f.data {
  227. if v.Name == nme {
  228. return true
  229. }
  230. }
  231. return false
  232. }
  233. // ContainsFormat returns true if this registry contains the specified format
  234. func (f *defaultFormats) ContainsFormat(strfmt Format) bool {
  235. f.Lock()
  236. defer f.Unlock()
  237. tpe := reflect.TypeOf(strfmt)
  238. if tpe.Kind() == reflect.Ptr {
  239. tpe = tpe.Elem()
  240. }
  241. for _, v := range f.data {
  242. if v.Type == tpe {
  243. return true
  244. }
  245. }
  246. return false
  247. }
  248. // Validates passed data against format.
  249. //
  250. // Note that the format name is automatically normalized, e.g. one may
  251. // use "date-time" to use the "datetime" format validator.
  252. func (f *defaultFormats) Validates(name, data string) bool {
  253. f.Lock()
  254. defer f.Unlock()
  255. nme := f.normalizeName(name)
  256. for _, v := range f.data {
  257. if v.Name == nme {
  258. return v.Validator(data)
  259. }
  260. }
  261. return false
  262. }
  263. // Parse a string into the appropriate format representation type.
  264. //
  265. // E.g. parsing a string a "date" will return a Date type.
  266. func (f *defaultFormats) Parse(name, data string) (interface{}, error) {
  267. f.Lock()
  268. defer f.Unlock()
  269. nme := f.normalizeName(name)
  270. for _, v := range f.data {
  271. if v.Name == nme {
  272. nw := reflect.New(v.Type).Interface()
  273. if dec, ok := nw.(encoding.TextUnmarshaler); ok {
  274. if err := dec.UnmarshalText([]byte(data)); err != nil {
  275. return nil, err
  276. }
  277. return nw, nil
  278. }
  279. return nil, errors.InvalidTypeName(name)
  280. }
  281. }
  282. return nil, errors.InvalidTypeName(name)
  283. }
上海开阖软件有限公司 沪ICP备12045867号-1