Skip to content

Commit 28ded3e

Browse files
committed
if unused, convert []byte to string without allocating and copying
1 parent 1369358 commit 28ded3e

File tree

28 files changed

+113
-40
lines changed

28 files changed

+113
-40
lines changed

ap/activity.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"errors"
2323
"fmt"
2424
"log/slog"
25+
26+
"github.com/dimkr/tootik/danger"
2527
)
2628

2729
type ActivityType string
@@ -155,8 +157,7 @@ func (a *Activity) Scan(src any) error {
155157
}
156158

157159
func (a *Activity) Value() (driver.Value, error) {
158-
buf, err := json.Marshal(a)
159-
return string(buf), err
160+
return danger.MarshalJSON(a)
160161
}
161162

162163
func (a *Activity) LogValue() slog.Value {

ap/actor.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"database/sql/driver"
2121
"encoding/json"
2222
"fmt"
23+
24+
"github.com/dimkr/tootik/danger"
2325
)
2426

2527
type ActorType string
@@ -71,6 +73,5 @@ func (a *Actor) Scan(src any) error {
7173
}
7274

7375
func (a *Actor) Value() (driver.Value, error) {
74-
buf, err := json.Marshal(a)
75-
return string(buf), err
76+
return danger.MarshalJSON(a)
7677
}

ap/attachment.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"database/sql/driver"
2121
"encoding/json"
2222
"fmt"
23+
24+
"github.com/dimkr/tootik/danger"
2325
)
2426

2527
type AttachmentType string
@@ -50,6 +52,5 @@ func (a *Attachment) Scan(src any) error {
5052
}
5153

5254
func (a *Attachment) Value() (driver.Value, error) {
53-
buf, err := json.Marshal(a)
54-
return string(buf), err
55+
return danger.MarshalJSON(a)
5556
}

ap/audience.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"encoding/json"
2222
"fmt"
2323

24+
"github.com/dimkr/tootik/danger"
2425
"github.com/dimkr/tootik/data"
2526
)
2627

@@ -89,6 +90,5 @@ func (a *Audience) Scan(src any) error {
8990
}
9091

9192
func (a *Audience) Value() (driver.Value, error) {
92-
buf, err := json.Marshal(a)
93-
return string(buf), err
93+
return danger.MarshalJSON(a)
9494
}

ap/object.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"database/sql/driver"
2121
"encoding/json"
2222
"fmt"
23+
24+
"github.com/dimkr/tootik/danger"
2325
)
2426

2527
type ObjectType string
@@ -85,6 +87,5 @@ func (o *Object) Scan(src any) error {
8587
}
8688

8789
func (o *Object) Value() (driver.Value, error) {
88-
buf, err := json.Marshal(o)
89-
return string(buf), err
90+
return danger.MarshalJSON(o)
9091
}

ap/time.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2023, 2024 Dima Krasner
2+
Copyright 2023 - 2025 Dima Krasner
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -16,7 +16,11 @@ limitations under the License.
1616

1717
package ap
1818

19-
import "time"
19+
import (
20+
"time"
21+
22+
"github.com/dimkr/tootik/danger"
23+
)
2024

2125
// Time is a wrapper around [time.Time] with fallback if parsing of RFC3339 fails.
2226
type Time struct {
@@ -27,7 +31,7 @@ func (t *Time) UnmarshalJSON(b []byte) error {
2731
err := t.Time.UnmarshalJSON(b)
2832
// ugly hack for Threads
2933
if err != nil && len(b) > 2 && b[0] == '"' && b[len(b)-1] == '"' {
30-
t.Time, err = time.Parse("2006-01-02T15:04:05-0700", string(b[1:len(b)-1]))
34+
t.Time, err = time.Parse("2006-01-02T15:04:05-0700", danger.String(b[1:len(b)-1]))
3135
}
3236
return err
3337
}

cmd/tootik/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/dimkr/tootik/ap"
3838
"github.com/dimkr/tootik/buildinfo"
3939
"github.com/dimkr/tootik/cfg"
40+
"github.com/dimkr/tootik/danger"
4041
"github.com/dimkr/tootik/data"
4142
"github.com/dimkr/tootik/fed"
4243
"github.com/dimkr/tootik/front"
@@ -288,7 +289,7 @@ func main() {
288289
ctx,
289290
"insert into icons(name, buf) values($1, $2) on conflict(name) do update set buf = $2",
290291
userName,
291-
string(resized),
292+
danger.String(resized),
292293
); err != nil {
293294
panic(err)
294295
}

danger/danger.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
Copyright 2025 Dima Krasner
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package danger provides memory unsafe utilities.
18+
package danger

inbox/json.go renamed to danger/json.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package inbox
17+
package danger
1818

1919
import "encoding/json"
2020

21-
func marshal(v any) (string, error) {
21+
// MarshalJSON encodes a value to a JSON string.
22+
//
23+
// It uses [String] to avoid memory allocation and copying.
24+
func MarshalJSON(v any) (string, error) {
2225
if b, err := json.Marshal(v); err != nil {
2326
return "", err
2427
} else {
25-
return string(b), nil
28+
return String(b), nil
2629
}
2730
}

danger/string.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
Copyright 2025 Dima Krasner
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package danger
18+
19+
import "unsafe"
20+
21+
// String casts a byte slice to a string without copying the underlying array.
22+
//
23+
// The caller must not modify b afterwards because this will change the returned string.
24+
func String(b []byte) string {
25+
return unsafe.String(unsafe.SliceData(b), len(b))
26+
}

0 commit comments

Comments
 (0)