]> Cypherpunks.ru repositories - gostls13.git/commitdiff
encoding: add AppendEncode and AppendDecode
authorJoe Tsai <joetsai@digital-static.net>
Mon, 20 Feb 2023 07:19:20 +0000 (23:19 -0800)
committerGopher Robot <gobot@golang.org>
Thu, 17 Aug 2023 16:23:42 +0000 (16:23 +0000)
Implement append-like equivalent of Encode and Decode functions.

Fixes #53693

Change-Id: I79d8d834e3c8f77fad32be2fd391e33d4d1527ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/504884
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Joseph Tsai <joetsai@digital-static.net>
Auto-Submit: Joseph Tsai <joetsai@digital-static.net>

api/next/53693.txt [new file with mode: 0644]
src/encoding/base32/base32.go
src/encoding/base32/base32_test.go
src/encoding/base64/base64.go
src/encoding/base64/base64_test.go
src/encoding/hex/hex.go
src/encoding/hex/hex_test.go
src/go/build/deps_test.go

diff --git a/api/next/53693.txt b/api/next/53693.txt
new file mode 100644 (file)
index 0000000..5a6f09e
--- /dev/null
@@ -0,0 +1,6 @@
+pkg encoding/base32, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
+pkg encoding/base32, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
+pkg encoding/base64, method (*Encoding) AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
+pkg encoding/base64, method (*Encoding) AppendEncode([]uint8, []uint8) []uint8 #53693
+pkg encoding/hex, func AppendDecode([]uint8, []uint8) ([]uint8, error) #53693
+pkg encoding/hex, func AppendEncode([]uint8, []uint8) []uint8 #53693
index 69ced9ca3c60452d9e9306a02cff9a071d007152..7cccbd17be3222f54a6cc6f3b26557d788a71a65 100644 (file)
@@ -7,6 +7,7 @@ package base32
 
 import (
        "io"
+       "slices"
        "strconv"
 )
 
@@ -176,6 +177,15 @@ func (enc *Encoding) Encode(dst, src []byte) {
        }
 }
 
+// AppendEncode appends the base32 encoded src to dst
+// and returns the extended buffer.
+func (enc *Encoding) AppendEncode(dst, src []byte) []byte {
+       n := enc.EncodedLen(len(src))
+       dst = slices.Grow(dst, n)
+       enc.Encode(dst[len(dst):][:n], src)
+       return dst[:len(dst)+n]
+}
+
 // EncodeToString returns the base32 encoding of src.
 func (enc *Encoding) EncodeToString(src []byte) string {
        buf := make([]byte, enc.EncodedLen(len(src)))
@@ -378,6 +388,16 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
        return
 }
 
+// AppendDecode appends the base32 decoded src to dst
+// and returns the extended buffer.
+// If the input is malformed, it returns the partially decoded src and an error.
+func (enc *Encoding) AppendDecode(dst, src []byte) ([]byte, error) {
+       n := enc.DecodedLen(len(src))
+       dst = slices.Grow(dst, n)
+       n, err := enc.Decode(dst[len(dst):][:n], src)
+       return dst[:len(dst)+n], err
+}
+
 // DecodeString returns the bytes represented by the base32 string s.
 func (enc *Encoding) DecodeString(s string) ([]byte, error) {
        buf := []byte(s)
index bdb9f0e61f86de98d57cb1b33e3cf1968661752d..0132744507502720da87d9c98c44d9157f535e4e 100644 (file)
@@ -57,6 +57,8 @@ func TestEncode(t *testing.T) {
        for _, p := range pairs {
                got := StdEncoding.EncodeToString([]byte(p.decoded))
                testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, p.encoded)
+               dst := StdEncoding.AppendEncode([]byte("lead"), []byte(p.decoded))
+               testEqual(t, `AppendEncode("lead", %q) = %q, want %q`, p.decoded, string(dst), "lead"+p.encoded)
        }
 }
 
