format.go 7.6 KB

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