PageRenderTime 30ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/gopkg.in/bluesuncorp/validator.v5/baked_in.go

https://gitlab.com/rpi-romlinch/drone
Go | 1001 lines | 650 code | 331 blank | 20 comment | 157 complexity | 01c0e4ed9967c53d11daa4664c9e8b57 MD5 | raw file
  1. package validator
  2. import (
  3. "fmt"
  4. "net/url"
  5. "reflect"
  6. "strconv"
  7. "strings"
  8. "time"
  9. "unicode/utf8"
  10. )
  11. // BakedInValidators is the default map of ValidationFunc
  12. // you can add, remove or even replace items to suite your needs,
  13. // or even disregard and use your own map if so desired.
  14. var BakedInValidators = map[string]Func{
  15. "required": hasValue,
  16. "len": hasLengthOf,
  17. "min": hasMinOf,
  18. "max": hasMaxOf,
  19. "eq": isEq,
  20. "ne": isNe,
  21. "lt": isLt,
  22. "lte": isLte,
  23. "gt": isGt,
  24. "gte": isGte,
  25. "eqfield": isEqField,
  26. "nefield": isNeField,
  27. "gtefield": isGteField,
  28. "gtfield": isGtField,
  29. "ltefield": isLteField,
  30. "ltfield": isLtField,
  31. "alpha": isAlpha,
  32. "alphanum": isAlphanum,
  33. "numeric": isNumeric,
  34. "number": isNumber,
  35. "hexadecimal": isHexadecimal,
  36. "hexcolor": isHexcolor,
  37. "rgb": isRgb,
  38. "rgba": isRgba,
  39. "hsl": isHsl,
  40. "hsla": isHsla,
  41. "email": isEmail,
  42. "url": isURL,
  43. "uri": isURI,
  44. "base64": isBase64,
  45. "contains": contains,
  46. "containsany": containsAny,
  47. "containsrune": containsRune,
  48. "excludes": excludes,
  49. "excludesall": excludesAll,
  50. "excludesrune": excludesRune,
  51. "isbn": isISBN,
  52. "isbn10": isISBN10,
  53. "isbn13": isISBN13,
  54. "uuid": isUUID,
  55. "uuid3": isUUID3,
  56. "uuid4": isUUID4,
  57. "uuid5": isUUID5,
  58. "ascii": isASCII,
  59. "printascii": isPrintableASCII,
  60. "multibyte": hasMultiByteCharacter,
  61. "datauri": isDataURI,
  62. "latitude": isLatitude,
  63. "longitude": isLongitude,
  64. "ssn": isSSN,
  65. }
  66. func isSSN(top interface{}, current interface{}, field interface{}, param string) bool {
  67. if len(field.(string)) != 11 {
  68. return false
  69. }
  70. return matchesRegex(sSNRegex, field)
  71. }
  72. func isLongitude(top interface{}, current interface{}, field interface{}, param string) bool {
  73. return matchesRegex(longitudeRegex, field)
  74. }
  75. func isLatitude(top interface{}, current interface{}, field interface{}, param string) bool {
  76. return matchesRegex(latitudeRegex, field)
  77. }
  78. func isDataURI(top interface{}, current interface{}, field interface{}, param string) bool {
  79. uri := strings.SplitN(field.(string), ",", 2)
  80. if len(uri) != 2 {
  81. return false
  82. }
  83. if !matchesRegex(dataURIRegex, uri[0]) {
  84. return false
  85. }
  86. return isBase64(top, current, uri[1], param)
  87. }
  88. func hasMultiByteCharacter(top interface{}, current interface{}, field interface{}, param string) bool {
  89. if len(field.(string)) == 0 {
  90. return true
  91. }
  92. return matchesRegex(multibyteRegex, field)
  93. }
  94. func isPrintableASCII(top interface{}, current interface{}, field interface{}, param string) bool {
  95. return matchesRegex(printableASCIIRegex, field)
  96. }
  97. func isASCII(top interface{}, current interface{}, field interface{}, param string) bool {
  98. return matchesRegex(aSCIIRegex, field)
  99. }
  100. func isUUID5(top interface{}, current interface{}, field interface{}, param string) bool {
  101. return matchesRegex(uUID5Regex, field)
  102. }
  103. func isUUID4(top interface{}, current interface{}, field interface{}, param string) bool {
  104. return matchesRegex(uUID4Regex, field)
  105. }
  106. func isUUID3(top interface{}, current interface{}, field interface{}, param string) bool {
  107. return matchesRegex(uUID3Regex, field)
  108. }
  109. func isUUID(top interface{}, current interface{}, field interface{}, param string) bool {
  110. return matchesRegex(uUIDRegex, field)
  111. }
  112. func isISBN(top interface{}, current interface{}, field interface{}, param string) bool {
  113. return isISBN10(top, current, field, param) || isISBN13(top, current, field, param)
  114. }
  115. func isISBN13(top interface{}, current interface{}, field interface{}, param string) bool {
  116. s := strings.Replace(strings.Replace(field.(string), "-", "", 4), " ", "", 4)
  117. if !matchesRegex(iSBN13Regex, s) {
  118. return false
  119. }
  120. var checksum int32
  121. var i int32
  122. factor := []int32{1, 3}
  123. for i = 0; i < 12; i++ {
  124. checksum += factor[i%2] * int32(s[i]-'0')
  125. }
  126. if (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0 {
  127. return true
  128. }
  129. return false
  130. }
  131. func isISBN10(top interface{}, current interface{}, field interface{}, param string) bool {
  132. s := strings.Replace(strings.Replace(field.(string), "-", "", 3), " ", "", 3)
  133. if !matchesRegex(iSBN10Regex, s) {
  134. return false
  135. }
  136. var checksum int32
  137. var i int32
  138. for i = 0; i < 9; i++ {
  139. checksum += (i + 1) * int32(s[i]-'0')
  140. }
  141. if s[9] == 'X' {
  142. checksum += 10 * 10
  143. } else {
  144. checksum += 10 * int32(s[9]-'0')
  145. }
  146. if checksum%11 == 0 {
  147. return true
  148. }
  149. return false
  150. }
  151. func excludesRune(top interface{}, current interface{}, field interface{}, param string) bool {
  152. return !containsRune(top, current, field, param)
  153. }
  154. func excludesAll(top interface{}, current interface{}, field interface{}, param string) bool {
  155. return !containsAny(top, current, field, param)
  156. }
  157. func excludes(top interface{}, current interface{}, field interface{}, param string) bool {
  158. return !contains(top, current, field, param)
  159. }
  160. func containsRune(top interface{}, current interface{}, field interface{}, param string) bool {
  161. r, _ := utf8.DecodeRuneInString(param)
  162. return strings.ContainsRune(field.(string), r)
  163. }
  164. func containsAny(top interface{}, current interface{}, field interface{}, param string) bool {
  165. return strings.ContainsAny(field.(string), param)
  166. }
  167. func contains(top interface{}, current interface{}, field interface{}, param string) bool {
  168. return strings.Contains(field.(string), param)
  169. }
  170. func isNeField(top interface{}, current interface{}, field interface{}, param string) bool {
  171. return !isEqField(top, current, field, param)
  172. }
  173. func isNe(top interface{}, current interface{}, field interface{}, param string) bool {
  174. return !isEq(top, current, field, param)
  175. }
  176. func isEqField(top interface{}, current interface{}, field interface{}, param string) bool {
  177. if current == nil {
  178. panic("struct not passed for cross validation")
  179. }
  180. currentVal := reflect.ValueOf(current)
  181. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  182. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  183. }
  184. var currentFielVal reflect.Value
  185. switch currentVal.Kind() {
  186. case reflect.Struct:
  187. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  188. currentFielVal = currentVal
  189. break
  190. }
  191. f := currentVal.FieldByName(param)
  192. if f.Kind() == reflect.Invalid {
  193. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  194. }
  195. currentFielVal = f
  196. default:
  197. currentFielVal = currentVal
  198. }
  199. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  200. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  201. }
  202. fv := reflect.ValueOf(field)
  203. switch fv.Kind() {
  204. case reflect.String:
  205. return fv.String() == currentFielVal.String()
  206. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  207. return fv.Int() == currentFielVal.Int()
  208. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  209. return fv.Uint() == currentFielVal.Uint()
  210. case reflect.Float32, reflect.Float64:
  211. return fv.Float() == currentFielVal.Float()
  212. case reflect.Slice, reflect.Map, reflect.Array:
  213. return int64(fv.Len()) == int64(currentFielVal.Len())
  214. case reflect.Struct:
  215. if fv.Type() == reflect.TypeOf(time.Time{}) {
  216. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  217. panic("Bad Top Level field type")
  218. }
  219. t := currentFielVal.Interface().(time.Time)
  220. fieldTime := field.(time.Time)
  221. return fieldTime.Equal(t)
  222. }
  223. }
  224. panic(fmt.Sprintf("Bad field type %T", field))
  225. }
  226. func isEq(top interface{}, current interface{}, field interface{}, param string) bool {
  227. st := reflect.ValueOf(field)
  228. switch st.Kind() {
  229. case reflect.String:
  230. return st.String() == param
  231. case reflect.Slice, reflect.Map, reflect.Array:
  232. p := asInt(param)
  233. return int64(st.Len()) == p
  234. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  235. p := asInt(param)
  236. return st.Int() == p
  237. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  238. p := asUint(param)
  239. return st.Uint() == p
  240. case reflect.Float32, reflect.Float64:
  241. p := asFloat(param)
  242. return st.Float() == p
  243. }
  244. panic(fmt.Sprintf("Bad field type %T", field))
  245. }
  246. func isBase64(top interface{}, current interface{}, field interface{}, param string) bool {
  247. return matchesRegex(base64Regex, field)
  248. }
  249. func isURI(top interface{}, current interface{}, field interface{}, param string) bool {
  250. st := reflect.ValueOf(field)
  251. switch st.Kind() {
  252. case reflect.String:
  253. _, err := url.ParseRequestURI(field.(string))
  254. return err == nil
  255. }
  256. panic(fmt.Sprintf("Bad field type %T", field))
  257. }
  258. func isURL(top interface{}, current interface{}, field interface{}, param string) bool {
  259. st := reflect.ValueOf(field)
  260. switch st.Kind() {
  261. case reflect.String:
  262. url, err := url.ParseRequestURI(field.(string))
  263. if err != nil {
  264. return false
  265. }
  266. if len(url.Scheme) == 0 {
  267. return false
  268. }
  269. return err == nil
  270. }
  271. panic(fmt.Sprintf("Bad field type %T", field))
  272. }
  273. func isEmail(top interface{}, current interface{}, field interface{}, param string) bool {
  274. return matchesRegex(emailRegex, field)
  275. }
  276. func isHsla(top interface{}, current interface{}, field interface{}, param string) bool {
  277. return matchesRegex(hslaRegex, field)
  278. }
  279. func isHsl(top interface{}, current interface{}, field interface{}, param string) bool {
  280. return matchesRegex(hslRegex, field)
  281. }
  282. func isRgba(top interface{}, current interface{}, field interface{}, param string) bool {
  283. return matchesRegex(rgbaRegex, field)
  284. }
  285. func isRgb(top interface{}, current interface{}, field interface{}, param string) bool {
  286. return matchesRegex(rgbRegex, field)
  287. }
  288. func isHexcolor(top interface{}, current interface{}, field interface{}, param string) bool {
  289. return matchesRegex(hexcolorRegex, field)
  290. }
  291. func isHexadecimal(top interface{}, current interface{}, field interface{}, param string) bool {
  292. return matchesRegex(hexadecimalRegex, field)
  293. }
  294. func isNumber(top interface{}, current interface{}, field interface{}, param string) bool {
  295. return matchesRegex(numberRegex, field)
  296. }
  297. func isNumeric(top interface{}, current interface{}, field interface{}, param string) bool {
  298. return matchesRegex(numericRegex, field)
  299. }
  300. func isAlphanum(top interface{}, current interface{}, field interface{}, param string) bool {
  301. return matchesRegex(alphaNumericRegex, field)
  302. }
  303. func isAlpha(top interface{}, current interface{}, field interface{}, param string) bool {
  304. return matchesRegex(alphaRegex, field)
  305. }
  306. func hasValue(top interface{}, current interface{}, field interface{}, param string) bool {
  307. st := reflect.ValueOf(field)
  308. switch st.Kind() {
  309. case reflect.Invalid:
  310. return false
  311. case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
  312. return !st.IsNil()
  313. case reflect.Array:
  314. return field != reflect.Zero(reflect.TypeOf(field)).Interface()
  315. default:
  316. return field != nil && field != reflect.Zero(reflect.TypeOf(field)).Interface()
  317. }
  318. }
  319. func isGteField(top interface{}, current interface{}, field interface{}, param string) bool {
  320. if current == nil {
  321. panic("struct not passed for cross validation")
  322. }
  323. currentVal := reflect.ValueOf(current)
  324. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  325. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  326. }
  327. var currentFielVal reflect.Value
  328. switch currentVal.Kind() {
  329. case reflect.Struct:
  330. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  331. currentFielVal = currentVal
  332. break
  333. }
  334. f := currentVal.FieldByName(param)
  335. if f.Kind() == reflect.Invalid {
  336. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  337. }
  338. currentFielVal = f
  339. default:
  340. currentFielVal = currentVal
  341. }
  342. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  343. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  344. }
  345. fv := reflect.ValueOf(field)
  346. switch fv.Kind() {
  347. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  348. return fv.Int() >= currentFielVal.Int()
  349. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  350. return fv.Uint() >= currentFielVal.Uint()
  351. case reflect.Float32, reflect.Float64:
  352. return fv.Float() >= currentFielVal.Float()
  353. case reflect.Struct:
  354. if fv.Type() == reflect.TypeOf(time.Time{}) {
  355. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  356. panic("Bad Top Level field type")
  357. }
  358. t := currentFielVal.Interface().(time.Time)
  359. fieldTime := field.(time.Time)
  360. return fieldTime.After(t) || fieldTime.Equal(t)
  361. }
  362. }
  363. panic(fmt.Sprintf("Bad field type %T", field))
  364. }
  365. func isGtField(top interface{}, current interface{}, field interface{}, param string) bool {
  366. if current == nil {
  367. panic("struct not passed for cross validation")
  368. }
  369. currentVal := reflect.ValueOf(current)
  370. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  371. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  372. }
  373. var currentFielVal reflect.Value
  374. switch currentVal.Kind() {
  375. case reflect.Struct:
  376. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  377. currentFielVal = currentVal
  378. break
  379. }
  380. f := currentVal.FieldByName(param)
  381. if f.Kind() == reflect.Invalid {
  382. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  383. }
  384. currentFielVal = f
  385. default:
  386. currentFielVal = currentVal
  387. }
  388. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  389. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  390. }
  391. fv := reflect.ValueOf(field)
  392. switch fv.Kind() {
  393. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  394. return fv.Int() > currentFielVal.Int()
  395. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  396. return fv.Uint() > currentFielVal.Uint()
  397. case reflect.Float32, reflect.Float64:
  398. return fv.Float() > currentFielVal.Float()
  399. case reflect.Struct:
  400. if fv.Type() == reflect.TypeOf(time.Time{}) {
  401. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  402. panic("Bad Top Level field type")
  403. }
  404. t := currentFielVal.Interface().(time.Time)
  405. fieldTime := field.(time.Time)
  406. return fieldTime.After(t)
  407. }
  408. }
  409. panic(fmt.Sprintf("Bad field type %T", field))
  410. }
  411. func isGte(top interface{}, current interface{}, field interface{}, param string) bool {
  412. st := reflect.ValueOf(field)
  413. switch st.Kind() {
  414. case reflect.String:
  415. p := asInt(param)
  416. return int64(utf8.RuneCountInString(st.String())) >= p
  417. case reflect.Slice, reflect.Map, reflect.Array:
  418. p := asInt(param)
  419. return int64(st.Len()) >= p
  420. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  421. p := asInt(param)
  422. return st.Int() >= p
  423. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  424. p := asUint(param)
  425. return st.Uint() >= p
  426. case reflect.Float32, reflect.Float64:
  427. p := asFloat(param)
  428. return st.Float() >= p
  429. case reflect.Struct:
  430. if st.Type() == reflect.TypeOf(time.Time{}) {
  431. now := time.Now().UTC()
  432. t := field.(time.Time)
  433. return t.After(now) || t.Equal(now)
  434. }
  435. }
  436. panic(fmt.Sprintf("Bad field type %T", field))
  437. }
  438. func isGt(top interface{}, current interface{}, field interface{}, param string) bool {
  439. st := reflect.ValueOf(field)
  440. switch st.Kind() {
  441. case reflect.String:
  442. p := asInt(param)
  443. return int64(utf8.RuneCountInString(st.String())) > p
  444. case reflect.Slice, reflect.Map, reflect.Array:
  445. p := asInt(param)
  446. return int64(st.Len()) > p
  447. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  448. p := asInt(param)
  449. return st.Int() > p
  450. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  451. p := asUint(param)
  452. return st.Uint() > p
  453. case reflect.Float32, reflect.Float64:
  454. p := asFloat(param)
  455. return st.Float() > p
  456. case reflect.Struct:
  457. if st.Type() == reflect.TypeOf(time.Time{}) {
  458. return field.(time.Time).After(time.Now().UTC())
  459. }
  460. }
  461. panic(fmt.Sprintf("Bad field type %T", field))
  462. }
  463. // length tests whether a variable's length is equal to a given
  464. // value. For strings it tests the number of characters whereas
  465. // for maps and slices it tests the number of items.
  466. func hasLengthOf(top interface{}, current interface{}, field interface{}, param string) bool {
  467. st := reflect.ValueOf(field)
  468. switch st.Kind() {
  469. case reflect.String:
  470. p := asInt(param)
  471. return int64(utf8.RuneCountInString(st.String())) == p
  472. case reflect.Slice, reflect.Map, reflect.Array:
  473. p := asInt(param)
  474. return int64(st.Len()) == p
  475. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  476. p := asInt(param)
  477. return st.Int() == p
  478. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  479. p := asUint(param)
  480. return st.Uint() == p
  481. case reflect.Float32, reflect.Float64:
  482. p := asFloat(param)
  483. return st.Float() == p
  484. }
  485. panic(fmt.Sprintf("Bad field type %T", field))
  486. }
  487. // min tests whether a variable value is larger or equal to a given
  488. // number. For number types, it's a simple lesser-than test; for
  489. // strings it tests the number of characters whereas for maps
  490. // and slices it tests the number of items.
  491. func hasMinOf(top interface{}, current interface{}, field interface{}, param string) bool {
  492. return isGte(top, current, field, param)
  493. }
  494. func isLteField(top interface{}, current interface{}, field interface{}, param string) bool {
  495. if current == nil {
  496. panic("struct not passed for cross validation")
  497. }
  498. currentVal := reflect.ValueOf(current)
  499. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  500. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  501. }
  502. var currentFielVal reflect.Value
  503. switch currentVal.Kind() {
  504. case reflect.Struct:
  505. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  506. currentFielVal = currentVal
  507. break
  508. }
  509. f := currentVal.FieldByName(param)
  510. if f.Kind() == reflect.Invalid {
  511. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  512. }
  513. currentFielVal = f
  514. default:
  515. currentFielVal = currentVal
  516. }
  517. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  518. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  519. }
  520. fv := reflect.ValueOf(field)
  521. switch fv.Kind() {
  522. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  523. return fv.Int() <= currentFielVal.Int()
  524. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  525. return fv.Uint() <= currentFielVal.Uint()
  526. case reflect.Float32, reflect.Float64:
  527. return fv.Float() <= currentFielVal.Float()
  528. case reflect.Struct:
  529. if fv.Type() == reflect.TypeOf(time.Time{}) {
  530. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  531. panic("Bad Top Level field type")
  532. }
  533. t := currentFielVal.Interface().(time.Time)
  534. fieldTime := field.(time.Time)
  535. return fieldTime.Before(t) || fieldTime.Equal(t)
  536. }
  537. }
  538. panic(fmt.Sprintf("Bad field type %T", field))
  539. }
  540. func isLtField(top interface{}, current interface{}, field interface{}, param string) bool {
  541. if current == nil {
  542. panic("struct not passed for cross validation")
  543. }
  544. currentVal := reflect.ValueOf(current)
  545. if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
  546. currentVal = reflect.ValueOf(currentVal.Elem().Interface())
  547. }
  548. var currentFielVal reflect.Value
  549. switch currentVal.Kind() {
  550. case reflect.Struct:
  551. if currentVal.Type() == reflect.TypeOf(time.Time{}) {
  552. currentFielVal = currentVal
  553. break
  554. }
  555. f := currentVal.FieldByName(param)
  556. if f.Kind() == reflect.Invalid {
  557. panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
  558. }
  559. currentFielVal = f
  560. default:
  561. currentFielVal = currentVal
  562. }
  563. if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
  564. currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
  565. }
  566. fv := reflect.ValueOf(field)
  567. switch fv.Kind() {
  568. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  569. return fv.Int() < currentFielVal.Int()
  570. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  571. return fv.Uint() < currentFielVal.Uint()
  572. case reflect.Float32, reflect.Float64:
  573. return fv.Float() < currentFielVal.Float()
  574. case reflect.Struct:
  575. if fv.Type() == reflect.TypeOf(time.Time{}) {
  576. if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
  577. panic("Bad Top Level field type")
  578. }
  579. t := currentFielVal.Interface().(time.Time)
  580. fieldTime := field.(time.Time)
  581. return fieldTime.Before(t)
  582. }
  583. }
  584. panic(fmt.Sprintf("Bad field type %T", field))
  585. }
  586. func isLte(top interface{}, current interface{}, field interface{}, param string) bool {
  587. st := reflect.ValueOf(field)
  588. switch st.Kind() {
  589. case reflect.String:
  590. p := asInt(param)
  591. return int64(utf8.RuneCountInString(st.String())) <= p
  592. case reflect.Slice, reflect.Map, reflect.Array:
  593. p := asInt(param)
  594. return int64(st.Len()) <= p
  595. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  596. p := asInt(param)
  597. return st.Int() <= p
  598. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  599. p := asUint(param)
  600. return st.Uint() <= p
  601. case reflect.Float32, reflect.Float64:
  602. p := asFloat(param)
  603. return st.Float() <= p
  604. case reflect.Struct:
  605. if st.Type() == reflect.TypeOf(time.Time{}) {
  606. now := time.Now().UTC()
  607. t := field.(time.Time)
  608. return t.Before(now) || t.Equal(now)
  609. }
  610. }
  611. panic(fmt.Sprintf("Bad field type %T", field))
  612. }
  613. func isLt(top interface{}, current interface{}, field interface{}, param string) bool {
  614. st := reflect.ValueOf(field)
  615. switch st.Kind() {
  616. case reflect.String:
  617. p := asInt(param)
  618. return int64(utf8.RuneCountInString(st.String())) < p
  619. case reflect.Slice, reflect.Map, reflect.Array:
  620. p := asInt(param)
  621. return int64(st.Len()) < p
  622. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  623. p := asInt(param)
  624. return st.Int() < p
  625. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  626. p := asUint(param)
  627. return st.Uint() < p
  628. case reflect.Float32, reflect.Float64:
  629. p := asFloat(param)
  630. return st.Float() < p
  631. case reflect.Struct:
  632. if st.Type() == reflect.TypeOf(time.Time{}) {
  633. return field.(time.Time).Before(time.Now().UTC())
  634. }
  635. }
  636. panic(fmt.Sprintf("Bad field type %T", field))
  637. }
  638. // max tests whether a variable value is lesser than a given
  639. // value. For numbers, it's a simple lesser-than test; for
  640. // strings it tests the number of characters whereas for maps
  641. // and slices it tests the number of items.
  642. func hasMaxOf(top interface{}, current interface{}, field interface{}, param string) bool {
  643. return isLte(top, current, field, param)
  644. }
  645. // asInt retuns the parameter as a int64
  646. // or panics if it can't convert
  647. func asInt(param string) int64 {
  648. i, err := strconv.ParseInt(param, 0, 64)
  649. panicIf(err)
  650. return i
  651. }
  652. // asUint returns the parameter as a uint64
  653. // or panics if it can't convert
  654. func asUint(param string) uint64 {
  655. i, err := strconv.ParseUint(param, 0, 64)
  656. panicIf(err)
  657. return i
  658. }
  659. // asFloat returns the parameter as a float64
  660. // or panics if it can't convert
  661. func asFloat(param string) float64 {
  662. i, err := strconv.ParseFloat(param, 64)
  663. panicIf(err)
  664. return i
  665. }
  666. func panicIf(err error) {
  667. if err != nil {
  668. panic(err.Error())
  669. }
  670. }