@@ -99,13 +101,15 @@ func TestDecode(t *testing.T) {
                if len(p.encoded) > 0 {
                        testEqual(t, "Decode(%q) = end %v, want %v", p.encoded, end, (p.encoded[len(p.encoded)-1] == '='))
                }
-               testEqual(t, "Decode(%q) = %q, want %q", p.encoded,
-                       string(dbuf[0:count]),
-                       p.decoded)
+               testEqual(t, "Decode(%q) = %q, want %q", p.encoded, string(dbuf[0:count]), p.decoded)
 
                dbuf, err = StdEncoding.DecodeString(p.encoded)
                testEqual(t, "DecodeString(%q) = error %v, want %v", p.encoded, err, error(nil))
                testEqual(t, "DecodeString(%q) = %q, want %q", p.encoded, string(dbuf), p.decoded)
+
+               dst, err := StdEncoding.AppendDecode([]byte("lead"), []byte(p.encoded))
+               testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil))
+               testEqual(t, `AppendDecode("lead", %q) = %q, want %q`, p.encoded, string(dst), "lead"+p.decoded)
        }
 }
 
index 87f68970627baa477af5c01cd9e4eef750e02445..5db72b91e26d35749e02c338514b2cbfaedf7817 100644 (file)
@@ -8,6 +8,7 @@ package base64
 import (
        "encoding/binary"
        "io"
+       "slices"
        "strconv"
 )
 
@@ -191,6 +192,15 @@ func (enc *Encoding) Encode(dst, src []byte) {
        }
 }
 
+// AppendEncode appends the base64 encoded src to dst
+// and returns the extended buffer.
+func (enc *Encoding) AppendEncode(dst, src []byte) []byte {
+       n := enc.EncodedLen(len(src))
+       dst = slices.Grow(dst, n)
+       enc.Encode(dst[len(dst):][:n], src)
+       return dst[:len(dst)+n]
+}
+
 // EncodeToString returns the base64 encoding of src.
 func (enc *Encoding) EncodeToString(src []byte) string {
        buf := make([]byte, enc.EncodedLen(len(src)))
@@ -395,6 +405,16 @@ func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err err
        return si, dlen - 1, err
 }
 
+// AppendDecode appends the base64 decoded src to dst
+// and returns the extended buffer.
+// If the input is malformed, it returns the partially decoded src and an error.
+func (enc *Encoding) AppendDecode(dst, src []byte) ([]byte, error) {
+       n := enc.DecodedLen(len(src))
+       dst = slices.Grow(dst, n)
+       n, err := enc.Decode(dst[len(dst):][:n], src)
+       return dst[:len(dst)+n], err
+}
+
 // DecodeString returns the bytes represented by the base64 string s.
 func (enc *Encoding) DecodeString(s string) ([]byte, error) {
        dbuf := make([]byte, enc.DecodedLen(len(s)))
index 97aea845ae3ece612004c8ce80e0dd9f7aba7b31..4d7437b919520a79c846a552343b070ef11a5b28 100644 (file)
@@ -113,8 +113,9 @@ func TestEncode(t *testing.T) {
        for _, p := range pairs {
                for _, tt := range encodingTests {
                        got := tt.enc.EncodeToString([]byte(p.decoded))
-                       testEqual(t, "Encode(%q) = %q, want %q", p.decoded,
-                               got, tt.conv(p.encoded))
+                       testEqual(t, "Encode(%q) = %q, want %q", p.decoded, got, tt.conv(p.encoded))
+                       dst := tt.enc.AppendEncode([]byte("lead"), []byte(p.decoded))
+                       testEqual(t, `AppendEncode("lead", %q) = %q, want %q`, p.decoded, string(dst), "lead"+tt.conv(p.encoded))
                }
        }
 }
@@ -162,6 +163,10 @@ func TestDecode(t *testing.T) {
                        dbuf, err = tt.enc.DecodeString(encoded)
                        testEqual(t, "DecodeString(%q) = error %v, want %v", encoded, err, error(nil))
                        testEqual(t, "DecodeString(%q) = %q, want %q", encoded, string(dbuf), p.decoded)
+
+                       dst, err := tt.enc.AppendDecode([]byte("lead"), []byte(encoded))
+                       testEqual(t, "AppendDecode(%q) = error %v, want %v", p.encoded, err, error(nil))
+                       testEqual(t, `AppendDecode("lead", %q) = %q, want %q`, p.encoded, string(dst), "lead"+p.decoded)
                }
        }
 }
