mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-14 19:35:48 +08:00
hotfix: fix flag context not works bug (#204)
This commit is contained in:
397
vendor/github.com/evanphx/json-patch/v5/patch.go
generated
vendored
397
vendor/github.com/evanphx/json-patch/v5/patch.go
generated
vendored
@@ -2,11 +2,12 @@ package jsonpatch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/evanphx/json-patch/v5/internal/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -37,6 +38,8 @@ var (
|
||||
ErrInvalid = errors.New("invalid state detected")
|
||||
ErrInvalidIndex = errors.New("invalid index referenced")
|
||||
|
||||
ErrExpectedObject = errors.New("invalid value, expected object")
|
||||
|
||||
rawJSONArray = []byte("[]")
|
||||
rawJSONObject = []byte("{}")
|
||||
rawJSONNull = []byte("null")
|
||||
@@ -45,7 +48,7 @@ var (
|
||||
type lazyNode struct {
|
||||
raw *json.RawMessage
|
||||
doc *partialDoc
|
||||
ary partialArray
|
||||
ary *partialArray
|
||||
which int
|
||||
}
|
||||
|
||||
@@ -56,11 +59,17 @@ type Operation map[string]*json.RawMessage
|
||||
type Patch []Operation
|
||||
|
||||
type partialDoc struct {
|
||||
self *lazyNode
|
||||
keys []string
|
||||
obj map[string]*lazyNode
|
||||
|
||||
opts *ApplyOptions
|
||||
}
|
||||
|
||||
type partialArray []*lazyNode
|
||||
type partialArray struct {
|
||||
self *lazyNode
|
||||
nodes []*lazyNode
|
||||
}
|
||||
|
||||
type container interface {
|
||||
get(key string, options *ApplyOptions) (*lazyNode, error)
|
||||
@@ -85,6 +94,8 @@ type ApplyOptions struct {
|
||||
// EnsurePathExistsOnAdd instructs json-patch to recursively create the missing parts of path on "add" operation.
|
||||
// Default to false.
|
||||
EnsurePathExistsOnAdd bool
|
||||
|
||||
EscapeHTML bool
|
||||
}
|
||||
|
||||
// NewApplyOptions creates a default set of options for calls to ApplyWithOptions.
|
||||
@@ -94,6 +105,7 @@ func NewApplyOptions() *ApplyOptions {
|
||||
AccumulatedCopySizeLimit: AccumulatedCopySizeLimit,
|
||||
AllowMissingPathOnRemove: false,
|
||||
EnsurePathExistsOnAdd: false,
|
||||
EscapeHTML: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,14 +119,14 @@ func newRawMessage(buf []byte) *json.RawMessage {
|
||||
return &ra
|
||||
}
|
||||
|
||||
func (n *lazyNode) MarshalJSON() ([]byte, error) {
|
||||
func (n *lazyNode) RedirectMarshalJSON() (any, error) {
|
||||
switch n.which {
|
||||
case eRaw:
|
||||
return json.Marshal(n.raw)
|
||||
return n.raw, nil
|
||||
case eDoc:
|
||||
return json.Marshal(n.doc)
|
||||
return n.doc, nil
|
||||
case eAry:
|
||||
return json.Marshal(n.ary)
|
||||
return n.ary.nodes, nil
|
||||
default:
|
||||
return nil, ErrUnknownType
|
||||
}
|
||||
@@ -128,39 +140,50 @@ func (n *lazyNode) UnmarshalJSON(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *partialDoc) MarshalJSON() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
if _, err := buf.WriteString("{"); err != nil {
|
||||
return nil, err
|
||||
func (n *partialDoc) TrustMarshalJSON(buf *bytes.Buffer) error {
|
||||
if n.obj == nil {
|
||||
return ErrExpectedObject
|
||||
}
|
||||
|
||||
if err := buf.WriteByte('{'); err != nil {
|
||||
return err
|
||||
}
|
||||
escaped := true
|
||||
|
||||
// n.opts should always be set, but in case we missed a case,
|
||||
// guard.
|
||||
if n.opts != nil {
|
||||
escaped = n.opts.EscapeHTML
|
||||
}
|
||||
|
||||
for i, k := range n.keys {
|
||||
if i > 0 {
|
||||
if _, err := buf.WriteString(", "); err != nil {
|
||||
return nil, err
|
||||
if err := buf.WriteByte(','); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
key, err := json.Marshal(k)
|
||||
key, err := json.MarshalEscaped(k, escaped)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if _, err := buf.Write(key); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if _, err := buf.WriteString(": "); err != nil {
|
||||
return nil, err
|
||||
if err := buf.WriteByte(':'); err != nil {
|
||||
return err
|
||||
}
|
||||
value, err := json.Marshal(n.obj[k])
|
||||
value, err := json.MarshalEscaped(n.obj[k], escaped)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
if _, err := buf.Write(value); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := buf.WriteString("}"); err != nil {
|
||||
return nil, err
|
||||
if err := buf.WriteByte('}'); err != nil {
|
||||
return err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
return nil
|
||||
}
|
||||
|
||||
type syntaxError struct {
|
||||
@@ -172,70 +195,29 @@ func (err *syntaxError) Error() string {
|
||||
}
|
||||
|
||||
func (n *partialDoc) UnmarshalJSON(data []byte) error {
|
||||
if err := json.Unmarshal(data, &n.obj); err != nil {
|
||||
return err
|
||||
}
|
||||
buffer := bytes.NewBuffer(data)
|
||||
d := json.NewDecoder(buffer)
|
||||
if t, err := d.Token(); err != nil {
|
||||
return err
|
||||
} else if t != startObject {
|
||||
return &syntaxError{fmt.Sprintf("unexpected JSON token in document node: %v", t)}
|
||||
}
|
||||
for d.More() {
|
||||
k, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
key, ok := k.(string)
|
||||
if !ok {
|
||||
return &syntaxError{fmt.Sprintf("unexpected JSON token as document node key: %s", k)}
|
||||
}
|
||||
if err := skipValue(d); err != nil {
|
||||
return err
|
||||
}
|
||||
n.keys = append(n.keys, key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func skipValue(d *json.Decoder) error {
|
||||
t, err := d.Token()
|
||||
keys, err := json.UnmarshalValidWithKeys(data, &n.obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t != startObject && t != startArray {
|
||||
return nil
|
||||
}
|
||||
for d.More() {
|
||||
if t == startObject {
|
||||
// consume key token
|
||||
if _, err := d.Token(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := skipValue(d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
end, err := d.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t == startObject && end != endObject {
|
||||
return &syntaxError{msg: "expected close object token"}
|
||||
}
|
||||
if t == startArray && end != endArray {
|
||||
return &syntaxError{msg: "expected close object token"}
|
||||
}
|
||||
|
||||
n.keys = keys
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy(src *lazyNode) (*lazyNode, int, error) {
|
||||
func (n *partialArray) UnmarshalJSON(data []byte) error {
|
||||
return json.UnmarshalValid(data, &n.nodes)
|
||||
}
|
||||
|
||||
func (n *partialArray) RedirectMarshalJSON() (interface{}, error) {
|
||||
return n.nodes, nil
|
||||
}
|
||||
|
||||
func deepCopy(src *lazyNode, options *ApplyOptions) (*lazyNode, int, error) {
|
||||
if src == nil {
|
||||
return nil, 0, nil
|
||||
}
|
||||
a, err := src.MarshalJSON()
|
||||
a, err := json.MarshalEscaped(src, options.EscapeHTML)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
@@ -243,7 +225,17 @@ func deepCopy(src *lazyNode) (*lazyNode, int, error) {
|
||||
return newLazyNode(newRawMessage(a)), sz, nil
|
||||
}
|
||||
|
||||
func (n *lazyNode) intoDoc() (*partialDoc, error) {
|
||||
func (n *lazyNode) nextByte() byte {
|
||||
s := []byte(*n.raw)
|
||||
|
||||
for unicode.IsSpace(rune(s[0])) {
|
||||
s = s[1:]
|
||||
}
|
||||
|
||||
return s[0]
|
||||
}
|
||||
|
||||
func (n *lazyNode) intoDoc(options *ApplyOptions) (*partialDoc, error) {
|
||||
if n.which == eDoc {
|
||||
return n.doc, nil
|
||||
}
|
||||
@@ -252,8 +244,17 @@ func (n *lazyNode) intoDoc() (*partialDoc, error) {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
|
||||
err := json.Unmarshal(*n.raw, &n.doc)
|
||||
if n.nextByte() != '{' {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
|
||||
err := unmarshal(*n.raw, &n.doc)
|
||||
|
||||
if n.doc == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
|
||||
n.doc.opts = options
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -264,21 +265,21 @@ func (n *lazyNode) intoDoc() (*partialDoc, error) {
|
||||
|
||||
func (n *lazyNode) intoAry() (*partialArray, error) {
|
||||
if n.which == eAry {
|
||||
return &n.ary, nil
|
||||
return n.ary, nil
|
||||
}
|
||||
|
||||
if n.raw == nil {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
|
||||
err := json.Unmarshal(*n.raw, &n.ary)
|
||||
err := unmarshal(*n.raw, &n.ary)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
n.which = eAry
|
||||
return &n.ary, nil
|
||||
return n.ary, nil
|
||||
}
|
||||
|
||||
func (n *lazyNode) compact() []byte {
|
||||
@@ -302,12 +303,16 @@ func (n *lazyNode) tryDoc() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
err := json.Unmarshal(*n.raw, &n.doc)
|
||||
err := unmarshal(*n.raw, &n.doc)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n.doc == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
n.which = eDoc
|
||||
return true
|
||||
}
|
||||
@@ -317,7 +322,7 @@ func (n *lazyNode) tryAry() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
err := json.Unmarshal(*n.raw, &n.ary)
|
||||
err := unmarshal(*n.raw, &n.ary)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -327,6 +332,18 @@ func (n *lazyNode) tryAry() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *lazyNode) isNull() bool {
|
||||
if n == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if n.raw == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return bytes.Equal(n.compact(), rawJSONNull)
|
||||
}
|
||||
|
||||
func (n *lazyNode) equal(o *lazyNode) bool {
|
||||
if n.which == eRaw {
|
||||
if !n.tryDoc() && !n.tryAry() {
|
||||
@@ -334,7 +351,27 @@ func (n *lazyNode) equal(o *lazyNode) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return bytes.Equal(n.compact(), o.compact())
|
||||
nc := n.compact()
|
||||
oc := o.compact()
|
||||
|
||||
if nc[0] == '"' && oc[0] == '"' {
|
||||
// ok, 2 strings
|
||||
|
||||
var ns, os string
|
||||
|
||||
err := json.UnmarshalValid(nc, &ns)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
err = json.UnmarshalValid(oc, &os)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return ns == os
|
||||
}
|
||||
|
||||
return bytes.Equal(nc, oc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,12 +417,12 @@ func (n *lazyNode) equal(o *lazyNode) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(n.ary) != len(o.ary) {
|
||||
if len(n.ary.nodes) != len(o.ary.nodes) {
|
||||
return false
|
||||
}
|
||||
|
||||
for idx, val := range n.ary {
|
||||
if !val.equal(o.ary[idx]) {
|
||||
for idx, val := range n.ary.nodes {
|
||||
if !val.equal(o.ary.nodes[idx]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -398,7 +435,7 @@ func (o Operation) Kind() string {
|
||||
if obj, ok := o["op"]; ok && obj != nil {
|
||||
var op string
|
||||
|
||||
err := json.Unmarshal(*obj, &op)
|
||||
err := unmarshal(*obj, &op)
|
||||
|
||||
if err != nil {
|
||||
return "unknown"
|
||||
@@ -415,7 +452,7 @@ func (o Operation) Path() (string, error) {
|
||||
if obj, ok := o["path"]; ok && obj != nil {
|
||||
var op string
|
||||
|
||||
err := json.Unmarshal(*obj, &op)
|
||||
err := unmarshal(*obj, &op)
|
||||
|
||||
if err != nil {
|
||||
return "unknown", err
|
||||
@@ -432,7 +469,7 @@ func (o Operation) From() (string, error) {
|
||||
if obj, ok := o["from"]; ok && obj != nil {
|
||||
var op string
|
||||
|
||||
err := json.Unmarshal(*obj, &op)
|
||||
err := unmarshal(*obj, &op)
|
||||
|
||||
if err != nil {
|
||||
return "unknown", err
|
||||
@@ -446,6 +483,10 @@ func (o Operation) From() (string, error) {
|
||||
|
||||
func (o Operation) value() *lazyNode {
|
||||
if obj, ok := o["value"]; ok {
|
||||
// A `null` gets decoded as a nil RawMessage, so let's fix it up here.
|
||||
if obj == nil {
|
||||
return newLazyNode(newRawMessage(rawJSONNull))
|
||||
}
|
||||
return newLazyNode(obj)
|
||||
}
|
||||
|
||||
@@ -461,7 +502,7 @@ func (o Operation) ValueInterface() (interface{}, error) {
|
||||
|
||||
var v interface{}
|
||||
|
||||
err := json.Unmarshal(*obj, &v)
|
||||
err := unmarshal(*obj, &v)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -497,6 +538,9 @@ func findObject(pd *container, path string, options *ApplyOptions) (container, s
|
||||
split := strings.Split(path, "/")
|
||||
|
||||
if len(split) < 2 {
|
||||
if path == "" {
|
||||
return doc, ""
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
@@ -521,7 +565,7 @@ func findObject(pd *container, path string, options *ApplyOptions) (container, s
|
||||
return nil, ""
|
||||
}
|
||||
} else {
|
||||
doc, err = next.intoDoc()
|
||||
doc, err = next.intoDoc(options)
|
||||
|
||||
if err != nil {
|
||||
return nil, ""
|
||||
@@ -533,6 +577,10 @@ func findObject(pd *container, path string, options *ApplyOptions) (container, s
|
||||
}
|
||||
|
||||
func (d *partialDoc) set(key string, val *lazyNode, options *ApplyOptions) error {
|
||||
if d.obj == nil {
|
||||
return ErrExpectedObject
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, k := range d.keys {
|
||||
if k == key {
|
||||
@@ -552,6 +600,14 @@ func (d *partialDoc) add(key string, val *lazyNode, options *ApplyOptions) error
|
||||
}
|
||||
|
||||
func (d *partialDoc) get(key string, options *ApplyOptions) (*lazyNode, error) {
|
||||
if key == "" {
|
||||
return d.self, nil
|
||||
}
|
||||
|
||||
if d.obj == nil {
|
||||
return nil, ErrExpectedObject
|
||||
}
|
||||
|
||||
v, ok := d.obj[key]
|
||||
if !ok {
|
||||
return v, errors.Wrapf(ErrMissing, "unable to get nonexistent key: %s", key)
|
||||
@@ -560,6 +616,10 @@ func (d *partialDoc) get(key string, options *ApplyOptions) (*lazyNode, error) {
|
||||
}
|
||||
|
||||
func (d *partialDoc) remove(key string, options *ApplyOptions) error {
|
||||
if d.obj == nil {
|
||||
return ErrExpectedObject
|
||||
}
|
||||
|
||||
_, ok := d.obj[key]
|
||||
if !ok {
|
||||
if options.AllowMissingPathOnRemove {
|
||||
@@ -591,19 +651,19 @@ func (d *partialArray) set(key string, val *lazyNode, options *ApplyOptions) err
|
||||
if !options.SupportNegativeIndices {
|
||||
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
if idx < -len(*d) {
|
||||
if idx < -len(d.nodes) {
|
||||
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
idx += len(*d)
|
||||
idx += len(d.nodes)
|
||||
}
|
||||
|
||||
(*d)[idx] = val
|
||||
d.nodes[idx] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *partialArray) add(key string, val *lazyNode, options *ApplyOptions) error {
|
||||
if key == "-" {
|
||||
*d = append(*d, val)
|
||||
d.nodes = append(d.nodes, val)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -612,11 +672,11 @@ func (d *partialArray) add(key string, val *lazyNode, options *ApplyOptions) err
|
||||
return errors.Wrapf(err, "value was not a proper array index: '%s'", key)
|
||||
}
|
||||
|
||||
sz := len(*d) + 1
|
||||
sz := len(d.nodes) + 1
|
||||
|
||||
ary := make([]*lazyNode, sz)
|
||||
|
||||
cur := *d
|
||||
cur := d
|
||||
|
||||
if idx >= len(ary) {
|
||||
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
@@ -632,15 +692,19 @@ func (d *partialArray) add(key string, val *lazyNode, options *ApplyOptions) err
|
||||
idx += len(ary)
|
||||
}
|
||||
|
||||
copy(ary[0:idx], cur[0:idx])
|
||||
copy(ary[0:idx], cur.nodes[0:idx])
|
||||
ary[idx] = val
|
||||
copy(ary[idx+1:], cur[idx:])
|
||||
copy(ary[idx+1:], cur.nodes[idx:])
|
||||
|
||||
*d = ary
|
||||
d.nodes = ary
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *partialArray) get(key string, options *ApplyOptions) (*lazyNode, error) {
|
||||
if key == "" {
|
||||
return d.self, nil
|
||||
}
|
||||
|
||||
idx, err := strconv.Atoi(key)
|
||||
|
||||
if err != nil {
|
||||
@@ -651,17 +715,17 @@ func (d *partialArray) get(key string, options *ApplyOptions) (*lazyNode, error)
|
||||
if !options.SupportNegativeIndices {
|
||||
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
if idx < -len(*d) {
|
||||
if idx < -len(d.nodes) {
|
||||
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
idx += len(*d)
|
||||
idx += len(d.nodes)
|
||||
}
|
||||
|
||||
if idx >= len(*d) {
|
||||
if idx >= len(d.nodes) {
|
||||
return nil, errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
|
||||
return (*d)[idx], nil
|
||||
return d.nodes[idx], nil
|
||||
}
|
||||
|
||||
func (d *partialArray) remove(key string, options *ApplyOptions) error {
|
||||
@@ -670,9 +734,9 @@ func (d *partialArray) remove(key string, options *ApplyOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cur := *d
|
||||
cur := d
|
||||
|
||||
if idx >= len(cur) {
|
||||
if idx >= len(cur.nodes) {
|
||||
if options.AllowMissingPathOnRemove {
|
||||
return nil
|
||||
}
|
||||
@@ -683,21 +747,21 @@ func (d *partialArray) remove(key string, options *ApplyOptions) error {
|
||||
if !options.SupportNegativeIndices {
|
||||
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
if idx < -len(cur) {
|
||||
if idx < -len(cur.nodes) {
|
||||
if options.AllowMissingPathOnRemove {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(ErrInvalidIndex, "Unable to access invalid index: %d", idx)
|
||||
}
|
||||
idx += len(cur)
|
||||
idx += len(cur.nodes)
|
||||
}
|
||||
|
||||
ary := make([]*lazyNode, len(cur)-1)
|
||||
ary := make([]*lazyNode, len(cur.nodes)-1)
|
||||
|
||||
copy(ary[0:idx], cur[0:idx])
|
||||
copy(ary[idx:], cur[idx+1:])
|
||||
copy(ary[0:idx], cur.nodes[0:idx])
|
||||
copy(ary[idx:], cur.nodes[idx+1:])
|
||||
|
||||
*d = ary
|
||||
d.nodes = ary
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -707,6 +771,33 @@ func (p Patch) add(doc *container, op Operation, options *ApplyOptions) error {
|
||||
return errors.Wrapf(ErrMissing, "add operation failed to decode path")
|
||||
}
|
||||
|
||||
// special case, adding to empty means replacing the container with the value given
|
||||
if path == "" {
|
||||
val := op.value()
|
||||
|
||||
var pd container
|
||||
if (*val.raw)[0] == '[' {
|
||||
pd = &partialArray{
|
||||
self: val,
|
||||
}
|
||||
} else {
|
||||
pd = &partialDoc{
|
||||
self: val,
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
err := json.UnmarshalValid(*val.raw, pd)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*doc = pd
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if options.EnsurePathExistsOnAdd {
|
||||
err = ensurePathExists(doc, path, options)
|
||||
|
||||
@@ -762,9 +853,9 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
|
||||
if arrIndex, err = strconv.Atoi(part); err == nil {
|
||||
pa, ok := doc.(*partialArray)
|
||||
|
||||
if ok && arrIndex >= len(*pa)+1 {
|
||||
if ok && arrIndex >= len(pa.nodes)+1 {
|
||||
// Pad the array with null values up to the required index.
|
||||
for i := len(*pa); i <= arrIndex-1; i++ {
|
||||
for i := len(pa.nodes); i <= arrIndex-1; i++ {
|
||||
doc.add(strconv.Itoa(i), newLazyNode(newRawMessage(rawJSONNull)), options)
|
||||
}
|
||||
}
|
||||
@@ -798,7 +889,10 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
|
||||
newNode := newLazyNode(newRawMessage(rawJSONObject))
|
||||
|
||||
doc.add(part, newNode, options)
|
||||
doc, _ = newNode.intoDoc()
|
||||
doc, err = newNode.intoDoc(options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if isArray(*target.raw) {
|
||||
@@ -808,7 +902,7 @@ func ensurePathExists(pd *container, path string, options *ApplyOptions) error {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
doc, err = target.intoDoc()
|
||||
doc, err = target.intoDoc(options)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -894,12 +988,14 @@ func (p Patch) replace(doc *container, op Operation, options *ApplyOptions) erro
|
||||
if !val.tryAry() {
|
||||
return errors.Wrapf(err, "replace operation value must be object or array")
|
||||
}
|
||||
} else {
|
||||
val.doc.opts = options
|
||||
}
|
||||
}
|
||||
|
||||
switch val.which {
|
||||
case eAry:
|
||||
*doc = &val.ary
|
||||
*doc = val.ary
|
||||
case eDoc:
|
||||
*doc = val.doc
|
||||
case eRaw:
|
||||
@@ -934,6 +1030,10 @@ func (p Patch) move(doc *container, op Operation, options *ApplyOptions) error {
|
||||
return errors.Wrapf(err, "move operation failed to decode from")
|
||||
}
|
||||
|
||||
if from == "" {
|
||||
return errors.Wrapf(ErrInvalid, "unable to move entire document to another path")
|
||||
}
|
||||
|
||||
con, key := findObject(doc, from, options)
|
||||
|
||||
if con == nil {
|
||||
@@ -983,7 +1083,7 @@ func (p Patch) test(doc *container, op Operation, options *ApplyOptions) error {
|
||||
self.doc = sv
|
||||
self.which = eDoc
|
||||
case *partialArray:
|
||||
self.ary = *sv
|
||||
self.ary = sv
|
||||
self.which = eAry
|
||||
}
|
||||
|
||||
@@ -1005,12 +1105,14 @@ func (p Patch) test(doc *container, op Operation, options *ApplyOptions) error {
|
||||
return errors.Wrapf(err, "error in test for path: '%s'", path)
|
||||
}
|
||||
|
||||
ov := op.value()
|
||||
|
||||
if val == nil {
|
||||
if op.value() == nil || op.value().raw == nil {
|
||||
if ov.isNull() {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
|
||||
} else if op.value() == nil {
|
||||
} else if ov.isNull() {
|
||||
return errors.Wrapf(ErrTestFailed, "testing value %s failed", path)
|
||||
}
|
||||
|
||||
@@ -1030,7 +1132,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64, op
|
||||
con, key := findObject(doc, from, options)
|
||||
|
||||
if con == nil {
|
||||
return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: %s", from)
|
||||
return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing from path: \"%s\"", from)
|
||||
}
|
||||
|
||||
val, err := con.get(key, options)
|
||||
@@ -1049,7 +1151,7 @@ func (p Patch) copy(doc *container, op Operation, accumulatedCopySize *int64, op
|
||||
return errors.Wrapf(ErrMissing, "copy operation does not apply: doc is missing destination path: %s", path)
|
||||
}
|
||||
|
||||
valCopy, sz, err := deepCopy(val)
|
||||
valCopy, sz, err := deepCopy(val, options)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error while performing deep copy")
|
||||
}
|
||||
@@ -1077,9 +1179,13 @@ func Equal(a, b []byte) bool {
|
||||
|
||||
// DecodePatch decodes the passed JSON document as an RFC 6902 patch.
|
||||
func DecodePatch(buf []byte) (Patch, error) {
|
||||
if !json.Valid(buf) {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
|
||||
var p Patch
|
||||
|
||||
err := json.Unmarshal(buf, &p)
|
||||
err := unmarshal(buf, &p)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1117,14 +1223,26 @@ func (p Patch) ApplyIndentWithOptions(doc []byte, indent string, options *ApplyO
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
var pd container
|
||||
if doc[0] == '[' {
|
||||
pd = &partialArray{}
|
||||
} else {
|
||||
pd = &partialDoc{}
|
||||
if !json.Valid(doc) {
|
||||
return nil, ErrInvalid
|
||||
}
|
||||
|
||||
err := json.Unmarshal(doc, pd)
|
||||
raw := json.RawMessage(doc)
|
||||
self := newLazyNode(&raw)
|
||||
|
||||
var pd container
|
||||
if doc[0] == '[' {
|
||||
pd = &partialArray{
|
||||
self: self,
|
||||
}
|
||||
} else {
|
||||
pd = &partialDoc{
|
||||
self: self,
|
||||
opts: options,
|
||||
}
|
||||
}
|
||||
|
||||
err := unmarshal(doc, pd)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1157,11 +1275,18 @@ func (p Patch) ApplyIndentWithOptions(doc []byte, indent string, options *ApplyO
|
||||
}
|
||||
}
|
||||
|
||||
if indent != "" {
|
||||
return json.MarshalIndent(pd, "", indent)
|
||||
data, err := json.MarshalEscaped(pd, options.EscapeHTML)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(pd)
|
||||
if indent == "" {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
json.Indent(&buf, data, "", indent)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// From http://tools.ietf.org/html/rfc6901#section-4 :
|
||||
|
Reference in New Issue
Block a user