Skip to content

Commit 7d6e22c

Browse files
committed
feat:values deployment & warp error
1 parent 36d0568 commit 7d6e22c

File tree

2 files changed

+250
-13
lines changed

2 files changed

+250
-13
lines changed

ognl.go

Lines changed: 229 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ognl
22

33
import (
44
"errors"
5+
"fmt"
56
"reflect"
67
"strconv"
78
"unsafe"
@@ -14,6 +15,8 @@ var ErrMapKeyMustInt = errors.New("map key must be int")
1415
var ErrIndexOutOfBounds = errors.New("index out of bounds")
1516
var ErrStructIndexOutOfBounds = errors.New("struct index out of bounds")
1617
var ErrParseInt = errors.New("parse int error")
18+
var ErrUnableExpand = errors.New("unable to expand")
19+
var ErrInvalidValue = errors.New("invalid value")
1720

1821
// Type is Result type
1922
type Type int
@@ -146,7 +149,31 @@ func (r Result) Values() []interface{} {
146149
}
147150
return r.raw.([]interface{})
148151
}
149-
return []interface{}{r.raw}
152+
153+
v, t, _ := deployment(reflect.TypeOf(r.raw), reflect.ValueOf(r.raw))
154+
if t == Invalid {
155+
return []interface{}{r.raw}
156+
}
157+
return v
158+
}
159+
160+
func (r Result) ValuesE() ([]interface{}, error) {
161+
162+
if r.deployment {
163+
if r.raw == nil {
164+
return nil, nil
165+
}
166+
return r.raw.([]interface{}), nil
167+
}
168+
169+
v, t, err := deployment(reflect.TypeOf(r.raw), reflect.ValueOf(r.raw))
170+
if err != nil {
171+
return nil, warpError(err, r.raw, "")
172+
}
173+
if t == Invalid {
174+
return []interface{}{r.raw}, nil
175+
}
176+
return v, nil
150177
}
151178

