45
45
type lazyNode struct {
46
46
raw * json.RawMessage
47
47
doc * partialDoc
48
- ary partialArray
48
+ ary * partialArray
49
49
which int
50
50
}
51
51
@@ -56,11 +56,15 @@ type Operation map[string]*json.RawMessage
56
56
type Patch []Operation
57
57
58
58
type partialDoc struct {
59
+ self * lazyNode
59
60
keys []string
60
61
obj map [string ]* lazyNode
61
62
}
62
63
63
- type partialArray []* lazyNode
64
+ type partialArray struct {
65
+ self * lazyNode
66
+ nodes []* lazyNode
67
+ }
64
68
65
69
type container interface {
66
70
get (key string , options * ApplyOptions ) (* lazyNode , error )
@@ -114,7 +118,7 @@ func (n *lazyNode) MarshalJSON() ([]byte, error) {
114
118
case eDoc :
115
119
return json .Marshal (n .doc )
116
120
case eAry :
117
- return json .Marshal (n .ary )
121
+ return json .Marshal (n .ary . nodes )
118
122
default :
119
123
return nil , ErrUnknownType
120
124
}
@@ -199,6 +203,14 @@ func (n *partialDoc) UnmarshalJSON(data []byte) error {
199
203
return nil
200
204
}
201
205
206
+ func (n * partialArray ) UnmarshalJSON (data []byte ) error {
207
+ return json .Unmarshal (data , & n .nodes )
208
+ }
209
+
210
+ func (n * partialArray ) MarshalJSON () ([]byte , error ) {
211
+ return json .Marshal (n .nodes )
212
+ }
213
+
202
214
func skipValue (d * json.Decoder ) error {
203
215
t , err := d .Token ()
204
216
if err != nil {
@@ -264,7 +276,7 @@ func (n *lazyNode) intoDoc() (*partialDoc, error) {
264
276
265
277
func (n * lazyNode ) intoAry () (* partialArray , error ) {
266
278
if n .which == eAry {
267
- return & n .ary , nil
279
+ return n .ary , nil
268
280
}
269
281
270
282
if n .raw == nil {
@@ -278,7 +290,7 @@ func (n *lazyNode) intoAry() (*partialArray, error) {
278
290
}
279
291
280
292
n .which = eAry
281
- return & n .ary , nil
293
+ return n .ary , nil
282
294
}
283
295
284
296
func (n * lazyNode ) compact () []byte {
@@ -380,12 +392,12 @@ func (n *lazyNode) equal(o *lazyNode) bool {
380
392
return false
381
393
}
382
394
383
- if len (n .ary ) != len (o .ary ) {
395
+ if len (n .ary . nodes ) != len (o .ary . nodes ) {
384
396
return false
385
397
}
386
398
387
- for idx , val := range n .ary {
388
- if ! val .equal (o .ary [idx ]) {
399
+ for idx , val := range n .ary . nodes {
400
+ if ! val .equal (o .ary . nodes [idx ]) {
389
401
return false
390
402
}
391
403
}
@@ -497,6 +509,9 @@ func findObject(pd *container, path string, options *ApplyOptions) (container, s
497
509
split := strings .Split (path , "/" )
498
510
499
511
if len (split ) < 2 {
512
+ if path == "" {
513
+ return doc , ""
514
+ }
500
515
return nil , ""
501
516
}
502
517
@@ -552,6 +567,9 @@ func (d *partialDoc) add(key string, val *lazyNode, options *ApplyOptions) error
552
567
}
553
568
554
569
func (d * partialDoc ) get (key string , options * ApplyOptions ) (* lazyNode , error ) {
570
+ if key == "" {
571
+ return d .self , nil
572
+ }
555
573
v , ok := d .obj [key ]
556
574
if ! ok {
557
575
return v , errors .Wrapf (ErrMissing , "unable to get nonexistent key: %s" , key )
@@ -591,19 +609,19 @@ func (d *partialArray) set(key string, val *lazyNode, options *ApplyOptions) err
591
609
if ! options .SupportNegativeIndices {
592
610
return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
593
611
}
594
- if idx < - len (* d ) {
612
+ if idx < - len (d . nodes ) {
595
613
return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
596
614
}
597
- idx += len (* d )
615
+ idx += len (d . nodes )
598
616
}
599
617
600
- ( * d ) [idx ] = val
618
+ d . nodes [idx ] = val
601
619
return nil
602
620
}
603
621
604
622
func (d * partialArray ) add (key string , val * lazyNode , options * ApplyOptions ) error {
605
623
if key == "-" {
606
- * d = append (* d , val )
624
+ d . nodes = append (d . nodes , val )
607
625
return nil
608
626
}
609
627
@@ -612,11 +630,11 @@ func (d *partialArray) add(key string, val *lazyNode, options *ApplyOptions) err
612
630
return errors .Wrapf (err , "value was not a proper array index: '%s'" , key )
613
631
}
614
632
615
- sz := len (* d ) + 1
633
+ sz := len (d . nodes ) + 1
616
634
617
635
ary := make ([]* lazyNode , sz )
618
636
619
- cur := * d
637
+ cur := d
620
638
621
639
if idx >= len (ary ) {
622
640
return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
@@ -632,15 +650,19 @@ func (d *partialArray) add(key string, val *lazyNode, options *ApplyOptions) err
632
650
idx += len (ary )
633
651
}
634
652
635
- copy (ary [0 :idx ], cur [0 :idx ])
653
+ copy (ary [0 :idx ], cur . nodes [0 :idx ])
636
654
ary [idx ] = val
637
- copy (ary [idx + 1 :], cur [idx :])
655
+ copy (ary [idx + 1 :], cur . nodes [idx :])
638
656
639
- * d = ary
657
+ d . nodes = ary
640
658
return nil
641
659
}
642
660
643
661
func (d * partialArray ) get (key string , options * ApplyOptions ) (* lazyNode , error ) {
662
+ if key == "" {
663
+ return d .self , nil
664
+ }
665
+
644
666
idx , err := strconv .Atoi (key )
645
667
646
668
if err != nil {
@@ -651,17 +673,17 @@ func (d *partialArray) get(key string, options *ApplyOptions) (*lazyNode, error)
651
673
if ! options .SupportNegativeIndices {
652
674
return nil , errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
653
675
}
654
- if idx < - len (* d ) {
676
+ if idx < - len (d . nodes ) {
655
677
return nil , errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
656
678
}
657
- idx += len (* d )
679
+ idx += len (d . nodes )
658
680
}
659
681
660
- if idx >= len (* d ) {
682
+ if idx >= len (d . nodes ) {
661
683
return nil , errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
662
684
}
663
685
664
- return ( * d ) [idx ], nil
686
+ return d . nodes [idx ], nil
665
687
}
666
688
667
689
func (d * partialArray ) remove (key string , options * ApplyOptions ) error {
@@ -670,9 +692,9 @@ func (d *partialArray) remove(key string, options *ApplyOptions) error {
670
692
return err
671
693
}
672
694
673
- cur := * d
695
+ cur := d
674
696
675
- if idx >= len (cur ) {
697
+ if idx >= len (cur . nodes ) {
676
698
if options .AllowMissingPathOnRemove {
677
699
return nil
678
700
}
@@ -683,21 +705,21 @@ func (d *partialArray) remove(key string, options *ApplyOptions) error {
683
705
if ! options .SupportNegativeIndices {
684
706
return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
685
707
}
686
- if idx < - len (cur ) {
708
+ if idx < - len (cur . nodes ) {
687
709
if options .AllowMissingPathOnRemove {
688
710
return nil
689
711
}
690
712
return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
691
713
}
692
- idx += len (cur )
714
+ idx += len (cur . nodes )
693
715
}
694
716
695
- ary := make ([]* lazyNode , len (cur )- 1 )
717
+ ary := make ([]* lazyNode , len (cur . nodes )- 1 )
696
718
697
- copy (ary [0 :idx ], cur [0 :idx ])
698
- copy (ary [idx :], cur [idx + 1 :])
719
+ copy (ary [0 :idx ], cur . nodes [0 :idx ])
720
+ copy (ary [idx :], cur . nodes [idx + 1 :])
699
721
700
- * d = ary
722
+ d . nodes = ary
701
723
return nil
702
724
}
703
725
@@ -762,9 +784,9 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
762
784
if arrIndex , err = strconv .Atoi (part ); err == nil {
763
785
pa , ok := doc .(* partialArray )
764
786
765
- if ok && arrIndex >= len (* pa )+ 1 {
787
+ if ok && arrIndex >= len (pa . nodes )+ 1 {
766
788
// Pad the array with null values up to the required index.
767
- for i := len (* pa ); i <= arrIndex - 1 ; i ++ {
789
+ for i := len (pa . nodes ); i <= arrIndex - 1 ; i ++ {
768
790
doc .add (strconv .Itoa (i ), newLazyNode (newRawMessage (rawJSONNull )), options )
769
791
}
770
792
}
@@ -899,7 +921,7 @@ func (p Patch) replace(doc *container, op Operation, options *ApplyOptions) erro
899
921
900
922
switch val .which {
901
923
case eAry :
902
- * doc = & val .ary
924
+ * doc = val .ary
903
925
case eDoc :
904
926
* doc = val .doc
905
927
case eRaw :
@@ -934,6 +956,10 @@ func (p Patch) move(doc *container, op Operation, options *ApplyOptions) error {
934
956
return errors .Wrapf (err , "move operation failed to decode from" )
935
957
}
936
958
959
+ if from == "" {
960
+ return errors .Wrapf (ErrInvalid , "unable to move entire document to another path" )
961
+ }
962
+
937
963
con , key := findObject (doc , from , options )
938
964
939
965
if con == nil {
@@ -983,7 +1009,7 @@ func (p Patch) test(doc *container, op Operation, options *ApplyOptions) error {
983
1009
self .doc = sv
984
1010
self .which = eDoc
985
1011
case * partialArray :
986
- self .ary = * sv
1012
+ self .ary = sv
987
1013
self .which = eAry
988
1014
}
989
1015
@@ -1030,7 +1056,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64, op
1030
1056
con , key := findObject (doc , from , options )
1031
1057
1032
1058
if con == nil {
1033
- return errors .Wrapf (ErrMissing , "copy operation does not apply: doc is missing from path: %s " , from )
1059
+ return errors .Wrapf (ErrMissing , "copy operation does not apply: doc is missing from path: \" %s \" " , from )
1034
1060
}
1035
1061
1036
1062
val , err := con .get (key , options )
@@ -1117,11 +1143,18 @@ func (p Patch) ApplyIndentWithOptions(doc []byte, indent string, options *ApplyO
1117
1143
return doc , nil
1118
1144
}
1119
1145
1146
+ raw := json .RawMessage (doc )
1147
+ self := newLazyNode (& raw )
1148
+
1120
1149
var pd container
1121
1150
if doc [0 ] == '[' {
1122
- pd = & partialArray {}
1151
+ pd = & partialArray {
1152
+ self : self ,
1153
+ }
1123
1154
} else {
1124
- pd = & partialDoc {}
1155
+ pd = & partialDoc {
1156
+ self : self ,
1157
+ }
1125
1158
}
1126
1159
1127
1160
err := json .Unmarshal (doc , pd )
0 commit comments