4545type lazyNode struct {
4646 raw * json.RawMessage
4747 doc * partialDoc
48- ary partialArray
48+ ary * partialArray
4949 which int
5050}
5151
@@ -56,11 +56,15 @@ type Operation map[string]*json.RawMessage
5656type Patch []Operation
5757
5858type partialDoc struct {
59+ self * lazyNode
5960 keys []string
6061 obj map [string ]* lazyNode
6162}
6263
63- type partialArray []* lazyNode
64+ type partialArray struct {
65+ self * lazyNode
66+ nodes []* lazyNode
67+ }
6468
6569type container interface {
6670 get (key string , options * ApplyOptions ) (* lazyNode , error )
@@ -114,7 +118,7 @@ func (n *lazyNode) MarshalJSON() ([]byte, error) {
114118 case eDoc :
115119 return json .Marshal (n .doc )
116120 case eAry :
117- return json .Marshal (n .ary )
121+ return json .Marshal (n .ary . nodes )
118122 default :
119123 return nil , ErrUnknownType
120124 }
@@ -199,6 +203,14 @@ func (n *partialDoc) UnmarshalJSON(data []byte) error {
199203 return nil
200204}
201205
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+
202214func skipValue (d * json.Decoder ) error {
203215 t , err := d .Token ()
204216 if err != nil {
@@ -264,7 +276,7 @@ func (n *lazyNode) intoDoc() (*partialDoc, error) {
264276
265277func (n * lazyNode ) intoAry () (* partialArray , error ) {
266278 if n .which == eAry {
267- return & n .ary , nil
279+ return n .ary , nil
268280 }
269281
270282 if n .raw == nil {
@@ -278,7 +290,7 @@ func (n *lazyNode) intoAry() (*partialArray, error) {
278290 }
279291
280292 n .which = eAry
281- return & n .ary , nil
293+ return n .ary , nil
282294}
283295
284296func (n * lazyNode ) compact () []byte {
@@ -380,12 +392,12 @@ func (n *lazyNode) equal(o *lazyNode) bool {
380392 return false
381393 }
382394
383- if len (n .ary ) != len (o .ary ) {
395+ if len (n .ary . nodes ) != len (o .ary . nodes ) {
384396 return false
385397 }
386398
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 ]) {
389401 return false
390402 }
391403 }
@@ -497,6 +509,9 @@ func findObject(pd *container, path string, options *ApplyOptions) (container, s
497509 split := strings .Split (path , "/" )
498510
499511 if len (split ) < 2 {
512+ if path == "" {
513+ return doc , ""
514+ }
500515 return nil , ""
501516 }
502517
@@ -552,6 +567,9 @@ func (d *partialDoc) add(key string, val *lazyNode, options *ApplyOptions) error
552567}
553568
554569func (d * partialDoc ) get (key string , options * ApplyOptions ) (* lazyNode , error ) {
570+ if key == "" {
571+ return d .self , nil
572+ }
555573 v , ok := d .obj [key ]
556574 if ! ok {
557575 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
591609 if ! options .SupportNegativeIndices {
592610 return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
593611 }
594- if idx < - len (* d ) {
612+ if idx < - len (d . nodes ) {
595613 return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
596614 }
597- idx += len (* d )
615+ idx += len (d . nodes )
598616 }
599617
600- ( * d ) [idx ] = val
618+ d . nodes [idx ] = val
601619 return nil
602620}
603621
604622func (d * partialArray ) add (key string , val * lazyNode , options * ApplyOptions ) error {
605623 if key == "-" {
606- * d = append (* d , val )
624+ d . nodes = append (d . nodes , val )
607625 return nil
608626 }
609627
@@ -612,11 +630,11 @@ func (d *partialArray) add(key string, val *lazyNode, options *ApplyOptions) err
612630 return errors .Wrapf (err , "value was not a proper array index: '%s'" , key )
613631 }
614632
615- sz := len (* d ) + 1
633+ sz := len (d . nodes ) + 1
616634
617635 ary := make ([]* lazyNode , sz )
618636
619- cur := * d
637+ cur := d
620638
621639 if idx >= len (ary ) {
622640 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
632650 idx += len (ary )
633651 }
634652
635- copy (ary [0 :idx ], cur [0 :idx ])
653+ copy (ary [0 :idx ], cur . nodes [0 :idx ])
636654 ary [idx ] = val
637- copy (ary [idx + 1 :], cur [idx :])
655+ copy (ary [idx + 1 :], cur . nodes [idx :])
638656
639- * d = ary
657+ d . nodes = ary
640658 return nil
641659}
642660
643661func (d * partialArray ) get (key string , options * ApplyOptions ) (* lazyNode , error ) {
662+ if key == "" {
663+ return d .self , nil
664+ }
665+
644666 idx , err := strconv .Atoi (key )
645667
646668 if err != nil {
@@ -651,17 +673,17 @@ func (d *partialArray) get(key string, options *ApplyOptions) (*lazyNode, error)
651673 if ! options .SupportNegativeIndices {
652674 return nil , errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
653675 }
654- if idx < - len (* d ) {
676+ if idx < - len (d . nodes ) {
655677 return nil , errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
656678 }
657- idx += len (* d )
679+ idx += len (d . nodes )
658680 }
659681
660- if idx >= len (* d ) {
682+ if idx >= len (d . nodes ) {
661683 return nil , errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
662684 }
663685
664- return ( * d ) [idx ], nil
686+ return d . nodes [idx ], nil
665687}
666688
667689func (d * partialArray ) remove (key string , options * ApplyOptions ) error {
@@ -670,9 +692,9 @@ func (d *partialArray) remove(key string, options *ApplyOptions) error {
670692 return err
671693 }
672694
673- cur := * d
695+ cur := d
674696
675- if idx >= len (cur ) {
697+ if idx >= len (cur . nodes ) {
676698 if options .AllowMissingPathOnRemove {
677699 return nil
678700 }
@@ -683,21 +705,21 @@ func (d *partialArray) remove(key string, options *ApplyOptions) error {
683705 if ! options .SupportNegativeIndices {
684706 return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
685707 }
686- if idx < - len (cur ) {
708+ if idx < - len (cur . nodes ) {
687709 if options .AllowMissingPathOnRemove {
688710 return nil
689711 }
690712 return errors .Wrapf (ErrInvalidIndex , "Unable to access invalid index: %d" , idx )
691713 }
692- idx += len (cur )
714+ idx += len (cur . nodes )
693715 }
694716
695- ary := make ([]* lazyNode , len (cur )- 1 )
717+ ary := make ([]* lazyNode , len (cur . nodes )- 1 )
696718
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 :])
699721
700- * d = ary
722+ d . nodes = ary
701723 return nil
702724}
703725
@@ -762,9 +784,9 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
762784 if arrIndex , err = strconv .Atoi (part ); err == nil {
763785 pa , ok := doc .(* partialArray )
764786
765- if ok && arrIndex >= len (* pa )+ 1 {
787+ if ok && arrIndex >= len (pa . nodes )+ 1 {
766788 // 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 ++ {
768790 doc .add (strconv .Itoa (i ), newLazyNode (newRawMessage (rawJSONNull )), options )
769791 }
770792 }
@@ -899,7 +921,7 @@ func (p Patch) replace(doc *container, op Operation, options *ApplyOptions) erro
899921
900922 switch val .which {
901923 case eAry :
902- * doc = & val .ary
924+ * doc = val .ary
903925 case eDoc :
904926 * doc = val .doc
905927 case eRaw :
@@ -934,6 +956,10 @@ func (p Patch) move(doc *container, op Operation, options *ApplyOptions) error {
934956 return errors .Wrapf (err , "move operation failed to decode from" )
935957 }
936958
959+ if from == "" {
960+ return errors .Wrapf (ErrInvalid , "unable to move entire document to another path" )
961+ }
962+
937963 con , key := findObject (doc , from , options )
938964
939965 if con == nil {
@@ -983,7 +1009,7 @@ func (p Patch) test(doc *container, op Operation, options *ApplyOptions) error {
9831009 self .doc = sv
9841010 self .which = eDoc
9851011 case * partialArray :
986- self .ary = * sv
1012+ self .ary = sv
9871013 self .which = eAry
9881014 }
9891015
@@ -1030,7 +1056,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64, op
10301056 con , key := findObject (doc , from , options )
10311057
10321058 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 )
10341060 }
10351061
10361062 val , err := con .get (key , options )
@@ -1117,11 +1143,18 @@ func (p Patch) ApplyIndentWithOptions(doc []byte, indent string, options *ApplyO
11171143 return doc , nil
11181144 }
11191145
1146+ raw := json .RawMessage (doc )
1147+ self := newLazyNode (& raw )
1148+
11201149 var pd container
11211150 if doc [0 ] == '[' {
1122- pd = & partialArray {}
1151+ pd = & partialArray {
1152+ self : self ,
1153+ }
11231154 } else {
1124- pd = & partialDoc {}
1155+ pd = & partialDoc {
1156+ self : self ,
1157+ }
11251158 }
11261159
11271160 err := json .Unmarshal (doc , pd )
0 commit comments