index 375f5831709bb7764f73f909c541bb7830bacc0a..ccc395e2f704351bbcf208e6fa32b0f3e0c150e0 100644 (file)
@@ -9,6 +9,7 @@ import (
        "errors"
        "fmt"
        "io"
+       "slices"
        "strings"
 )
 
@@ -51,6 +52,15 @@ func Encode(dst, src []byte) int {
        return len(src) * 2
 }
 
+// AppendEncode appends the hexadecimally encoded src to dst
+// and returns the extended buffer.
+func AppendEncode(dst, src []byte) []byte {
+       n := EncodedLen(len(src))
+       dst = slices.Grow(dst, n)
+       Encode(dst[len(dst):][:n], src)
+       return dst[:len(dst)+n]
+}
+
 // ErrLength reports an attempt to decode an odd-length input
 // using Decode or DecodeString.
 // The stream-based Decoder returns io.ErrUnexpectedEOF instead of ErrLength.
@@ -102,6 +112,16 @@ func Decode(dst, src []byte) (int, error) {
        return i, nil
 }
 
+// AppendDecode appends the hexadecimally decoded src to dst
+// and returns the extended buffer.
+// If the input is malformed, it returns the partially decoded src and an error.
+func AppendDecode(dst, src []byte) ([]byte, error) {
+       n := DecodedLen(len(src))
+       dst = slices.Grow(dst, n)
+       n, err := Decode(dst[len(dst):][:n], src)
+       return dst[:len(dst)+n], err
+}
+
 // EncodeToString returns the hexadecimal encoding of src.
 func EncodeToString(src []byte) string {
        dst := make([]byte, EncodedLen(len(src)))
index a820fe7a1514f7533e32d9d67830a23dced05361..03331eaae5afd4d79a52ba4600bff980be02055f 100644 (file)
@@ -37,6 +37,11 @@ func TestEncode(t *testing.T) {
                if string(dst) != test.enc {
                        t.Errorf("#%d: got: %#v want: %#v", i, dst, test.enc)
                }
+               dst = []byte("lead")
+               dst = AppendEncode(dst, test.dec)
+               if string(dst) != "lead"+test.enc {
+                       t.Errorf("#%d: got: %#v want: %#v", i, dst, "lead"+test.enc)
+               }
        }
 }
 
@@ -52,6 +57,13 @@ func TestDecode(t *testing.T) {
                } else if !bytes.Equal(dst, test.dec) {
                        t.Errorf("#%d: got: %#v want: %#v", i, dst, test.dec)
                }
+               dst = []byte("lead")
+               dst, err = AppendDecode(dst, []byte(test.enc))
+               if err != nil {
+                       t.Errorf("#%d: AppendDecode error: %v", i, err)
+               } else if string(dst) != "lead"+string(test.dec) {
+                       t.Errorf("#%d: got: %#v want: %#v", i, dst, "lead"+string(test.dec))
+               }
        }
 }
 
index bdb09737b039542077a57734135b9051c09f224c..39f22af5f9a16bca73782c6337fcda362949f46b 100644 (file)
@@ -210,7 +210,7 @@ var depsRules = `
 
        # encodings
        # core ones do not use fmt.
-       io, strconv
+       io, strconv, slices
        < encoding;
 
        encoding, reflect