diff options
author | Ian Lance Taylor <iant@golang.org> | 2022-03-18 12:14:20 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2022-03-28 22:06:49 +0000 |
commit | 32fdad19a246143ae4f194d1b39886d778de1380 (patch) | |
tree | 72e204d9e129ad64c328fd3fff9eb51058919884 /src/bytes | |
parent | 460fd63cccd2f1d16fc4b1b761545b1649e14e28 (diff) | |
download | go-32fdad19a246143ae4f194d1b39886d778de1380.tar.gz go-32fdad19a246143ae4f194d1b39886d778de1380.zip |
bytes: restore old Trim/TrimLeft behavior for nil
Keep returning nil for the cases where we historically returned nil,
even though this is slightly different for TrimLeft and TrimRight.
Fixes #51793
Change-Id: Ifbdfc6b09d52b8e063cfe6341019f9b2eb8b70e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/393876
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/bytes')
-rw-r--r-- | src/bytes/bytes.go | 24 | ||||
-rw-r--r-- | src/bytes/bytes_test.go | 93 |
2 files changed, 106 insertions, 11 deletions
diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 41323ad549..e3dab4d035 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -909,7 +909,11 @@ func containsRune(s string, r rune) bool { // Trim returns a subslice of s by slicing off all leading and // trailing UTF-8-encoded code points contained in cutset. func Trim(s []byte, cutset string) []byte { - if len(s) == 0 || cutset == "" { + if len(s) == 0 { + // This is what we've historically done. + return nil + } + if cutset == "" { return s } if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { @@ -924,7 +928,11 @@ func Trim(s []byte, cutset string) []byte { // TrimLeft returns a subslice of s by slicing off all leading // UTF-8-encoded code points contained in cutset. func TrimLeft(s []byte, cutset string) []byte { - if len(s) == 0 || cutset == "" { + if len(s) == 0 { + // This is what we've historically done. + return nil + } + if cutset == "" { return s } if len(cutset) == 1 && cutset[0] < utf8.RuneSelf { @@ -940,6 +948,10 @@ func trimLeftByte(s []byte, c byte) []byte { for len(s) > 0 && s[0] == c { s = s[1:] } + if len(s) == 0 { + // This is what we've historically done. + return nil + } return s } @@ -950,6 +962,10 @@ func trimLeftASCII(s []byte, as *asciiSet) []byte { } s = s[1:] } + if len(s) == 0 { + // This is what we've historically done. + return nil + } return s } @@ -964,6 +980,10 @@ func trimLeftUnicode(s []byte, cutset string) []byte { } s = s[n:] } + if len(s) == 0 { + // This is what we've historically done. + return nil + } return s } diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 3bece6adf0..2e6ab31540 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -1278,24 +1278,69 @@ var trimTests = []TrimTest{ {"TrimSuffix", "aabb", "b", "aab"}, } +type TrimNilTest struct { + f string + in []byte + arg string + out []byte +} + +var trimNilTests = []TrimNilTest{ + {"Trim", nil, "", nil}, + {"Trim", []byte{}, "", nil}, + {"Trim", []byte{'a'}, "a", nil}, + {"Trim", []byte{'a', 'a'}, "a", nil}, + {"Trim", []byte{'a'}, "ab", nil}, + {"Trim", []byte{'a', 'b'}, "ab", nil}, + {"Trim", []byte("☺"), "☺", nil}, + {"TrimLeft", nil, "", nil}, + {"TrimLeft", []byte{}, "", nil}, + {"TrimLeft", []byte{'a'}, "a", nil}, + {"TrimLeft", []byte{'a', 'a'}, "a", nil}, + {"TrimLeft", []byte{'a'}, "ab", nil}, + {"TrimLeft", []byte{'a', 'b'}, "ab", nil}, + {"TrimLeft", []byte("☺"), "☺", nil}, + {"TrimRight", nil, "", nil}, + {"TrimRight", []byte{}, "", []byte{}}, + {"TrimRight", []byte{'a'}, "a", []byte{}}, + {"TrimRight", []byte{'a', 'a'}, "a", []byte{}}, + {"TrimRight", []byte{'a'}, "ab", []byte{}}, + {"TrimRight", []byte{'a', 'b'}, "ab", []byte{}}, + {"TrimRight", []byte("☺"), "☺", []byte{}}, + {"TrimPrefix", nil, "", nil}, + {"TrimPrefix", []byte{}, "", []byte{}}, + {"TrimPrefix", []byte{'a'}, "a", []byte{}}, + {"TrimPrefix", []byte("☺"), "☺", []byte{}}, + {"TrimSuffix", nil, "", nil}, + {"TrimSuffix", []byte{}, "", []byte{}}, + {"TrimSuffix", []byte{'a'}, "a", []byte{}}, + {"TrimSuffix", []byte("☺"), "☺", []byte{}}, +} + func TestTrim(t *testing.T) { - for _, tc := range trimTests { - name := tc.f - var f func([]byte, string) []byte - var fb func([]byte, []byte) []byte + toFn := func(name string) (func([]byte, string) []byte, func([]byte, []byte) []byte) { switch name { case "Trim": - f = Trim + return Trim, nil case "TrimLeft": - f = TrimLeft + return TrimLeft, nil case "TrimRight": - f = TrimRight + return TrimRight, nil case "TrimPrefix": - fb = TrimPrefix + return nil, TrimPrefix case "TrimSuffix": - fb = TrimSuffix + return nil, TrimSuffix default: t.Errorf("Undefined trim function %s", name) + return nil, nil + } + } + + for _, tc := range trimTests { + name := tc.f + f, fb := toFn(name) + if f == nil && fb == nil { + continue } var actual string if f != nil { @@ -1307,6 +1352,36 @@ func TestTrim(t *testing.T) { t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out) } } + + for _, tc := range trimNilTests { + name := tc.f + f, fb := toFn(name) + if f == nil && fb == nil { + continue + } + var actual []byte + if f != nil { + actual = f(tc.in, tc.arg) + } else { + actual = fb(tc.in, []byte(tc.arg)) + } + report := func(s []byte) string { + if s == nil { + return "nil" + } else { + return fmt.Sprintf("%q", s) + } + } + if len(actual) != 0 { + t.Errorf("%s(%s, %q) returned non-empty value", name, report(tc.in), tc.arg) + } else { + actualNil := actual == nil + outNil := tc.out == nil + if actualNil != outNil { + t.Errorf("%s(%s, %q) got nil %t; want nil %t", name, report(tc.in), tc.arg, actualNil, outNil) + } + } + } } type predicate struct { |