From 4d3d137499befdb2940c9cae75e2c232470c78a9 Mon Sep 17 00:00:00 2001 From: Jille Timmermans Date: Mon, 25 Sep 2023 14:51:45 +0200 Subject: [PATCH] Allow 1-2 byte strings in the dictionary Interning 1-2 byte strings isn't very useful because their binary format is longer / equal to simply encoding it as a string. So we shouldn't try to automatically intern those strings. However, if someone adds such string to their dict, they probably want it interned anyway. (In my case to reduce allocations.) After this change, people explicitly passing a dict with 1-2 byte entries will see different binary output from msgpack. Decoding keeps working. Automatic interning is unchanged. --- intern.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/intern.go b/intern.go index be0316a..7f019aa 100644 --- a/intern.go +++ b/intern.go @@ -57,18 +57,16 @@ func encodeInternedStringValue(e *Encoder, v reflect.Value) error { func (e *Encoder) encodeInternedString(s string, intern bool) error { // Interned string takes at least 3 bytes. Plain string 1 byte + string len. - if len(s) >= minInternedStringLen { - if idx, ok := e.dict[s]; ok { - return e.encodeInternedStringIndex(idx) - } + if idx, ok := e.dict[s]; ok { + return e.encodeInternedStringIndex(idx) + } - if intern && len(e.dict) < maxDictLen { - if e.dict == nil { - e.dict = make(map[string]int) - } - idx := len(e.dict) - e.dict[s] = idx + if intern && len(s) >= minInternedStringLen && len(e.dict) < maxDictLen { + if e.dict == nil { + e.dict = make(map[string]int) } + idx := len(e.dict) + e.dict[s] = idx } return e.encodeNormalString(s)