Skip to content

Commit f6b1026

Browse files
committed
wip
1 parent 9f20e45 commit f6b1026

File tree

3 files changed

+67
-51
lines changed

3 files changed

+67
-51
lines changed

assign_test.go

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
package jsonpointer_test
22

33
import (
4-
"fmt"
54
"testing"
65

76
"github.com/chanced/jsonpointer"
87
"github.com/stretchr/testify/require"
98
)
109

11-
func TestAssignStructField(t *testing.T) {
10+
func TestAssign(t *testing.T) {
1211
assert := require.New(t)
1312

14-
r := Root{
15-
Nested: Nested{
16-
String: "",
17-
},
18-
}
13+
r := Root{}
1914

2015
tests := []struct {
2116
ptr jsonpointer.JSONPointer
@@ -25,11 +20,13 @@ func TestAssignStructField(t *testing.T) {
2520
}{
2621
{"/nested/str", "strval", nil, func(val interface{}) {
2722
assert.Equal(val, r.Nested.String)
28-
fmt.Println(r.Nested.String)
2923
}},
3024
{"/nestedptr/str", "x", nil, func(val interface{}) {
3125
assert.Equal(val, r.NestedPtr.String)
32-
fmt.Println(r.NestedPtr.String)
26+
}},
27+
{"/nested/entrymap/keyval/name", "entry-name", nil, func(v interface{}) {
28+
assert.Contains(r.Nested.EntryMap, "keyval")
29+
assert.Equal("entry-name", r.Nested.EntryMap["keyval"].Name)
3330
}},
3431
}
3532

@@ -43,20 +40,3 @@ func TestAssignStructField(t *testing.T) {
4340
}
4441
}
4542
}
46-
47-
func TestAssignMapValue(t *testing.T) {
48-
// assert := require.New(t)
49-
// m := make(map[string]structentry)
50-
// ptr := JSONPointer("/foo")
51-
// assign := newAssignState(ptr)
52-
// val := structentry{Name: "fooval"}
53-
// err := assign.setMapIndex(
54-
// ptr,
55-
// reflect.TypeOf(m),
56-
// reflect.ValueOf(m),
57-
// reflect.ValueOf(val),
58-
// )
59-
// assert.NoError(err)
60-
// assert.Contains(m, "foo")
61-
// assert.Equal(val, m["foo"])
62-
}

errors.go

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,51 @@ var (
1313
//
1414
// This error is returned by JSONPointer.Validate() which is called by
1515
// Resolve, Assign, and Delete.
16+
//
1617
ErrMalformedToken = fmt.Errorf(`jsonpointer: reference must be empty or start with a "/"`)
18+
1719
// ErrNonPointer indicates a non-pointer value was passed to Assign.
20+
//
1821
ErrNonPointer = errors.New("jsonpointer: dst must be a pointer")
22+
1923
// ErrUnexportedField indicates the given path is not reachable due to being
2024
// an unexported field.
25+
//
2126
ErrUnexportedField = errors.New("jsonpointer: unexported field")
27+
2228
// ErrInvalidKeyType indicates the key type is not supported.
2329
//
2430
// Custom key types must implement encoding.TextUnmarshaler
31+
//
2532
ErrInvalidKeyType = errors.New("jsonpointer: invalid key type")
33+
2634
// ErrNotAssignable indicates the type of the value is not assignable to the
2735
// provided path.
36+
//
2837
ErrNotAssignable = errors.New("jsonpointer: invalid value type")
38+
2939
// ErrNotFound indicates a JSONPointer is not reachable from the root object
3040
// (e.g. a nil pointer, missing map key).
41+
//
3142
ErrNotFound = errors.New(`jsonpointer: value not found`)
43+
3244
// ErrOutOfRange indicates an index is out of range for an array or slice
45+
//
3346
ErrOutOfRange = errors.New("jsonpointer: index out of range")
34-
// ErrUnreachable indicates a reference is not reachable. This occurs
35-
// when a primitive leaf node is reached and the reference is not empty.
47+
48+
// ErrUnreachable indicates a reference is not reachable. This occurs when
49+
// resolving and a primitive (string, number, or bool) leaf node is reached
50+
// and the reference is not empty.
51+
//
3652
ErrUnreachable = fmt.Errorf("%w due to being unreachable", ErrNotFound)
53+
54+
// ErrNilInterface is returned when assigning and a nil interface is
55+
// reached.
56+
//
57+
// To solve this, the node containing the interface should implement
58+
// jsonpoint.Resolver and return a non-nil implemention of the interface.
59+
//
60+
ErrNilInterface = errors.New("jsonpointer: can not assign due to nil interface")
3761
)
3862

3963
// Error is a base error type returned from Resolve, Assign, and Delete.
@@ -282,3 +306,22 @@ func (e *indexError) AsIndexError(err error) (IndexError, bool) {
282306
func (e *indexError) Unwrap() error {
283307
return e.err
284308
}
309+
310+
type nilInterfaceError struct {
311+
ptrError
312+
}
313+
314+
func newNilInterfaceError(s state, typ reflect.Type) *nilInterfaceError {
315+
return &nilInterfaceError{
316+
ptrError: ptrError{
317+
state: s,
318+
err: ErrNilInterface,
319+
typ: typ,
320+
},
321+
}
322+
}
323+
324+
func (e *nilInterfaceError) Error() string {
325+
t, _ := e.Token()
326+
return fmt.Sprintf("jsonpointer: can not assign token \"%s\" of \"%s\" because %v is nil and can not be instantiated.", t, e.ptr, e.typ)
327+
}

state.go

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import (
99
"reflect"
1010
"sort"
1111
"sync"
12-
13-
"github.com/sanity-io/litter"
1412
)
1513

1614
var (
@@ -252,7 +250,6 @@ func (s *state) assign(dst reflect.Value, value reflect.Value) (reflect.Value, e
252250
// TODO: deref the current pointer and use that instead
253251
if s.current.IsRoot() {
254252
_, err := s.assignValue(dst, value)
255-
fmt.Printf("--------------\nROOT\n\"%v\" => %v\n--------------\n", t, dst.Type())
256253
return dst, err
257254
}
258255

@@ -264,18 +261,29 @@ func (s *state) assign(dst reflect.Value, value reflect.Value) (reflect.Value, e
264261
// can i just overwrite src?
265262
var nd reflect.Value
266263
nd, err = s.resolveNext(dst, t)
267-
fmt.Printf("resolved: \"%v\" => %v\n", t, nd.Type())
268264
if err != nil {
269265
return nd, err
270266
}
271267

272268
shouldSet := false
269+
switch nd.Kind() {
270+
case reflect.Ptr:
271+
if nd.IsNil() {
272+
nd.Set(reflect.New(nd.Type().Elem()))
273+
}
274+
case reflect.Interface:
275+
if nd.IsNil() {
276+
return nd, newError(ErrUnreachable, *s, nd.Type())
277+
}
278+
}
279+
273280
if !nd.IsValid() {
274-
switch dst.Kind() {
281+
switch dst.Elem().Kind() {
275282
case reflect.Map, reflect.Slice:
276283
shouldSet = true
277284
nd = reflect.Zero(dst.Type().Elem())
278285
default:
286+
fmt.Println(dst.Type())
279287
// TODO: figure out which other types would be invalid and remove this panic
280288
panic("resolving an invalid value which is not an entry on a map/slice is not done")
281289
}
@@ -291,41 +299,26 @@ func (s *state) assign(dst reflect.Value, value reflect.Value) (reflect.Value, e
291299
nd = pv
292300
}
293301

294-
fmt.Printf("new dst: \"%v\" => %v\n", t, nd.Type())
295-
fmt.Printf("cur dst: \"%v\" => %v\n", t, dst.Type())
296302
_ = shouldSet
303+
297304
var nv reflect.Value
298305
nv, err = s.assign(nd, value)
299-
300-
fmt.Printf("Prepending \"%v\" to \"%s\"\n", s.current, t)
301306
s.current = s.current.Prepend(t)
302-
fmt.Printf("new val: \"%v\" => %v\n", t, nv.Type())
307+
303308
if err != nil {
304309
return dst, err
305310
}
306-
307-
fmt.Printf("calling assignValue(%v, %v) with current = %v, token = %v\n", nd.Type(), nv.Elem().Type(), s.current, t)
308-
fmt.Printf("val: %v\n", value.Type())
309-
fmt.Printf("dst: %v\n", dst.Type())
310311
nd, err = s.assignValue(nd, nv.Elem())
311312
if err != nil {
312313
return nd, err
313314
}
314-
315-
fmt.Printf("--------------\n\"%v\" => %v\n--------------\n", t, nd.Type())
316315
return dst, nil
317316
}
318317

319318
func (s *state) assignValue(dst reflect.Value, v reflect.Value) (reflect.Value, error) {
320319
var err error
321320
cur := s.current
322-
fmt.Println("\nassignValue:")
323-
fmt.Printf("current: \"%s\"", cur)
324-
fmt.Printf("\ndst: %v", dst.Elem().Type())
325-
fmt.Printf("\nvalue: %v\n\n", v.Type())
326-
fmt.Printf("---------------\nASSIGN VALUE: ")
327-
litter.Dump(v.Interface())
328-
fmt.Println("---------------")
321+
329322
if dst.Type().Implements(typeAssigner) {
330323
err = dst.Interface().(Assigner).AssignByJSONPointer(&cur, v)
331324
if err != nil {

0 commit comments

Comments
 (0)