diff --git a/bytes.go b/bytes.go index dfe18d2..4f9e285 100644 --- a/bytes.go +++ b/bytes.go @@ -23,25 +23,35 @@ func arreq(a, b []string) bool { } func unescape(s string) string { - n := strings.Count(s, "~") if n == 0 { return s } - t := make([]byte, len(s)-n) // remove one char per ~ + t := make([]byte, len(s)-n+1) // remove one char per ~ w := 0 start := 0 for i := 0; i < n; i++ { j := start + strings.Index(s[start:], "~") w += copy(t[w:], s[start:j]) - switch s[j+1] { + if len(s) < j+2 { + t[w] = '~' + w++ + break + } + c := s[j+1] + switch c { case '0': t[w] = '~' w++ case '1': t[w] = '/' w++ + default: + t[w] = '~' + w++ + t[w] = c + w++ } start = j + 2 } diff --git a/bytes_test.go b/bytes_test.go index 3823cab..e741f05 100644 --- a/bytes_test.go +++ b/bytes_test.go @@ -428,6 +428,34 @@ func TestEscape(t *testing.T) { t.Errorf("unescape(escape(%q) [%q]) = %q", test, esc, got) } } + + tf := func(s chars) bool { + uns := unescape(string(s)) + got := string(escape(uns, nil)) + return got == string(s) + } + quick.Check(tf, nil) +} + +func TestUnescape(t *testing.T) { + tests := []struct { + in, exp string + }{ + {"", ""}, + {"/", "/"}, + {"/thing", "/thing"}, + {"~0", "~"}, + {"~1", "/"}, + {"~2", "~2"}, + {"~", "~"}, + {"thing~", "thing~"}, + } + for _, test := range tests { + got := string(unescape(test.in)) + if got != test.exp { + t.Errorf("on %q, got %q, wanted %q", test.in, got, test.exp) + } + } } var codeJSON []byte @@ -550,7 +578,6 @@ func oldunescape(s string) string { func TestNewEscaper(t *testing.T) { of := func(in chars) string { - t.Logf("Looking at %q", in) return oldunescape(string(in)) } nf := func(in chars) string {