aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/evanphx/json-patch/patch.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/evanphx/json-patch/patch.go')
-rw-r--r--vendor/github.com/evanphx/json-patch/patch.go682
1 files changed, 0 insertions, 682 deletions
diff --git a/vendor/github.com/evanphx/json-patch/patch.go b/vendor/github.com/evanphx/json-patch/patch.go
deleted file mode 100644
index f26b6824b..000000000
--- a/vendor/github.com/evanphx/json-patch/patch.go
+++ /dev/null
@@ -1,682 +0,0 @@
-package jsonpatch
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "strconv"
- "strings"
-)
-
-const (
- eRaw = iota
- eDoc
- eAry
-)
-
-var SupportNegativeIndices bool = true
-
-type lazyNode struct {
- raw *json.RawMessage
- doc partialDoc
- ary partialArray
- which int
-}
-
-type operation map[string]*json.RawMessage
-
-// Patch is an ordered collection of operations.
-type Patch []operation
-
-type partialDoc map[string]*lazyNode
-type partialArray []*lazyNode
-
-type container interface {
- get(key string) (*lazyNode, error)
- set(key string, val *lazyNode) error
- add(key string, val *lazyNode) error
- remove(key string) error
-}
-
-func newLazyNode(raw *json.RawMessage) *lazyNode {
- return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw}
-}
-
-func (n *lazyNode) MarshalJSON() ([]byte, error) {
- switch n.which {
- case eRaw:
- return json.Marshal(n.raw)
- case eDoc:
- return json.Marshal(n.doc)
- case eAry:
- return json.Marshal(n.ary)
- default:
- return nil, fmt.Errorf("Unknown type")
- }
-}
-
-func (n *lazyNode) UnmarshalJSON(data []byte) error {
- dest := make(json.RawMessage, len(data))
- copy(dest, data)
- n.raw = &dest
- n.which = eRaw
- return nil
-}
-
-func (n *lazyNode) intoDoc() (*partialDoc, error) {
- if n.which == eDoc {
- return &n.doc, nil
- }
-
- if n.raw == nil {
- return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial document")
- }
-
- err := json.Unmarshal(*n.raw, &n.doc)
-
- if err != nil {
- return nil, err
- }
-
- n.which = eDoc
- return &n.doc, nil
-}
-
-func (n *lazyNode) intoAry() (*partialArray, error) {
- if n.which == eAry {
- return &n.ary, nil
- }
-
- if n.raw == nil {
- return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial array")
- }
-
- err := json.Unmarshal(*n.raw, &n.ary)
-
- if err != nil {
- return nil, err
- }
-
- n.which = eAry
- return &n.ary, nil
-}
-
-func (n *lazyNode) compact() []byte {
- buf := &bytes.Buffer{}
-
- if n.raw == nil {
- return nil
- }
-
- err := json.Compact(buf, *n.raw)
-
- if err != nil {
- return *n.raw
- }
-
- return buf.Bytes()
-}
-
-func (n *lazyNode) tryDoc() bool {
- if n.raw == nil {
- return false
- }
-
- err := json.Unmarshal(*n.raw, &n.doc)
-
- if err != nil {
- return false
- }
-
- n.which = eDoc
- return true
-}
-
-func (n *lazyNode) tryAry() bool {
- if n.raw == nil {
- return false
- }
-
- err := json.Unmarshal(*n.raw, &n.ary)
-
- if err != nil {
- return false
- }
-
- n.which = eAry
- return true
-}
-
-func (n *lazyNode) equal(o *lazyNode) bool {
- if n.which == eRaw {
- if !n.tryDoc() && !n.tryAry() {
- if o.which != eRaw {
- return false
- }
-
- return bytes.Equal(n.compact(), o.compact())
- }
- }
-
- if n.which == eDoc {
- if o.which == eRaw {
- if !o.tryDoc() {
- return false
- }
- }
-
- if o.which != eDoc {
- return false
- }
-
- for k, v := range n.doc {
- ov, ok := o.doc[k]
-
- if !ok {
- return false
- }
-
- if v == nil && ov == nil {
- continue
- }
-
- if !v.equal(ov) {
- return false
- }
- }
-
- return true
- }
-
- if o.which != eAry && !o.tryAry() {
- return false
- }
-
- if len(n.ary) != len(o.ary) {
- return false
- }
-
- for idx, val := range n.ary {
- if !val.equal(o.ary[idx]) {
- return false
- }
- }
-
- return true
-}
-
-func (o operation) kind() string {
- if obj, ok := o["op"]; ok && obj != nil {
- var op string
-
- err := json.Unmarshal(*obj, &op)
-
- if err != nil {
- return "unknown"
- }
-
- return op
- }
-
- return "unknown"
-}
-
-func (o operation) path() string {
- if obj, ok := o["path"]; ok && obj != nil {
- var op string
-
- err := json.Unmarshal(*obj, &op)
-
- if err != nil {
- return "unknown"
- }
-
- return op
- }
-
- return "unknown"
-}
-
-func (o operation) from() string {
- if obj, ok := o["from"]; ok && obj != nil {
- var op string
-
- err := json.Unmarshal(*obj, &op)
-
- if err != nil {
- return "unknown"
- }
-
- return op
- }
-
- return "unknown"
-}
-
-func (o operation) value() *lazyNode {
- if obj, ok := o["value"]; ok {
- return newLazyNode(obj)
- }
-
- return nil
-}
-
-func isArray(buf []byte) bool {
-Loop:
- for _, c := range buf {
- switch c {
- case ' ':
- case '\n':
- case '\t':
- continue
- case '[':
- return true
- default:
- break Loop
- }
- }
-
- return false
-}
-
-func findObject(pd *container, path string) (container, string) {
- doc := *pd
-
- split := strings.Split(path, "/")
-
- if len(split) < 2 {
- return nil, ""
- }
-
- parts := split[1 : len(split)-1]
-
- key := split[len(split)-1]
-
- var err error
-
- for _, part := range parts {
-
- next, ok := doc.get(decodePatchKey(part))
-
- if next == nil || ok != nil {
- return nil, ""
- }
-
- if isArray(*next.raw) {
- doc, err = next.intoAry()
-
- if err != nil {
- return nil, ""
- }
- } else {
- doc, err = next.intoDoc()
-
- if err != nil {
- return nil, ""
- }
- }
- }
-
- return doc, decodePatchKey(key)
-}
-
-func (d *partialDoc) set(key string, val *lazyNode) error {
- (*d)[key] = val
- return nil
-}
-
-func (d *partialDoc) add(key string, val *lazyNode) error {
- (*d)[key] = val
- return nil
-}
-
-func (d *partialDoc) get(key string) (*lazyNode, error) {
- return (*d)[key], nil
-}
-
-func (d *partialDoc) remove(key string) error {
- _, ok := (*d)[key]
- if !ok {
- return fmt.Errorf("Unable to remove nonexistent key: %s", key)
- }
-
- delete(*d, key)
- return nil
-}
-
-func (d *partialArray) set(key string, val *lazyNode) error {
- if key == "-" {
- *d = append(*d, val)
- return nil
- }
-
- idx, err := strconv.Atoi(key)
- if err != nil {
- return err
- }
-
- sz := len(*d)
- if idx+1 > sz {
- sz = idx + 1
- }
-
- ary := make([]*lazyNode, sz)
-
- cur := *d
-
- copy(ary, cur)
-
- if idx >= len(ary) {
- return fmt.Errorf("Unable to access invalid index: %d", idx)
- }
-
- ary[idx] = val
-
- *d = ary
- return nil
-}
-
-func (d *partialArray) add(key string, val *lazyNode) error {
- if key == "-" {
- *d = append(*d, val)
- return nil
- }
-
- idx, err := strconv.Atoi(key)
- if err != nil {
- return err
- }
-
- ary := make([]*lazyNode, len(*d)+1)
-
- cur := *d
-
- if idx >= len(ary) {
- return fmt.Errorf("Unable to access invalid index: %d", idx)
- }
-
- if SupportNegativeIndices {
- if idx < -len(ary) {
- return fmt.Errorf("Unable to access invalid index: %d", idx)
- }
-
- if idx < 0 {
- idx += len(ary)
- }
- }
-
- copy(ary[0:idx], cur[0:idx])
- ary[idx] = val
- copy(ary[idx+1:], cur[idx:])
-
- *d = ary
- return nil
-}
-
-func (d *partialArray) get(key string) (*lazyNode, error) {
- idx, err := strconv.Atoi(key)
-
- if err != nil {
- return nil, err
- }
-
- if idx >= len(*d) {
- return nil, fmt.Errorf("Unable to access invalid index: %d", idx)
- }
-
- return (*d)[idx], nil
-}
-
-func (d *partialArray) remove(key string) error {
- idx, err := strconv.Atoi(key)
- if err != nil {
- return err
- }
-
- cur := *d
-
- if idx >= len(cur) {
- return fmt.Errorf("Unable to access invalid index: %d", idx)
- }
-
- if SupportNegativeIndices {
- if idx < -len(cur) {
- return fmt.Errorf("Unable to access invalid index: %d", idx)
- }
-
- if idx < 0 {
- idx += len(cur)
- }
- }
-
- ary := make([]*lazyNode, len(cur)-1)
-
- copy(ary[0:idx], cur[0:idx])
- copy(ary[idx:], cur[idx+1:])
-
- *d = ary
- return nil
-
-}
-
-func (p Patch) add(doc *container, op operation) error {
- path := op.path()
-
- con, key := findObject(doc, path)
-
- if con == nil {
- return fmt.Errorf("jsonpatch add operation does not apply: doc is missing path: \"%s\"", path)
- }
-
- return con.add(key, op.value())
-}
-
-func (p Patch) remove(doc *container, op operation) error {
- path := op.path()
-
- con, key := findObject(doc, path)
-
- if con == nil {
- return fmt.Errorf("jsonpatch remove operation does not apply: doc is missing path: \"%s\"", path)
- }
-
- return con.remove(key)
-}
-
-func (p Patch) replace(doc *container, op operation) error {
- path := op.path()
-
- con, key := findObject(doc, path)
-
- if con == nil {
- return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing path: %s", path)
- }
-
- _, ok := con.get(key)
- if ok != nil {
- return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing key: %s", path)
- }
-
- return con.set(key, op.value())
-}
-
-func (p Patch) move(doc *container, op operation) error {
- from := op.from()
-
- con, key := findObject(doc, from)
-
- if con == nil {
- return fmt.Errorf("jsonpatch move operation does not apply: doc is missing from path: %s", from)
- }
-
- val, err := con.get(key)
- if err != nil {
- return err
- }
-
- err = con.remove(key)
- if err != nil {
- return err
- }
-
- path := op.path()
-
- con, key = findObject(doc, path)
-
- if con == nil {
- return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path)
- }
-
- return con.set(key, val)
-}
-
-func (p Patch) test(doc *container, op operation) error {
- path := op.path()
-
- con, key := findObject(doc, path)
-
- if con == nil {
- return fmt.Errorf("jsonpatch test operation does not apply: is missing path: %s", path)
- }
-
- val, err := con.get(key)
-
- if err != nil {
- return err
- }
-
- if val == nil {
- if op.value().raw == nil {
- return nil
- }
- return fmt.Errorf("Testing value %s failed", path)
- } else if op.value() == nil {
- return fmt.Errorf("Testing value %s failed", path)
- }
-
- if val.equal(op.value()) {
- return nil
- }
-
- return fmt.Errorf("Testing value %s failed", path)
-}
-
-func (p Patch) copy(doc *container, op operation) error {
- from := op.from()
-
- con, key := findObject(doc, from)
-
- if con == nil {
- return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing from path: %s", from)
- }
-
- val, err := con.get(key)
- if err != nil {
- return err
- }
-
- path := op.path()
-
- con, key = findObject(doc, path)
-
- if con == nil {
- return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path)
- }
-
- return con.set(key, val)
-}
-
-// Equal indicates if 2 JSON documents have the same structural equality.
-func Equal(a, b []byte) bool {
- ra := make(json.RawMessage, len(a))
- copy(ra, a)
- la := newLazyNode(&ra)
-
- rb := make(json.RawMessage, len(b))
- copy(rb, b)
- lb := newLazyNode(&rb)
-
- return la.equal(lb)
-}
-
-// DecodePatch decodes the passed JSON document as an RFC 6902 patch.
-func DecodePatch(buf []byte) (Patch, error) {
- var p Patch
-
- err := json.Unmarshal(buf, &p)
-
- if err != nil {
- return nil, err
- }
-
- return p, nil
-}
-
-// Apply mutates a JSON document according to the patch, and returns the new
-// document.
-func (p Patch) Apply(doc []byte) ([]byte, error) {
- return p.ApplyIndent(doc, "")
-}
-
-// ApplyIndent mutates a JSON document according to the patch, and returns the new
-// document indented.
-func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
- var pd container
- if doc[0] == '[' {
- pd = &partialArray{}
- } else {
- pd = &partialDoc{}
- }
-
- err := json.Unmarshal(doc, pd)
-
- if err != nil {
- return nil, err
- }
-
- err = nil
-
- for _, op := range p {
- switch op.kind() {
- case "add":
- err = p.add(&pd, op)
- case "remove":
- err = p.remove(&pd, op)
- case "replace":
- err = p.replace(&pd, op)
- case "move":
- err = p.move(&pd, op)
- case "test":
- err = p.test(&pd, op)
- case "copy":
- err = p.copy(&pd, op)
- default:
- err = fmt.Errorf("Unexpected kind: %s", op.kind())
- }
-
- if err != nil {
- return nil, err
- }
- }
-
- if indent != "" {
- return json.MarshalIndent(pd, "", indent)
- }
-
- return json.Marshal(pd)
-}
-
-// From http://tools.ietf.org/html/rfc6901#section-4 :
-//
-// Evaluation of each reference token begins by decoding any escaped
-// character sequence. This is performed by first transforming any
-// occurrence of the sequence '~1' to '/', and then transforming any
-// occurrence of the sequence '~0' to '~'.
-
-var (
- rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
-)
-
-func decodePatchKey(k string) string {
- return rfc6901Decoder.Replace(k)
-}