]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.18] bytes: restore old Trim/TrimLeft behavior for nil
authorIan Lance Taylor <iant@golang.org>
Fri, 18 Mar 2022 19:14:20 +0000 (12:14 -0700)
committerHeschi Kreinick <heschi@google.com>
Wed, 30 Mar 2022 16:42:29 +0000 (16:42 +0000)
Keep returning nil for the cases where we historically returned nil,
even though this is slightly different for TrimLeft and TrimRight.

For #51793
Fixes #51796

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>
(cherry picked from commit 32fdad19a246143ae4f194d1b39886d778de1380)
Reviewed-on: https://go-review.googlesource.com/c/go/+/396294
Reviewed-by: Austin Clements <austin@google.com>
src/bytes/bytes.go
src/bytes/bytes_test.go

index 41323ad549bba92c5399dc071e8670de14053814..e3dab4d03560b85047a729e3bfce2a177e26fc9f 100644 (file)
@@ -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
 }
 
index 3bece6adf0b905b63f580db349c5ee0cf007b89b..2e6ab315404e8ca84367d2e6510571362970bce7 100644 (file)
@@ -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 {