Skip to content

Commit ad46a19

Browse files
committed
wip
1 parent 63edefd commit ad46a19

File tree

8 files changed

+339
-208
lines changed

8 files changed

+339
-208
lines changed

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
# jsonpointer
2-
3-
wip

errors.go

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ var (
2828
ErrNotAssignable = errors.New("jsonpointer: invalid value type")
2929
// ErrNotFound indicates a JSONPointer is not reachable from the root object
3030
// (e.g. a nil pointer, missing map key).
31-
ErrNotFound = errors.New(`jsonpointer: token path not found`)
32-
// ErrOutOfBounds indicates an index is out of bounds for an array or slice
33-
ErrOutOfBounds = errors.New("jsonpointer: index out of bounds")
31+
ErrNotFound = errors.New(`jsonpointer: value not found`)
32+
// ErrOutOfRange indicates an index is out of range for an array or slice
33+
ErrOutOfRange = errors.New("jsonpointer: index out of range")
3434
// ErrInvalidReference indicates a reference is not reachable. This occurs
3535
// when a primitive leaf node is reached and the reference is not empty.
3636
ErrInvalidReference = errors.New("jsonpointer: bad reference")
@@ -72,14 +72,24 @@ type ptrError struct {
7272
}
7373

7474
func (e *ptrError) Error() string {
75-
return e.err.Error()
75+
t, ok := e.Token()
76+
fmt.Println("e.current", e.current)
77+
fmt.Println("TOKEN ERROR", t, ok)
78+
if ok {
79+
return fmt.Sprintf(`"%v for token "%s" in reference "%v"`, e.err.Error(), t, e.ptr)
80+
}
81+
return fmt.Sprintf(`"%v" for reference "%v"`, e.err.Error(), e.ptr)
7682
}
7783

7884
// Unwrap returns the underlying error.
7985
func (e *ptrError) Unwrap() error {
8086
return e.err
8187
}
8288

89+
func (e *ptrError) updateState(s *state) {
90+
e.state = *s
91+
}
92+
8393
// JSONPointer returns the initial JSONPointer.
8494
func (e *ptrError) JSONPointer() JSONPointer {
8595
return e.ptr
@@ -217,3 +227,60 @@ func (e *valueError) Error() string {
217227
func (e *valueError) ValueType() reflect.Type {
218228
return e.valuetype
219229
}
230+
231+
func updateErrorState(err error, s *state) {
232+
if e, ok := err.(interface{ updateState(s *state) }); ok {
233+
e.updateState(s)
234+
}
235+
}
236+
237+
// IndexError indicates an error occurred with regards to an index of a slice or
238+
// array. The error may be wrapped in an Error if it is returned from an operation on a
239+
// JSON Pointer.
240+
//
241+
// err.Index() will return -1 if:
242+
//
243+
// - the source or destination is an array, token is equal to "-",
244+
// and the array does not have a zero value.
245+
//
246+
// - the token can not be parsed as an int
247+
//
248+
type IndexError interface {
249+
MaxIndex() int
250+
Index() int
251+
Error() string
252+
Unwrap() error
253+
}
254+
255+
type indexError struct {
256+
err error
257+
maxIndex int
258+
index int
259+
}
260+
261+
func (e *indexError) MaxIndex() int {
262+
return e.maxIndex
263+
}
264+
265+
func (e *indexError) Index() int {
266+
return e.index
267+
}
268+
269+
func (e *indexError) Error() string {
270+
if errors.Is(e.err, ErrOutOfRange) {
271+
return fmt.Sprintf("%v; expected index to be less than next (%d) but is (%d)", ErrOutOfRange, e.maxIndex, e.index)
272+
}
273+
return fmt.Sprintf("%v for index %d of %d", e.err.Error(), e.index, e.maxIndex)
274+
}
275+
276+
// AsIndexError is a convenience function which calls calls errors.As, returning
277+
// err as an IndexError and true or nil and false if err can not be assigned to
278+
// an IndexError
279+
func (e *indexError) AsIndexError(err error) (IndexError, bool) {
280+
var ie IndexError
281+
return ie, errors.As(err, &ie)
282+
}
283+
284+
func (e *indexError) Unwrap() error {
285+
return e.err
286+
}

jsonpointer.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,33 @@ func (p JSONPointer) String() string {
7070
return string(p)
7171
}
7272

73-
// AppendString encodes and appends token to value of p and returns the new
73+
// Append appends token to the end of reference p and returns the new JSONPointer.
74+
//
75+
// Note: token is not encoded. Use p.AppendString to encode and append the
76+
// token.
77+
func (p JSONPointer) Append(token Token) JSONPointer {
78+
return p + "/" + token.ptr()
79+
}
80+
81+
// AppendString encodes and appends token to the value of p and returns the new
7482
// JSONPointer.
7583
func (p JSONPointer) AppendString(token string) JSONPointer {
7684
return p.Append(Token(encoder.Replace(token)))
7785
}
7886

79-
// Append appends token to valuœe of p and returns the new JSONPointer.
87+
// Preppend prepends token to the beginning of the value of p and returns the
88+
// resulting JSONPointer.
8089
//
81-
// Note: token is not encoded. Use p.AppendString to encode and append the
90+
// Note: token is not encoded. Use p.PrependString to encode and prepend the
8291
// token.
83-
func (p JSONPointer) Append(token Token) JSONPointer {
84-
return JSONPointer(p + "/" + token.ptr())
92+
func (p JSONPointer) Prepend(token Token) JSONPointer {
93+
return "/" + token.ptr() + p
94+
}
95+
96+
// PrependString encodes and prepends token to the value of p and returns the new
97+
// JSONPointer.
98+
func (p JSONPointer) PrependString(token string) JSONPointer {
99+
return p.Prepend(Token(encoder.Replace(token)))
85100
}
86101

87102
func (p JSONPointer) Validate() error {

resolve_test.go

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ import (
77
"github.com/stretchr/testify/require"
88
)
99

10-
func TestResolve(t *testing.T) {
10+
func TestResolveField(t *testing.T) {
1111
assert := require.New(t)
1212
floatv := float64(3.4)
1313
fl := &floatv
1414

1515
r1 := Root{
1616
Nested: Nested{
17-
String: "string",
17+
String: "strval",
1818
FloatPtr: fl,
1919
},
2020
}
2121
var err error
2222
var sr string
23-
err = jsonpointer.Resolve(r1, "/nested/str", &sr)
23+
err = jsonpointer.Resolve(r1, "/nested/string", &sr)
2424
assert.NoError(err)
25-
assert.Equal("str", sr)
25+
assert.Equal("strval", sr)
2626

2727
var floatres *float64
2828
err = jsonpointer.Resolve(r1, "/nested/floatptr", &floatres)
@@ -33,3 +33,59 @@ func TestResolve(t *testing.T) {
3333
err = jsonpointer.Resolve(r1, "/nested/floatptr", &floatptrvalue)
3434
assert.ErrorIs(err, jsonpointer.ErrNotAssignable)
3535
}
36+
37+
func TestResolveMapIndex(t *testing.T) {
38+
assert := require.New(t)
39+
40+
r := Root{
41+
Nested: Nested{
42+
EntryMap: map[string]*Entry{
43+
"foo": {
44+
Name: "bar",
45+
Value: 34.34,
46+
},
47+
},
48+
},
49+
}
50+
var s string
51+
err := jsonpointer.Resolve(r, "/nested/entrymap/foo/name", &s)
52+
assert.Equal("bar", s)
53+
assert.NoError(err)
54+
}
55+
56+
func TestResolveBadMapKey(t *testing.T) {
57+
assert := require.New(t)
58+
var s string
59+
r := Root{
60+
Nested: Nested{
61+
EntryMap: map[string]*Entry{},
62+
},
63+
}
64+
65+
if err, ok := jsonpointer.AsError(jsonpointer.Resolve(r, "/nested/entrymap/x/name", &s)); ok {
66+
t, ok := err.Token()
67+
assert.True(ok)
68+
assert.Equal("x", t.String())
69+
} else {
70+
assert.Fail("expected jsonpointer.Error")
71+
}
72+
}
73+
74+
func TestResolveArray(t *testing.T) {
75+
assert := require.New(t)
76+
r := Root{
77+
Nested: Nested{
78+
StrArray: [3]string{"foo", "bar", "baz"},
79+
IntArray: [3]int{30, 31, 32},
80+
},
81+
}
82+
83+
var s string
84+
err := jsonpointer.Resolve(r, "/nested/strarray/1", &s)
85+
assert.NoError(err)
86+
assert.Equal("bar", s)
87+
88+
var i int
89+
err = jsonpointer.Resolve(r, "/nested/intarray/1", &i)
90+
assert.ErrorIs(err, jsonpointer.ErrNotAssignable)
91+
}

0 commit comments

Comments
 (0)