152179
func (r Result) Diagnosis() []error {
@@ -171,14 +198,184 @@ func (r Result) Get(path string) Result {
171198
return Get(r.raw, path)
172199
}
173200

201+
func (r Result) GetE(path string) (Result, error) {
202+
if r.deployment {
203+
nr := r
204+
list := nr.raw.([]interface{})
205+
ln := len(list)
206+
for i := 0; i < ln; i++ {
207+
next, err := GetE(list[i], path)
208+
if err != nil {
209+
nr.diagnosis = append(nr.diagnosis, warpError(err, list[i], path))
210+
}
211+
if next.typ != Invalid {
212+
list = append(list, next.raw)
213+
}
214+
nr.diagnosis = append(nr.diagnosis, next.diagnosis...)
215+
}
216+
nr.raw = list[ln:]
217+
if len(list[ln:]) == 0 {
218+
return nr, warpError(ErrInvalidValue, list, path)
219+
}
220+
return nr, nil
221+
}
222+
return GetE(r.raw, path)
223+
}
224+
174225
func Parse(result interface{}) Result {
175226
return Get(result, "")
176227
}
177228

178-
func Get(value interface{}, path string) Result {
229+
func GetE(value interface{}, path string) (Result, error) {
230+
if value == nil && (len(path) == 0 || validIdentifier(path, 0)) {
231+
return Result{typ: Interface, raw: value}, nil
232+
}
179233
if value == nil {
234+
return Result{typ: Invalid, raw: value}, warpError(ErrInvalidValue, value, path)
235+
}
236+
237+
var (
238+
index int
239+
result = Result{
240+
typ: Interface,
241+
raw: value,
242+
}
243+
)
244+
tp := reflect.TypeOf(value)
245+
tv := reflect.ValueOf(value)
246+
247+
if !tv.IsValid() {
248+
result.typ = Invalid
249+
return result, warpError(ErrInvalidValue, value, path)
250+
}
251+
252+
for ; index < len(path); index++ {
253+
switch path[index] {
254+
case ' ', '\t', '\n', '\r', '.':
255+
switch result.deployment {
256+
case true:
257+
list := result.raw.([]interface{})
258+
ln := len(list)
259+
for i := 0; i < ln; i++ {
260+
next, err := GetE(list[i], path[index+1:])
261+
if err != nil {
262+
result.diagnosis = append(result.diagnosis, warpError(err, list[i], path[index+1:]))
263+
}
264+
if next.typ != Invalid {
265+
list = append(list, next.raw)
266+
}
267+
268+
result.diagnosis = append(result.diagnosis, next.diagnosis...)
269+
}
270+
result.raw = list[ln:]
271+
if len(list[ln:]) == 0 {
272+
return result, warpError(ErrInvalidValue, list, string(path[index]))
273+
}
274+
return result, nil
275+
default:
276+
return GetE(result.raw, path[index+1:])
277+
}
278+
case '#':
279+
// 转化成slice 类型 平铺
280+
switch result.deployment {
281+
case true:
282+
// queue 展开
283+
list := result.raw.([]interface{})
284+
ln := len(list)
285+
for i := 0; i < ln; i++ {
286+
raw, typ, err := deployment(reflect.TypeOf(list[i]), reflect.ValueOf(list[i]))
287+
if err != nil {
288+
result.diagnosis = append(result.diagnosis, warpError(err, list[i], "#"))
289+
}
290+
if typ != Invalid {
291+
list = append(list, raw...)
292+
}
293+
}
294+
result.raw = list[ln:]
295+
if len(list[ln:]) == 0 {
296+
return result, warpError(ErrInvalidValue, list, "#")
297+
}
298+
default:
299+
result.deployment = true
300+
var err error
301+
result.raw, result.typ, err = deployment(tp, tv)
302+
if err != nil {
303+
return result, warpError(err, value, "#")
304+
}
305+
result.diagnosis = append(result.diagnosis, err)
306+
}
307+
308+
default:
309+
start := index
310+
loop:
311+
for ; index < len(path); index++ {
312+
switch path[index] {
313+
case '.', '#':
314+
index--
315+
break loop
316+
}
317+
}
318+
sv := path[start:min(index+1, len(path))]
319+
v, err := strconv.Atoi(sv)
320+
digit := err == nil && v >= 0
321+
switch result.deployment {
322+
case true:
323+
var (
324+
value interface{}
325+
tp Type
326+
)
327+
list := result.raw.([]interface{})
328+
ln := len(list)
329+
for i := 0; i < ln; i++ {
330+
if digit {
331+
value, tp, err = parseInt(reflect.TypeOf(list[i]), reflect.ValueOf(list[i]), v)
332+
} else {
333+
value, tp, err = parseString(reflect.TypeOf(list[i]), reflect.ValueOf(list[i]), sv)
334+
}
335+
if err != nil {
336+
result.diagnosis = append(result.diagnosis, warpError(err, list[i], sv))
337+
}
338+
if tp != Invalid {
339+
list = append(list, value)
340+
}
341+
}
342+
result.raw = list[ln:]
343+
if len(list[ln:]) == 0 {
344+
return result, warpError(ErrInvalidValue, list, sv)
345+
}
346+
347+
default:
348+
var (
349+
nv interface{}
350+
tpe Type
351+
)
352+
if digit {
353+
nv, tpe, err = parseInt(tp, tv, v)
354+
} else {
355+
nv, tpe, err = parseString(tp, tv, sv)
356+
}
357+
if err != nil {
358+
return result, warpError(err, value, sv)
359+
}
360+
if tpe == Invalid {
361+
return result, warpError(ErrInvalidValue, value, sv)
362+
}
363+
result.raw = nv
364+
result.typ = tpe
365+
}
366+
}
367+
}
368+
369+
return result, nil
370+
}
371+
372+
func Get(value interface{}, path string) Result {
373+
if value == nil && (len(path) == 0 || validIdentifier(path, 0)) {
180374
return Result{typ: Interface, raw: value}
181375
}
376+
if value == nil {
377+
return Result{typ: Invalid, raw: value, diagnosis: []error{warpError(ErrInvalidValue, value, path)}}
378+
}
182379

183380
var index int
184381

@@ -190,6 +387,7 @@ func Get(value interface{}, path string) Result {
190387
tv := reflect.ValueOf(value)
191388

192389
if !tv.IsValid() {
390+
result.diagnosis = append(result.diagnosis, warpError(ErrInvalidValue, value, path))
193391
return result
194392
}
195393

@@ -222,7 +420,7 @@ func Get(value interface{}, path string) Result {
222420
for i := 0; i < ln; i++ {
223421
raw, typ, err := deployment(reflect.TypeOf(list[i]), reflect.ValueOf(list[i]))
224422
if err != nil {
225-
result.diagnosis = append(result.diagnosis, err)
423+
result.diagnosis = append(result.diagnosis, warpError(err, list[i], "#"))
226424
}
227425
if typ != Invalid {
228426
list = append(list, raw...)
@@ -234,7 +432,7 @@ func Get(value interface{}, path string) Result {
234432
var err error
235433
result.raw, result.typ, err = deployment(tp, tv)
236434
if err != nil {
237-
result.diagnosis = append(result.diagnosis, err)
435+
result.diagnosis = append(result.diagnosis, warpError(err, value, "#"))
238436
}
239437
}
240438

@@ -266,7 +464,7 @@ func Get(value interface{}, path string) Result {
266464
value, tp, err = parseString(reflect.TypeOf(list[i]), reflect.ValueOf(list[i]), sv)
267465
}
268466
if err != nil {
269-
result.diagnosis = append(result.diagnosis, err)
467+
result.diagnosis = append(result.diagnosis, warpError(err, list[i], sv))
270468
}
271469
if tp != Invalid {
272470
list = append(list, value)
@@ -275,18 +473,18 @@ func Get(value interface{}, path string) Result {
275473
result.raw = list[ln:]
276474
default:
277475
var (
278-
value interface{}
279-
tpe Type
476+
nv interface{}
477+
tpe Type
280478
)
281479
if digit {
282-
value, tpe, err = parseInt(tp, tv, v)
480+
nv, tpe, err = parseInt(tp, tv, v)
283481
} else {
284-
value, tpe, err = parseString(tp, tv, sv)
482+
nv, tpe, err = parseString(tp, tv, sv)
285483
}
286484
if err != nil {
287-
result.diagnosis = append(result.diagnosis, err)
485+
result.diagnosis = append(result.diagnosis, warpError(err, value, sv))
288486
}
289-
result.raw = value
487+
result.raw = nv
290488
result.typ = tpe
291489
if tpe == Invalid {
292490
return result
@@ -472,10 +670,29 @@ func deployment(t reflect.Type, v reflect.Value) ([]interface{}, Type, error) {
472670
return ret, Interface, nil
473671

474672
default:
475-
return []interface{}{v.Interface()}, Type(v.Kind()), nil
673+
return []interface{}{v.Interface()}, Type(v.Kind()), ErrUnableExpand
476674
}
477675
}
478676

677+
func validIdentifier(path string, limit int) bool {
678+
count := 0
679+
for _, v := range path {
680+
switch v {
681+
case ' ', '\t', '\n', '\r', '.':
682+
default:
683+
count++
684+
if count > limit {
685+
return false
686+
}
687+
}
688+
}
689+
return true
690+
}
691+
692+
func warpError(err error, object interface{}, path string) error {
693+
return fmt.Errorf("object:%v,path:%s,err: %w", object, path, err)
694+
}
695+
479696
func min(a, b int) int {
480697
if a > b {
481698
return b

ognl_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func TestGet(t *testing.T) {
9898
for index, v := range test {
9999
vv := Get(t1, v.query)
100100
if !assert.Equal(t, v.effective, vv.Effective()) {
101-
t.Errorf("effective fault expected:%t, got:%t", v.effective, vv.Effective())
101+
t.Errorf("effective fault expected:%t, got:%t, index:%d", v.effective, vv.Effective(), index)
102102
return
103103
}
104104
if !assert.Equal(t, v.value, vv.Value()) {
@@ -146,4 +146,24 @@ func TestGet(t *testing.T) {
146146
t.Errorf("no equal index:%d, query:%s, expected:%v, got:%v", index, v.query, v.value, vv.Value())
147147
}
148148
}
149+
150+
test = []struct {
151+
query string
152+
value interface{}
153+
effective bool
154+
}{
155+
{"List", []interface{}{t2, t3, t4}, true},
156+
{"Array", []interface{}{t2, t3, t4}, true},
157+
}
158+
g1 = Get(t1, "")
159+
for index, v := range test {
160+
vv := g1.Get(v.query)
161+
if !assert.Equal(t, v.effective, vv.Effective()) {
162+
t.Errorf("effective fault expected:%t, got:%t", v.effective, vv.Effective())
163+
return
164+
}
165+
if !assert.Equal(t, v.value, vv.Values()) {
166+
t.Errorf("no equal index:%d, query:%s, expected:%v, got:%v", index, v.query, v.value, vv.Value())
167+
}
168+
}
149169
}

0 commit comments

Comments
 (0)