From 192ac34193a53a9e17da43c354a7ee3b011d861d Mon Sep 17 00:00:00 2001 From: Benjamin Gandon Date: Mon, 20 Apr 2020 20:22:44 +0200 Subject: [PATCH 1/2] Support missing encoding: ~2 for '?' and ~3 for '=' --- patch/pointer.go | 13 ++++++------- patch/pointer_test.go | 7 +++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/patch/pointer.go b/patch/pointer.go index 4119449..bbb8ac9 100644 --- a/patch/pointer.go +++ b/patch/pointer.go @@ -7,8 +7,8 @@ import ( ) var ( - rfc6901Decoder = strings.NewReplacer("~0", "~", "~1", "/", "~7", ":") - rfc6901Encoder = strings.NewReplacer("~", "~0", "/", "~1", ":", "~7") + rfc6901Decoder = strings.NewReplacer("~0", "~", "~1", "/", "~2", "?", "~3", "=", "~7", ":") + rfc6901Encoder = strings.NewReplacer("~", "~0", "/", "~1", "?", "~2", "=", "~3", ":", "~7") ) // More or less based on https://tools.ietf.org/html/rfc6901 @@ -65,8 +65,6 @@ func NewPointerFromString(str string) (Pointer, error) { } } - tok = rfc6901Decoder.Replace(tok) - // parse as after last index if isLast && tok == "-" { if len(modifiers) > 0 { @@ -85,14 +83,15 @@ func NewPointerFromString(str string) (Pointer, error) { if strings.HasSuffix(tok, "?") { optional = true + tok = strings.TrimSuffix(tok, "?") } // parse name=val kv := strings.SplitN(tok, "=", 2) if len(kv) == 2 { token := MatchingIndexToken{ - Key: kv[0], - Value: strings.TrimSuffix(kv[1], "?"), + Key: rfc6901Decoder.Replace(kv[0]), + Value: rfc6901Decoder.Replace(kv[1]), Optional: optional, Modifiers: modifiers, } @@ -107,7 +106,7 @@ func NewPointerFromString(str string) (Pointer, error) { // it's a map key token := KeyToken{ - Key: strings.TrimSuffix(tok, "?"), + Key: rfc6901Decoder.Replace(tok), Optional: optional, } diff --git a/patch/pointer_test.go b/patch/pointer_test.go index 36c4aa2..c37beea 100644 --- a/patch/pointer_test.go +++ b/patch/pointer_test.go @@ -71,7 +71,7 @@ var testCases = []PointerTestCase{ {"/=?", []Token{RootToken{}, MatchingIndexToken{Key: "", Value: "", Optional: true}}}, {"/name=", []Token{RootToken{}, MatchingIndexToken{Key: "name", Value: ""}}}, {"/=val", []Token{RootToken{}, MatchingIndexToken{Key: "", Value: "val"}}}, - {"/==", []Token{RootToken{}, MatchingIndexToken{Key: "", Value: "="}}}, + {"/=~3", []Token{RootToken{}, MatchingIndexToken{Key: "", Value: "="}}}, {"/name=val:before", []Token{ RootToken{}, @@ -94,11 +94,14 @@ var testCases = []PointerTestCase{ KeyToken{Key: "key", Optional: true}, }}, - // Escaping (todo support ~2 for '?'; ~3 for '=') + // Escaping {"/m~0n", []Token{RootToken{}, KeyToken{Key: "m~n"}}}, {"/a~01b", []Token{RootToken{}, KeyToken{Key: "a~1b"}}}, {"/a~1b", []Token{RootToken{}, KeyToken{Key: "a/b"}}}, + {"/plip~2plop", []Token{RootToken{}, KeyToken{Key: "plip?plop"}}}, + {"/plop~36713", []Token{RootToken{}, KeyToken{Key: "plop=6713"}}}, {"/name~0n=val~0n", []Token{RootToken{}, MatchingIndexToken{Key: "name~n", Value: "val~n"}}}, + {"/name~1in~2question=key~3val", []Token{RootToken{}, MatchingIndexToken{Key: "name/in?question", Value: "key=val"}}}, {"/m~7n", []Token{RootToken{}, KeyToken{Key: "m:n"}}}, // Special chars From 82931bcab2e97d464dd0ed1a41c11d52ab4da61b Mon Sep 17 00:00:00 2001 From: Benjamin Gandon Date: Mon, 20 Apr 2020 20:33:41 +0200 Subject: [PATCH 2/2] Document escape sequences --- docs/examples.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/examples.md b/docs/examples.md index bae940a..22d1640 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -17,6 +17,13 @@ - array insertion could be affected via `:before` and `:after` +- Escaping special token is possible with `~` sequences: + - `~` is escaped `~0` + - `/` is escaped `~1` + - `?` is escaped `~2` + - `=` is escaped `~3` + - `:` is escaped `~7` + See pointer test examples in [patch/pointer_test.go](../patch/pointer_test.go). ## Operations