functions.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. package jmespath
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "sort"
  8. "strconv"
  9. "strings"
  10. "unicode/utf8"
  11. )
  12. type jpFunction func(arguments []interface{}) (interface{}, error)
  13. type jpType string
  14. const (
  15. jpUnknown jpType = "unknown"
  16. jpNumber jpType = "number"
  17. jpString jpType = "string"
  18. jpArray jpType = "array"
  19. jpObject jpType = "object"
  20. jpArrayNumber jpType = "array[number]"
  21. jpArrayString jpType = "array[string]"
  22. jpExpref jpType = "expref"
  23. jpAny jpType = "any"
  24. )
  25. type functionEntry struct {
  26. name string
  27. arguments []argSpec
  28. handler jpFunction
  29. hasExpRef bool
  30. }
  31. type argSpec struct {
  32. types []jpType
  33. variadic bool
  34. }
  35. type byExprString struct {
  36. intr *treeInterpreter
  37. node ASTNode
  38. items []interface{}
  39. hasError bool
  40. }
  41. func (a *byExprString) Len() int {
  42. return len(a.items)
  43. }
  44. func (a *byExprString) Swap(i, j int) {
  45. a.items[i], a.items[j] = a.items[j], a.items[i]
  46. }
  47. func (a *byExprString) Less(i, j int) bool {
  48. first, err := a.intr.Execute(a.node, a.items[i])
  49. if err != nil {
  50. a.hasError = true
  51. // Return a dummy value.
  52. return true
  53. }
  54. ith, ok := first.(string)
  55. if !ok {
  56. a.hasError = true
  57. return true
  58. }
  59. second, err := a.intr.Execute(a.node, a.items[j])
  60. if err != nil {
  61. a.hasError = true
  62. // Return a dummy value.
  63. return true
  64. }
  65. jth, ok := second.(string)
  66. if !ok {
  67. a.hasError = true
  68. return true
  69. }
  70. return ith < jth
  71. }
  72. type byExprFloat struct {
  73. intr *treeInterpreter
  74. node ASTNode
  75. items []interface{}
  76. hasError bool
  77. }
  78. func (a *byExprFloat) Len() int {
  79. return len(a.items)
  80. }
  81. func (a *byExprFloat) Swap(i, j int) {
  82. a.items[i], a.items[j] = a.items[j], a.items[i]
  83. }
  84. func (a *byExprFloat) Less(i, j int) bool {
  85. first, err := a.intr.Execute(a.node, a.items[i])
  86. if err != nil {
  87. a.hasError = true
  88. // Return a dummy value.
  89. return true
  90. }
  91. ith, ok := first.(float64)
  92. if !ok {
  93. a.hasError = true
  94. return true
  95. }
  96. second, err := a.intr.Execute(a.node, a.items[j])
  97. if err != nil {
  98. a.hasError = true
  99. // Return a dummy value.
  100. return true
  101. }
  102. jth, ok := second.(float64)
  103. if !ok {
  104. a.hasError = true
  105. return true
  106. }
  107. return ith < jth
  108. }
  109. type functionCaller struct {
  110. functionTable map[string]functionEntry
  111. }
  112. func newFunctionCaller() *functionCaller {
  113. caller := &functionCaller{}
  114. caller.functionTable = map[string]functionEntry{
  115. "length": functionEntry{
  116. name: "length",
  117. arguments: []argSpec{
  118. argSpec{types: []jpType{jpString, jpArray, jpObject}},
  119. },
  120. handler: jpfLength,
  121. },
  122. "starts_with": functionEntry{
  123. name: "starts_with",
  124. arguments: []argSpec{
  125. argSpec{types: []jpType{jpString}},
  126. argSpec{types: []jpType{jpString}},
  127. },
  128. handler: jpfStartsWith,
  129. },
  130. "abs": functionEntry{
  131. name: "abs",
  132. arguments: []argSpec{
  133. argSpec{types: []jpType{jpNumber}},
  134. },
  135. handler: jpfAbs,
  136. },
  137. "avg": functionEntry{
  138. name: "avg",
  139. arguments: []argSpec{
  140. argSpec{types: []jpType{jpArrayNumber}},
  141. },
  142. handler: jpfAvg,
  143. },
  144. "ceil": functionEntry{
  145. name: "ceil",
  146. arguments: []argSpec{
  147. argSpec{types: []jpType{jpNumber}},
  148. },
  149. handler: jpfCeil,
  150. },
  151. "contains": functionEntry{
  152. name: "contains",
  153. arguments: []argSpec{
  154. argSpec{types: []jpType{jpArray, jpString}},
  155. argSpec{types: []jpType{jpAny}},
  156. },
  157. handler: jpfContains,
  158. },
  159. "ends_with": functionEntry{
  160. name: "ends_with",
  161. arguments: []argSpec{
  162. argSpec{types: []jpType{jpString}},
  163. argSpec{types: []jpType{jpString}},
  164. },
  165. handler: jpfEndsWith,
  166. },
  167. "floor": functionEntry{
  168. name: "floor",
  169. arguments: []argSpec{
  170. argSpec{types: []jpType{jpNumber}},
  171. },
  172. handler: jpfFloor,
  173. },
  174. "map": functionEntry{
  175. name: "amp",
  176. arguments: []argSpec{
  177. argSpec{types: []jpType{jpExpref}},
  178. argSpec{types: []jpType{jpArray}},
  179. },
  180. handler: jpfMap,
  181. hasExpRef: true,
  182. },
  183. "max": functionEntry{
  184. name: "max",
  185. arguments: []argSpec{
  186. argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
  187. },
  188. handler: jpfMax,
  189. },
  190. "merge": functionEntry{
  191. name: "merge",
  192. arguments: []argSpec{
  193. argSpec{types: []jpType{jpObject}, variadic: true},
  194. },
  195. handler: jpfMerge,
  196. },
  197. "max_by": functionEntry{
  198. name: "max_by",
  199. arguments: []argSpec{
  200. argSpec{types: []jpType{jpArray}},
  201. argSpec{types: []jpType{jpExpref}},
  202. },
  203. handler: jpfMaxBy,
  204. hasExpRef: true,
  205. },
  206. "sum": functionEntry{
  207. name: "sum",
  208. arguments: []argSpec{
  209. argSpec{types: []jpType{jpArrayNumber}},
  210. },
  211. handler: jpfSum,
  212. },
  213. "min": functionEntry{
  214. name: "min",
  215. arguments: []argSpec{
  216. argSpec{types: []jpType{jpArrayNumber, jpArrayString}},
  217. },
  218. handler: jpfMin,
  219. },
  220. "min_by": functionEntry{
  221. name: "min_by",
  222. arguments: []argSpec{
  223. argSpec{types: []jpType{jpArray}},
  224. argSpec{types: []jpType{jpExpref}},
  225. },
  226. handler: jpfMinBy,
  227. hasExpRef: true,
  228. },
  229. "type": functionEntry{
  230. name: "type",
  231. arguments: []argSpec{
  232. argSpec{types: []jpType{jpAny}},
  233. },
  234. handler: jpfType,
  235. },
  236. "keys": functionEntry{
  237. name: "keys",
  238. arguments: []argSpec{
  239. argSpec{types: []jpType{jpObject}},
  240. },
  241. handler: jpfKeys,
  242. },
  243. "values": functionEntry{
  244. name: "values",
  245. arguments: []argSpec{
  246. argSpec{types: []jpType{jpObject}},
  247. },
  248. handler: jpfValues,
  249. },
  250. "sort": functionEntry{
  251. name: "sort",
  252. arguments: []argSpec{
  253. argSpec{types: []jpType{jpArrayString, jpArrayNumber}},
  254. },
  255. handler: jpfSort,
  256. },
  257. "sort_by": functionEntry{
  258. name: "sort_by",
  259. arguments: []argSpec{
  260. argSpec{types: []jpType{jpArray}},
  261. argSpec{types: []jpType{jpExpref}},
  262. },
  263. handler: jpfSortBy,
  264. hasExpRef: true,
  265. },
  266. "join": functionEntry{
  267. name: "join",
  268. arguments: []argSpec{
  269. argSpec{types: []jpType{jpString}},
  270. argSpec{types: []jpType{jpArrayString}},
  271. },
  272. handler: jpfJoin,
  273. },
  274. "reverse": functionEntry{
  275. name: "reverse",
  276. arguments: []argSpec{
  277. argSpec{types: []jpType{jpArray, jpString}},
  278. },
  279. handler: jpfReverse,
  280. },
  281. "to_array": functionEntry{
  282. name: "to_array",
  283. arguments: []argSpec{
  284. argSpec{types: []jpType{jpAny}},
  285. },
  286. handler: jpfToArray,
  287. },
  288. "to_string": functionEntry{
  289. name: "to_string",
  290. arguments: []argSpec{
  291. argSpec{types: []jpType{jpAny}},
  292. },
  293. handler: jpfToString,
  294. },
  295. "to_number": functionEntry{
  296. name: "to_number",
  297. arguments: []argSpec{
  298. argSpec{types: []jpType{jpAny}},
  299. },
  300. handler: jpfToNumber,
  301. },
  302. "not_null": functionEntry{
  303. name: "not_null",
  304. arguments: []argSpec{
  305. argSpec{types: []jpType{jpAny}, variadic: true},
  306. },
  307. handler: jpfNotNull,
  308. },
  309. }
  310. return caller
  311. }
  312. func (e *functionEntry) resolveArgs(arguments []interface{}) ([]interface{}, error) {
  313. if len(e.arguments) == 0 {
  314. return arguments, nil
  315. }
  316. if !e.arguments[len(e.arguments)-1].variadic {
  317. if len(e.arguments) != len(arguments) {
  318. return nil, errors.New("incorrect number of args")
  319. }
  320. for i, spec := range e.arguments {
  321. userArg := arguments[i]
  322. err := spec.typeCheck(userArg)
  323. if err != nil {
  324. return nil, err
  325. }
  326. }
  327. return arguments, nil
  328. }
  329. if len(arguments) < len(e.arguments) {
  330. return nil, errors.New("Invalid arity.")
  331. }
  332. return arguments, nil
  333. }
  334. func (a *argSpec) typeCheck(arg interface{}) error {
  335. for _, t := range a.types {
  336. switch t {
  337. case jpNumber:
  338. if _, ok := arg.(float64); ok {
  339. return nil
  340. }
  341. case jpString:
  342. if _, ok := arg.(string); ok {
  343. return nil
  344. }
  345. case jpArray:
  346. if _, ok := arg.([]interface{}); ok {
  347. return nil
  348. }
  349. case jpObject:
  350. if _, ok := arg.(map[string]interface{}); ok {
  351. return nil
  352. }
  353. case jpArrayNumber:
  354. if _, ok := toArrayNum(arg); ok {
  355. return nil
  356. }
  357. case jpArrayString:
  358. if _, ok := toArrayStr(arg); ok {
  359. return nil
  360. }
  361. case jpAny:
  362. return nil
  363. case jpExpref:
  364. if _, ok := arg.(expRef); ok {
  365. return nil
  366. }
  367. }
  368. }
  369. return fmt.Errorf("Invalid type for: %v, expected: %#v", arg, a.types)
  370. }
  371. func (f *functionCaller) CallFunction(name string, arguments []interface{}, intr *treeInterpreter) (interface{}, error) {
  372. entry, ok := f.functionTable[name]
  373. if !ok {
  374. return nil, errors.New("unknown function: " + name)
  375. }
  376. resolvedArgs, err := entry.resolveArgs(arguments)
  377. if err != nil {
  378. return nil, err
  379. }
  380. if entry.hasExpRef {
  381. var extra []interface{}
  382. extra = append(extra, intr)
  383. resolvedArgs = append(extra, resolvedArgs...)
  384. }
  385. return entry.handler(resolvedArgs)
  386. }
  387. func jpfAbs(arguments []interface{}) (interface{}, error) {
  388. num := arguments[0].(float64)
  389. return math.Abs(num), nil
  390. }
  391. func jpfLength(arguments []interface{}) (interface{}, error) {
  392. arg := arguments[0]
  393. if c, ok := arg.(string); ok {
  394. return float64(utf8.RuneCountInString(c)), nil
  395. } else if c, ok := arg.([]interface{}); ok {
  396. return float64(len(c)), nil
  397. } else if c, ok := arg.(map[string]interface{}); ok {
  398. return float64(len(c)), nil
  399. }
  400. return nil, errors.New("could not compute length()")
  401. }
  402. func jpfStartsWith(arguments []interface{}) (interface{}, error) {
  403. search := arguments[0].(string)
  404. prefix := arguments[1].(string)
  405. return strings.HasPrefix(search, prefix), nil
  406. }
  407. func jpfAvg(arguments []interface{}) (interface{}, error) {
  408. // We've already type checked the value so we can safely use
  409. // type assertions.
  410. args := arguments[0].([]interface{})
  411. length := float64(len(args))
  412. numerator := 0.0
  413. for _, n := range args {
  414. numerator += n.(float64)
  415. }
  416. return numerator / length, nil
  417. }
  418. func jpfCeil(arguments []interface{}) (interface{}, error) {
  419. val := arguments[0].(float64)
  420. return math.Ceil(val), nil
  421. }
  422. func jpfContains(arguments []interface{}) (interface{}, error) {
  423. search := arguments[0]
  424. el := arguments[1]
  425. if searchStr, ok := search.(string); ok {
  426. if elStr, ok := el.(string); ok {
  427. return strings.Index(searchStr, elStr) != -1, nil
  428. }
  429. return false, nil
  430. }
  431. // Otherwise this is a generic contains for []interface{}
  432. general := search.([]interface{})
  433. for _, item := range general {
  434. if item == el {
  435. return true, nil
  436. }
  437. }
  438. return false, nil
  439. }
  440. func jpfEndsWith(arguments []interface{}) (interface{}, error) {
  441. search := arguments[0].(string)
  442. suffix := arguments[1].(string)
  443. return strings.HasSuffix(search, suffix), nil
  444. }
  445. func jpfFloor(arguments []interface{}) (interface{}, error) {
  446. val := arguments[0].(float64)
  447. return math.Floor(val), nil
  448. }
  449. func jpfMap(arguments []interface{}) (interface{}, error) {
  450. intr := arguments[0].(*treeInterpreter)
  451. exp := arguments[1].(expRef)
  452. node := exp.ref
  453. arr := arguments[2].([]interface{})
  454. mapped := make([]interface{}, 0, len(arr))
  455. for _, value := range arr {
  456. current, err := intr.Execute(node, value)
  457. if err != nil {
  458. return nil, err
  459. }
  460. mapped = append(mapped, current)
  461. }
  462. return mapped, nil
  463. }
  464. func jpfMax(arguments []interface{}) (interface{}, error) {
  465. if items, ok := toArrayNum(arguments[0]); ok {
  466. if len(items) == 0 {
  467. return nil, nil
  468. }
  469. if len(items) == 1 {
  470. return items[0], nil
  471. }
  472. best := items[0]
  473. for _, item := range items[1:] {
  474. if item > best {
  475. best = item
  476. }
  477. }
  478. return best, nil
  479. }
  480. // Otherwise we're dealing with a max() of strings.
  481. items, _ := toArrayStr(arguments[0])
  482. if len(items) == 0 {
  483. return nil, nil
  484. }
  485. if len(items) == 1 {
  486. return items[0], nil
  487. }
  488. best := items[0]
  489. for _, item := range items[1:] {
  490. if item > best {
  491. best = item
  492. }
  493. }
  494. return best, nil
  495. }
  496. func jpfMerge(arguments []interface{}) (interface{}, error) {
  497. final := make(map[string]interface{})
  498. for _, m := range arguments {
  499. mapped := m.(map[string]interface{})
  500. for key, value := range mapped {
  501. final[key] = value
  502. }
  503. }
  504. return final, nil
  505. }
  506. func jpfMaxBy(arguments []interface{}) (interface{}, error) {
  507. intr := arguments[0].(*treeInterpreter)
  508. arr := arguments[1].([]interface{})
  509. exp := arguments[2].(expRef)
  510. node := exp.ref
  511. if len(arr) == 0 {
  512. return nil, nil
  513. } else if len(arr) == 1 {
  514. return arr[0], nil
  515. }
  516. start, err := intr.Execute(node, arr[0])
  517. if err != nil {
  518. return nil, err
  519. }
  520. switch t := start.(type) {
  521. case float64:
  522. bestVal := t
  523. bestItem := arr[0]
  524. for _, item := range arr[1:] {
  525. result, err := intr.Execute(node, item)
  526. if err != nil {
  527. return nil, err
  528. }
  529. current, ok := result.(float64)
  530. if !ok {
  531. return nil, errors.New("invalid type, must be number")
  532. }
  533. if current > bestVal {
  534. bestVal = current
  535. bestItem = item
  536. }
  537. }
  538. return bestItem, nil
  539. case string:
  540. bestVal := t
  541. bestItem := arr[0]
  542. for _, item := range arr[1:] {
  543. result, err := intr.Execute(node, item)
  544. if err != nil {
  545. return nil, err
  546. }
  547. current, ok := result.(string)
  548. if !ok {
  549. return nil, errors.New("invalid type, must be string")
  550. }
  551. if current > bestVal {
  552. bestVal = current
  553. bestItem = item
  554. }
  555. }
  556. return bestItem, nil
  557. default:
  558. return nil, errors.New("invalid type, must be number of string")
  559. }
  560. }
  561. func jpfSum(arguments []interface{}) (interface{}, error) {
  562. items, _ := toArrayNum(arguments[0])
  563. sum := 0.0
  564. for _, item := range items {
  565. sum += item
  566. }
  567. return sum, nil
  568. }
  569. func jpfMin(arguments []interface{}) (interface{}, error) {
  570. if items, ok := toArrayNum(arguments[0]); ok {
  571. if len(items) == 0 {
  572. return nil, nil
  573. }
  574. if len(items) == 1 {
  575. return items[0], nil
  576. }
  577. best := items[0]
  578. for _, item := range items[1:] {
  579. if item < best {
  580. best = item
  581. }
  582. }
  583. return best, nil
  584. }
  585. items, _ := toArrayStr(arguments[0])
  586. if len(items) == 0 {
  587. return nil, nil
  588. }
  589. if len(items) == 1 {
  590. return items[0], nil
  591. }
  592. best := items[0]
  593. for _, item := range items[1:] {
  594. if item < best {
  595. best = item
  596. }
  597. }
  598. return best, nil
  599. }
  600. func jpfMinBy(arguments []interface{}) (interface{}, error) {
  601. intr := arguments[0].(*treeInterpreter)
  602. arr := arguments[1].([]interface{})
  603. exp := arguments[2].(expRef)
  604. node := exp.ref
  605. if len(arr) == 0 {
  606. return nil, nil
  607. } else if len(arr) == 1 {
  608. return arr[0], nil
  609. }
  610. start, err := intr.Execute(node, arr[0])
  611. if err != nil {
  612. return nil, err
  613. }
  614. if t, ok := start.(float64); ok {
  615. bestVal := t
  616. bestItem := arr[0]
  617. for _, item := range arr[1:] {
  618. result, err := intr.Execute(node, item)
  619. if err != nil {
  620. return nil, err
  621. }
  622. current, ok := result.(float64)
  623. if !ok {
  624. return nil, errors.New("invalid type, must be number")
  625. }
  626. if current < bestVal {
  627. bestVal = current
  628. bestItem = item
  629. }
  630. }
  631. return bestItem, nil
  632. } else if t, ok := start.(string); ok {
  633. bestVal := t
  634. bestItem := arr[0]
  635. for _, item := range arr[1:] {
  636. result, err := intr.Execute(node, item)
  637. if err != nil {
  638. return nil, err
  639. }
  640. current, ok := result.(string)
  641. if !ok {
  642. return nil, errors.New("invalid type, must be string")
  643. }
  644. if current < bestVal {
  645. bestVal = current
  646. bestItem = item
  647. }
  648. }
  649. return bestItem, nil
  650. } else {
  651. return nil, errors.New("invalid type, must be number of string")
  652. }
  653. }
  654. func jpfType(arguments []interface{}) (interface{}, error) {
  655. arg := arguments[0]
  656. if _, ok := arg.(float64); ok {
  657. return "number", nil
  658. }
  659. if _, ok := arg.(string); ok {
  660. return "string", nil
  661. }
  662. if _, ok := arg.([]interface{}); ok {
  663. return "array", nil
  664. }
  665. if _, ok := arg.(map[string]interface{}); ok {
  666. return "object", nil
  667. }
  668. if arg == nil {
  669. return "null", nil
  670. }
  671. if arg == true || arg == false {
  672. return "boolean", nil
  673. }
  674. return nil, errors.New("unknown type")
  675. }
  676. func jpfKeys(arguments []interface{}) (interface{}, error) {
  677. arg := arguments[0].(map[string]interface{})
  678. collected := make([]interface{}, 0, len(arg))
  679. for key := range arg {
  680. collected = append(collected, key)
  681. }
  682. return collected, nil
  683. }
  684. func jpfValues(arguments []interface{}) (interface{}, error) {
  685. arg := arguments[0].(map[string]interface{})
  686. collected := make([]interface{}, 0, len(arg))
  687. for _, value := range arg {
  688. collected = append(collected, value)
  689. }
  690. return collected, nil
  691. }
  692. func jpfSort(arguments []interface{}) (interface{}, error) {
  693. if items, ok := toArrayNum(arguments[0]); ok {
  694. d := sort.Float64Slice(items)
  695. sort.Stable(d)
  696. final := make([]interface{}, len(d))
  697. for i, val := range d {
  698. final[i] = val
  699. }
  700. return final, nil
  701. }
  702. // Otherwise we're dealing with sort()'ing strings.
  703. items, _ := toArrayStr(arguments[0])
  704. d := sort.StringSlice(items)
  705. sort.Stable(d)
  706. final := make([]interface{}, len(d))
  707. for i, val := range d {
  708. final[i] = val
  709. }
  710. return final, nil
  711. }
  712. func jpfSortBy(arguments []interface{}) (interface{}, error) {
  713. intr := arguments[0].(*treeInterpreter)
  714. arr := arguments[1].([]interface{})
  715. exp := arguments[2].(expRef)
  716. node := exp.ref
  717. if len(arr) == 0 {
  718. return arr, nil
  719. } else if len(arr) == 1 {
  720. return arr, nil
  721. }
  722. start, err := intr.Execute(node, arr[0])
  723. if err != nil {
  724. return nil, err
  725. }
  726. if _, ok := start.(float64); ok {
  727. sortable := &byExprFloat{intr, node, arr, false}
  728. sort.Stable(sortable)
  729. if sortable.hasError {
  730. return nil, errors.New("error in sort_by comparison")
  731. }
  732. return arr, nil
  733. } else if _, ok := start.(string); ok {
  734. sortable := &byExprString{intr, node, arr, false}
  735. sort.Stable(sortable)
  736. if sortable.hasError {
  737. return nil, errors.New("error in sort_by comparison")
  738. }
  739. return arr, nil
  740. } else {
  741. return nil, errors.New("invalid type, must be number of string")
  742. }
  743. }
  744. func jpfJoin(arguments []interface{}) (interface{}, error) {
  745. sep := arguments[0].(string)
  746. // We can't just do arguments[1].([]string), we have to
  747. // manually convert each item to a string.
  748. arrayStr := []string{}
  749. for _, item := range arguments[1].([]interface{}) {
  750. arrayStr = append(arrayStr, item.(string))
  751. }
  752. return strings.Join(arrayStr, sep), nil
  753. }
  754. func jpfReverse(arguments []interface{}) (interface{}, error) {
  755. if s, ok := arguments[0].(string); ok {
  756. r := []rune(s)
  757. for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
  758. r[i], r[j] = r[j], r[i]
  759. }
  760. return string(r), nil
  761. }
  762. items := arguments[0].([]interface{})
  763. length := len(items)
  764. reversed := make([]interface{}, length)
  765. for i, item := range items {
  766. reversed[length-(i+1)] = item
  767. }
  768. return reversed, nil
  769. }
  770. func jpfToArray(arguments []interface{}) (interface{}, error) {
  771. if _, ok := arguments[0].([]interface{}); ok {
  772. return arguments[0], nil
  773. }
  774. return arguments[:1:1], nil
  775. }
  776. func jpfToString(arguments []interface{}) (interface{}, error) {
  777. if v, ok := arguments[0].(string); ok {
  778. return v, nil
  779. }
  780. result, err := json.Marshal(arguments[0])
  781. if err != nil {
  782. return nil, err
  783. }
  784. return string(result), nil
  785. }
  786. func jpfToNumber(arguments []interface{}) (interface{}, error) {
  787. arg := arguments[0]
  788. if v, ok := arg.(float64); ok {
  789. return v, nil
  790. }
  791. if v, ok := arg.(string); ok {
  792. conv, err := strconv.ParseFloat(v, 64)
  793. if err != nil {
  794. return nil, nil
  795. }
  796. return conv, nil
  797. }
  798. if _, ok := arg.([]interface{}); ok {
  799. return nil, nil
  800. }
  801. if _, ok := arg.(map[string]interface{}); ok {
  802. return nil, nil
  803. }
  804. if arg == nil {
  805. return nil, nil
  806. }
  807. if arg == true || arg == false {
  808. return nil, nil
  809. }
  810. return nil, errors.New("unknown type")
  811. }
  812. func jpfNotNull(arguments []interface{}) (interface{}, error) {
  813. for _, arg := range arguments {
  814. if arg != nil {
  815. return arg, nil
  816. }
  817. }
  818. return nil, nil
  819. }