Skip to content

Commit 5759715

Browse files
authored
perf(encoding/text): reduce allocs (#142)
1 parent 8674397 commit 5759715

File tree

7 files changed

+53
-45
lines changed

7 files changed

+53
-45
lines changed

encoding/text/decode_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"reflect"
55
"testing"
66

7-
"github.com/abemedia/go-don/encoding/text"
7+
"github.com/abemedia/go-don/encoding"
88
"github.com/abemedia/go-don/pkg/httptest"
99
"github.com/google/go-cmp/cmp"
1010
"github.com/valyala/fasthttp"
@@ -35,9 +35,14 @@ func TestDecode(t *testing.T) {
3535
}
3636

3737
for _, test := range tests {
38+
dec := encoding.GetDecoder("text/plain")
39+
if dec == nil {
40+
t.Fatal("decoder not found")
41+
}
42+
3843
ctx := httptest.NewRequest(fasthttp.MethodGet, "/", test.in, nil)
3944
v := reflect.New(reflect.TypeOf(test.want)).Interface()
40-
if err := text.Decode(ctx, v); err != nil {
45+
if err := dec(ctx, v); err != nil {
4146
t.Error(err)
4247
} else {
4348
if diff := cmp.Diff(test.want, reflect.ValueOf(v).Elem().Interface()); diff != "" {

encoding/text/encode.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,19 @@ func encode(ctx *fasthttp.RequestCtx, v any) error {
5454
case error:
5555
b = byteconv.Atob(v.Error())
5656
case fmt.Stringer:
57-
b = append(ctx.Response.Body(), v.String()...)
57+
b = byteconv.Atob(v.String())
5858
default:
5959
return don.ErrNotAcceptable
6060
}
6161
}
6262

63+
if err != nil {
64+
return err
65+
}
66+
6367
if len(b) > 0 {
64-
ctx.Response.SetBodyRaw(append(b, '\n'))
68+
ctx.Response.SetBodyRaw(b)
6569
}
6670

67-
return err
71+
return nil
6872
}

encoding/text/encode_test.go

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"errors"
55
"testing"
66

7-
"github.com/abemedia/go-don/encoding/text"
7+
"github.com/abemedia/go-don/encoding"
88
"github.com/abemedia/go-don/pkg/httptest"
99
"github.com/google/go-cmp/cmp"
1010
"github.com/valyala/fasthttp"
@@ -15,31 +15,36 @@ func TestEncode(t *testing.T) {
1515
in any
1616
want string
1717
}{
18-
{"test", "test\n"},
19-
{[]byte("test"), "test\n"},
20-
{int(5), "5\n"},
21-
{int8(5), "5\n"},
22-
{int16(5), "5\n"},
23-
{int32(5), "5\n"},
24-
{int64(5), "5\n"},
25-
{uint(5), "5\n"},
26-
{uint8(5), "5\n"},
27-
{uint16(5), "5\n"},
28-
{uint32(5), "5\n"},
29-
{uint64(5), "5\n"},
30-
{float32(5.1), "5.1\n"},
31-
{float64(5.1), "5.1\n"},
32-
{true, "true\n"},
33-
{errors.New("test"), "test\n"},
34-
{marshaler{}, "test\n"},
35-
{&marshaler{}, "test\n"},
36-
{stringer{}, "test\n"},
37-
{&stringer{}, "test\n"},
18+
{"test", "test"},
19+
{[]byte("test"), "test"},
20+
{int(5), "5"},
21+
{int8(5), "5"},
22+
{int16(5), "5"},
23+
{int32(5), "5"},
24+
{int64(5), "5"},
25+
{uint(5), "5"},
26+
{uint8(5), "5"},
27+
{uint16(5), "5"},
28+
{uint32(5), "5"},
29+
{uint64(5), "5"},
30+
{float32(5.1), "5.1"},
31+
{float64(5.1), "5.1"},
32+
{true, "true"},
33+
{errors.New("test"), "test"},
34+
{marshaler{}, "test"},
35+
{&marshaler{}, "test"},
36+
{stringer{}, "test"},
37+
{&stringer{}, "test"},
3838
}
3939

4040
for _, test := range tests {
41+
enc := encoding.GetEncoder("text/plain")
42+
if enc == nil {
43+
t.Fatal("encoder not found")
44+
}
45+
4146
ctx := httptest.NewRequest(fasthttp.MethodGet, "/", "", nil)
42-
if err := text.Encode(ctx, test.in); err != nil {
47+
if err := enc(ctx, test.in); err != nil {
4348
t.Error(err)
4449
} else {
4550
if diff := cmp.Diff(test.want, string(ctx.Response.Body())); diff != "" {

encoding/text/export_test.go

Lines changed: 0 additions & 6 deletions
This file was deleted.

encoding/text/text_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88

99
var opt = test.EncodingOptions[string]{
1010
Mime: "text/plain",
11-
Raw: "foo\n",
11+
Raw: "foo",
1212
Parsed: "foo",
1313
}
1414

handler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ func H[T, O any](handle Handle[T, O]) httprouter.Handle {
7979
func handleError(ctx *fasthttp.RequestCtx, err error) {
8080
code := getStatusCode(err, http.StatusInternalServerError)
8181
if code < http.StatusInternalServerError {
82-
ctx.Error(err.Error()+"\n", code)
82+
ctx.Error(err.Error(), code)
8383
return
8484
}
85-
ctx.Error(fasthttp.StatusMessage(code)+"\n", code)
85+
ctx.Error(fasthttp.StatusMessage(code), code)
8686
ctx.Logger().Printf("%v", err)
8787
}
8888

handler_test.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ func TestHandlerResponse(t *testing.T) {
119119
message: "should return error on unprocessable request",
120120
want: response{
121121
Code: fasthttp.StatusUnsupportedMediaType,
122-
Body: "Unsupported Media Type\n",
122+
Body: "Unsupported Media Type",
123123
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
124124
},
125125
handler: don.H(func(ctx context.Context, req struct{ Hello string }) (any, error) {
@@ -131,7 +131,7 @@ func TestHandlerResponse(t *testing.T) {
131131
message: "should return error on unacceptable",
132132
want: response{
133133
Code: fasthttp.StatusNotAcceptable,
134-
Body: "Not Acceptable\n",
134+
Body: "Not Acceptable",
135135
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
136136
},
137137
handler: don.H(func(ctx context.Context, req any) ([]string, error) {
@@ -143,7 +143,7 @@ func TestHandlerResponse(t *testing.T) {
143143
message: "should return error on unsupported accept",
144144
want: response{
145145
Code: fasthttp.StatusNotAcceptable,
146-
Body: "Not Acceptable\n",
146+
Body: "Not Acceptable",
147147
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
148148
},
149149
handler: don.H(func(ctx context.Context, req any) (any, error) {
@@ -155,7 +155,7 @@ func TestHandlerResponse(t *testing.T) {
155155
message: "should return error on unsupported content type",
156156
want: response{
157157
Code: fasthttp.StatusUnsupportedMediaType,
158-
Body: "Unsupported Media Type\n",
158+
Body: "Unsupported Media Type",
159159
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
160160
},
161161
handler: don.H(func(ctx context.Context, req any) (any, error) {
@@ -170,7 +170,7 @@ func TestHandlerResponse(t *testing.T) {
170170
message: "should return error on invalid query",
171171
want: response{
172172
Code: fasthttp.StatusBadRequest,
173-
Body: "strconv.ParseInt: parsing \"foo\": invalid syntax\n",
173+
Body: "strconv.ParseInt: parsing \"foo\": invalid syntax",
174174
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
175175
},
176176
handler: don.H(func(ctx context.Context, req struct {
@@ -185,7 +185,7 @@ func TestHandlerResponse(t *testing.T) {
185185
message: "should return error on invalid header",
186186
want: response{
187187
Code: fasthttp.StatusBadRequest,
188-
Body: "strconv.ParseInt: parsing \"foo\": invalid syntax\n",
188+
Body: "strconv.ParseInt: parsing \"foo\": invalid syntax",
189189
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
190190
},
191191
handler: don.H(func(ctx context.Context, req struct {
@@ -200,7 +200,7 @@ func TestHandlerResponse(t *testing.T) {
200200
message: "should return error on invalid path element",
201201
want: response{
202202
Code: fasthttp.StatusNotFound,
203-
Body: "Not Found\n",
203+
Body: "Not Found",
204204
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
205205
},
206206
handler: don.H(func(ctx context.Context, req struct {
@@ -216,7 +216,7 @@ func TestHandlerResponse(t *testing.T) {
216216
message: "should return error on invalid body",
217217
want: response{
218218
Code: fasthttp.StatusBadRequest,
219-
Body: "strconv.Atoi: parsing \"foo\": invalid syntax\n",
219+
Body: "strconv.Atoi: parsing \"foo\": invalid syntax",
220220
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
221221
},
222222
handler: don.H(func(ctx context.Context, req int) (any, error) {
@@ -228,7 +228,7 @@ func TestHandlerResponse(t *testing.T) {
228228
message: "should return internal server error",
229229
want: response{
230230
Code: fasthttp.StatusInternalServerError,
231-
Body: "test\n",
231+
Body: "test",
232232
Header: map[string]string{"Content-Type": "text/plain; charset=utf-8"},
233233
},
234234
handler: don.H(func(ctx context.Context, req any) (any, error) {

0 commit comments

Comments
 (0)