Skip to content

Commit 5276107

Browse files
apocelipesgopherbot
authored andcommitted
math/big,regexp: implement the encoding.TextAppender interface
For #62384 Change-Id: I1557704c6a0f9c6f3b9aad001374dd5cdbc99065 GitHub-Last-Rev: c258d18 GitHub-Pull-Request: #68893 Reviewed-on: https://go-review.googlesource.com/c/go/+/605758 Reviewed-by: Ian Lance Taylor <[email protected]> Commit-Queue: Robert Griesemer <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Robert Griesemer <[email protected]>
1 parent bd8977b commit 5276107

File tree

12 files changed

+161
-19
lines changed

12 files changed

+161
-19
lines changed

api/next/62384.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ pkg encoding, type TextAppender interface, AppendText([]uint8) ([]uint8, error)
55
pkg net/url, method (*URL) AppendBinary([]uint8) ([]uint8, error) #62384
66
pkg log/slog, method (Level) AppendText([]uint8) ([]uint8, error) #62384
77
pkg log/slog, method (*LevelVar) AppendText([]uint8) ([]uint8, error) #62384
8+
pkg math/big, method (*Float) AppendText([]uint8) ([]uint8, error) #62384
9+
pkg math/big, method (*Int) AppendText([]uint8) ([]uint8, error) #62384
10+
pkg math/big, method (*Rat) AppendText([]uint8) ([]uint8, error) #62384
11+
pkg regexp, method (*Regexp) AppendText([]uint8) ([]uint8, error) #62384
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Float], [Int] and [Rat] now implement the [encoding.TextAppender] interface.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Regexp] now implements the [encoding.TextAppender] interface.

src/math/big/floatmarsh.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,21 @@ func (z *Float) GobDecode(buf []byte) error {
106106
return nil
107107
}
108108

109-
// MarshalText implements the [encoding.TextMarshaler] interface.
109+
// AppendText implements the [encoding.TextAppender] interface.
110110
// Only the [Float] value is marshaled (in full precision), other
111111
// attributes such as precision or accuracy are ignored.
112-
func (x *Float) MarshalText() (text []byte, err error) {
112+
func (x *Float) AppendText(b []byte) ([]byte, error) {
113113
if x == nil {
114-
return []byte("<nil>"), nil
114+
return append(b, "<nil>"...), nil
115115
}
116-
var buf []byte
117-
return x.Append(buf, 'g', -1), nil
116+
return x.Append(b, 'g', -1), nil
117+
}
118+
119+
// MarshalText implements the [encoding.TextMarshaler] interface.
120+
// Only the [Float] value is marshaled (in full precision), other
121+
// attributes such as precision or accuracy are ignored.
122+
func (x *Float) MarshalText() (text []byte, err error) {
123+
return x.AppendText(nil)
118124
}
119125

120126
// UnmarshalText implements the [encoding.TextUnmarshaler] interface.

src/math/big/floatmarsh_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,46 @@ func TestFloatGobDecodeInvalid(t *testing.T) {
171171
}
172172
}
173173
}
174+
175+
func TestFloatAppendText(t *testing.T) {
176+
for _, test := range floatVals {
177+
for _, sign := range []string{"", "+", "-"} {
178+
for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} {
179+
if prec > 53 && testing.Short() {
180+
continue
181+
}
182+
x := sign + test
183+
var tx Float
184+
_, _, err := tx.SetPrec(prec).Parse(x, 0)
185+
if err != nil {
186+
t.Errorf("parsing of %s (prec = %d) failed (invalid test case): %v", x, prec, err)
187+
continue
188+
}
189+
buf := make([]byte, 4, 32)
190+
b, err := tx.AppendText(buf)
191+
if err != nil {
192+
t.Errorf("marshaling of %v (prec = %d) failed: %v", &tx, prec, err)
193+
continue
194+
}
195+
var rx Float
196+
rx.SetPrec(prec)
197+
if err := rx.UnmarshalText(b[4:]); err != nil {
198+
t.Errorf("unmarshaling of %v (prec = %d) failed: %v", &tx, prec, err)
199+
continue
200+
}
201+
if rx.Cmp(&tx) != 0 {
202+
t.Errorf("AppendText of %v (prec = %d) failed: got %v want %v", &tx, prec, &rx, &tx)
203+
}
204+
}
205+
}
206+
}
207+
}
208+
209+
func TestFloatAppendTextNil(t *testing.T) {
210+
var x *Float
211+
buf := make([]byte, 4, 16)
212+
data, _ := x.AppendText(buf)
213+
if string(data[4:]) != "<nil>" {
214+
t.Errorf("got %q, want <nil>", data[4:])
215+
}
216+
}

