1
2
3
4
5
6
7
8
9
10
11
12
13 package mango
14
15 import (
16 "encoding/json"
17 "errors"
18 "fmt"
19 "regexp"
20 "sort"
21 )
22
23
24 type Selector struct {
25 root Node
26 }
27
28
29 func (s *Selector) Match(doc interface{}) bool {
30 return s.root.Match(doc)
31 }
32
33
34 func (s *Selector) UnmarshalJSON(data []byte) error {
35 node, err := Parse(data)
36 if err != nil {
37 return err
38 }
39 s.root = node
40 return nil
41 }
42
43
44 func Parse(input []byte) (Node, error) {
45 var tmp map[string]json.RawMessage
46 if err := json.Unmarshal(input, &tmp); err != nil {
47 return nil, err
48 }
49 if len(tmp) == 0 {
50
51 return &combinationNode{
52 op: OpAnd,
53 sel: nil,
54 }, nil
55 }
56 sels := make([]Node, 0, len(tmp))
57 for k, v := range tmp {
58 switch op := Operator(k); op {
59 case OpAnd, OpOr, OpNor:
60 var sel []json.RawMessage
61 if err := json.Unmarshal(v, &sel); err != nil {
62 return nil, fmt.Errorf("%s: %w", k, err)
63 }
64 subsels := make([]Node, 0, len(sel))
65 for _, s := range sel {
66 sel, err := Parse(s)
67 if err != nil {
68 return nil, fmt.Errorf("%s: %w", k, err)
69 }
70 subsels = append(subsels, sel)
71 }
72
73 sels = append(sels, &combinationNode{
74 op: op,
75 sel: subsels,
76 })
77 case OpNot:
78 sel, err := Parse(v)
79 if err != nil {
80 return nil, fmt.Errorf("%s: %w", k, err)
81 }
82 sels = append(sels, ¬Node{
83 sel: sel,
84 })
85 case OpEqual, OpLessThan, OpLessThanOrEqual, OpNotEqual,
86 OpGreaterThan, OpGreaterThanOrEqual:
87 op, value, err := opAndValue(v)
88 if err != nil {
89 return nil, err
90 }
91 sels = append(sels, &conditionNode{
92 op: op,
93 cond: value,
94 })
95 default:
96 if op[0] == '$' {
97 return nil, fmt.Errorf("unknown operator %s", op)
98 }
99 op, value, err := opAndValue(v)
100 if err != nil {
101 return nil, err
102 }
103
104 switch op {
105 case OpElemMatch, OpAllMatch, OpKeyMapMatch:
106 sels = append(sels, &fieldNode{
107 field: k,
108 cond: &elementNode{
109 op: op,
110 cond: value.(*conditionNode),
111 },
112 })
113 default:
114 sels = append(sels, &fieldNode{
115 field: k,
116 cond: &conditionNode{
117 op: op,
118 cond: value,
119 },
120 })
121 }
122 }
123 }
124 if len(sels) == 1 {
125 return sels[0], nil
126 }
127
128
129 sort.Slice(sels, func(i, j int) bool {
130 return cmpSelectors(sels[i], sels[j]) < 0
131 })
132
133 return &combinationNode{
134 op: OpAnd,
135 sel: sels,
136 }, nil
137 }
138
139
140
141
142 func opAndValue(input json.RawMessage) (Operator, interface{}, error) {
143 if input[0] != '{' {
144 var value interface{}
145 if err := json.Unmarshal(input, &value); err != nil {
146 return "", nil, err
147 }
148 return OpEqual, value, nil
149 }
150 var tmp map[string]json.RawMessage
151 if err := json.Unmarshal(input, &tmp); err != nil {
152 return "", nil, err
153 }
154 switch len(tmp) {
155 case 0:
156 return OpEqual, map[string]interface{}{}, nil
157 case 1:
158 for k, v := range tmp {
159 switch op := Operator(k); op {
160 case OpEqual, OpLessThan, OpLessThanOrEqual, OpNotEqual,
161 OpGreaterThan, OpGreaterThanOrEqual:
162 var value interface{}
163 err := json.Unmarshal(v, &value)
164 return op, value, err
165 case OpExists:
166 var value bool
167 if err := json.Unmarshal(v, &value); err != nil {
168 return "", nil, fmt.Errorf("%s: %w", k, err)
169 }
170 return OpExists, value, nil
171 case OpType:
172 var value string
173 if err := json.Unmarshal(v, &value); err != nil {
174 return "", nil, fmt.Errorf("%s: %w", k, err)
175 }
176 return OpType, value, nil
177 case OpIn, OpNotIn:
178 var value []interface{}
179 if err := json.Unmarshal(v, &value); err != nil {
180 return "", nil, fmt.Errorf("%s: %w", k, err)
181 }
182 return op, value, nil
183 case OpSize:
184 var value uint
185 if err := json.Unmarshal(v, &value); err != nil {
186 return "", nil, fmt.Errorf("%s: %w", k, err)
187 }
188 return OpSize, float64(value), nil
189 case OpMod:
190 var value [2]int64
191 if err := json.Unmarshal(v, &value); err != nil {
192 return "", nil, fmt.Errorf("%s: %w", k, err)
193 }
194 if value[0] == 0 {
195 return "", nil, errors.New("$mod: divisor must be non-zero")
196 }
197 return OpMod, value, nil
198 case OpRegex:
199 var pattern string
200 if err := json.Unmarshal(v, &pattern); err != nil {
201 return "", nil, fmt.Errorf("%s: %w", k, err)
202 }
203 re, err := regexp.Compile(pattern)
204 if err != nil {
205 return "", nil, fmt.Errorf("%s: %w", k, err)
206 }
207 return OpRegex, re, nil
208 case OpAll:
209 var value []interface{}
210 if err := json.Unmarshal(v, &value); err != nil {
211 return "", nil, fmt.Errorf("%s: %w", k, err)
212 }
213 return OpAll, value, nil
214 case OpElemMatch, OpAllMatch, OpKeyMapMatch:
215 sel, err := Parse(v)
216 if err != nil {
217 return "", nil, fmt.Errorf("%s: %w", k, err)
218 }
219 return op, sel, nil
220 }
221 return "", nil, fmt.Errorf("invalid operator %s", k)
222 }
223 default:
224 return "", nil, errors.New("too many keys in object")
225 }
226 panic("impossible")
227 }
228
View as plain text