src/math/big/intmarsh.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@ func (z *Int) GobDecode(buf []byte) error {
4545
return nil
4646
}
4747

48+
// AppendText implements the [encoding.TextAppender] interface.
49+
func (x *Int) AppendText(b []byte) (text []byte, err error) {
50+
return x.Append(b, 10), nil
51+
}
52+
4853
// MarshalText implements the [encoding.TextMarshaler] interface.
4954
func (x *Int) MarshalText() (text []byte, err error) {
50-
if x == nil {
51-
return []byte("<nil>"), nil
52-
}
53-
return x.abs.itoa(x.neg, 10), nil
55+
return x.AppendText(nil)
5456
}
5557

5658
// UnmarshalText implements the [encoding.TextUnmarshaler] interface.

src/math/big/intmarsh_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,36 @@ func TestIntXMLEncoding(t *testing.T) {
132132
}
133133
}
134134
}
135+
136+
func TestIntAppendText(t *testing.T) {
137+
for _, test := range encodingTests {
138+
for _, sign := range []string{"", "+", "-"} {
139+
x := sign + test
140+
var tx Int
141+
tx.SetString(x, 10)
142+
buf := make([]byte, 4, 32)
143+
b, err := tx.AppendText(buf)
144+
if err != nil {
145+
t.Errorf("marshaling of %s failed: %s", &tx, err)
146+
continue
147+
}
148+
var rx Int
149+
if err := rx.UnmarshalText(b[4:]); err != nil {
150+
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
151+
continue
152+
}
153+
if rx.Cmp(&tx) != 0 {
154+
t.Errorf("AppendText of %s failed: got %s want %s", &tx, &rx, &tx)
155+
}
156+
}
157+
}
158+
}
159+
160+
func TestIntAppendTextNil(t *testing.T) {
161+
var x *Int
162+
buf := make([]byte, 4, 16)
163+
data, _ := x.AppendText(buf)
164+
if string(data[4:]) != "<nil>" {
165+
t.Errorf("got %q, want <nil>", data[4:])
166+
}
167+
}

src/math/big/ratconv.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,12 +299,13 @@ func scanExponent(r io.ByteScanner, base2ok, sepOk bool) (exp int64, base int, e
299299

300300
// String returns a string representation of x in the form "a/b" (even if b == 1).
301301
func (x *Rat) String() string {
302-
return string(x.marshal())
302+
return string(x.marshal(nil))
303303
}
304304

305-
// marshal implements String returning a slice of bytes
306-
func (x *Rat) marshal() []byte {
307-
var buf []byte
305+
// marshal implements [Rat.String] returning a slice of bytes.
306+
// It appends the string representation of x in the form "a/b" (even if b == 1) to buf,
307+
// and returns the extended buffer.
308+
func (x *Rat) marshal(buf []byte) []byte {
308309
buf = x.a.Append(buf, 10)
309310
buf = append(buf, '/')
310311
if len(x.b.abs) != 0 {

src/math/big/ratmarsh.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,17 @@ func (z *Rat) GobDecode(buf []byte) error {
6868
return nil
6969
}
7070

71-
// MarshalText implements the [encoding.TextMarshaler] interface.
72-
func (x *Rat) MarshalText() (text []byte, err error) {
71+
// AppendText implements the [encoding.TextAppender] interface.
72+
func (x *Rat) AppendText(b []byte) ([]byte, error) {
7373
if x.IsInt() {
74-
return x.a.MarshalText()
74+
return x.a.AppendText(b)
7575
}
76-
return x.marshal(), nil
76+
return x.marshal(b), nil
77+
}
78+
79+
// MarshalText implements the [encoding.TextMarshaler] interface.
80+
func (x *Rat) MarshalText() (text []byte, err error) {
81+
return x.AppendText(nil)
7782
}
7883

7984
// UnmarshalText implements the [encoding.TextUnmarshaler] interface.

src/math/big/ratmarsh_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,26 @@ func TestRatGobDecodeShortBuffer(t *testing.T) {
136136
}
137137
}
138138
}
139+
140+
func TestRatAppendText(t *testing.T) {
141+
for _, num := range ratNums {
142+
for _, denom := range ratDenoms {
143+
var tx Rat
144+
tx.SetString(num + "/" + denom)
145+
buf := make([]byte, 4, 32)
146+
b, err := tx.AppendText(buf)
147+
if err != nil {
148+
t.Errorf("marshaling of %s failed: %s", &tx, err)
149+
continue
150+
}
151+
var rx Rat
152+
if err := rx.UnmarshalText(b[4:]); err != nil {
153+
t.Errorf("unmarshaling of %s failed: %s", &tx, err)
154+
continue
155+
}
156+
if rx.Cmp(&tx) != 0 {
157+
t.Errorf("AppendText of %s failed: got %s want %s", &tx, &rx, &tx)
158+
}
159+
}
160+
}
161+
}

src/regexp/all_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,21 @@ func TestUnmarshalText(t *testing.T) {
965965
if unmarshaled.String() != goodRe[i] {
966966
t.Errorf("UnmarshalText returned unexpected value: %s", unmarshaled.String())
967967
}
968+
969+
buf := make([]byte, 4, 32)
970+
marshalAppend, err := re.AppendText(buf)
971+
if err != nil {
972+
t.Errorf("regexp %#q failed to marshal: %s", re, err)
973+
continue
974+
}
975+
marshalAppend = marshalAppend[4:]
976+
if err := unmarshaled.UnmarshalText(marshalAppend); err != nil {
977+
t.Errorf("regexp %#q failed to unmarshal: %s", re, err)
978+
continue
979+
}
980+
if unmarshaled.String() != goodRe[i] {
981+
t.Errorf("UnmarshalText returned unexpected value: %s", unmarshaled.String())
982+
}
968983
}
969984
t.Run("invalid pattern", func(t *testing.T) {
970985
re := new(Regexp)

src/regexp/regexp.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,14 +1277,22 @@ func (re *Regexp) Split(s string, n int) []string {
12771277
return strings
12781278
}
12791279

1280-
// MarshalText implements [encoding.TextMarshaler]. The output
1280+
// AppendText implements [encoding.TextAppender]. The output
12811281
// matches that of calling the [Regexp.String] method.
12821282
//
12831283
// Note that the output is lossy in some cases: This method does not indicate
12841284
// POSIX regular expressions (i.e. those compiled by calling [CompilePOSIX]), or
12851285
// those for which the [Regexp.Longest] method has been called.
1286+
func (re *Regexp) AppendText(b []byte) ([]byte, error) {
1287+
return append(b, re.String()...), nil
1288+
}
1289+
1290+
// MarshalText implements [encoding.TextMarshaler]. The output
1291+
// matches that of calling the [Regexp.AppendText] method.
1292+
//
1293+
// See [Regexp.AppendText] for more information.
12861294
func (re *Regexp) MarshalText() ([]byte, error) {
1287-
return []byte(re.String()), nil
1295+
return re.AppendText(nil)
12881296
}
12891297

12901298
// UnmarshalText implements [encoding.TextUnmarshaler] by calling

0 commit comments

Comments
 (0)