Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save aktau/9f90b406adea5b41280b543dda7e8037 to your computer and use it in GitHub Desktop.

Select an option

Save aktau/9f90b406adea5b41280b543dda7e8037 to your computer and use it in GitHub Desktop.
json_v2_arshal_typeassert_commaoverwrite.go
package go852725
import (
"math"
"math/bits"
"reflect"
"slices"
"unicode/utf8"
)
// Batch pre-growing + indexed writes to avoid slice header updates inside
// loops:
//
// - Ints/Uints: 2-pass size via bits.Len64 + backwards formatting from end
// (or 1-pass conservative grow + putInt10 for len(s) < 8).
// - Bools: 1-pass conservative grow + 8-byte copy(buf[pos:pos+8], "true, ")
// which compiles to a single 64-bit MOVQ store per element.
// - Strings: 256-byte chunked batch grow + direct copy(buf[pos:], x) for
// unescaped ASCII strings, falling back to appendQuote only on
// escapes/UTF-8.
// - Floats: 1-pass batch grow + OverwriteComma.
func appendSimpleBestSafe(b []byte, v reflect.Value, flags *Flags) ([]byte, bool) {
if v.Kind() != reflect.Slice {
return appendScalar(b, v, flags)
}
if v.IsNil() && flags.Get(FormatNilSliceAsNull) {
return append(b, "null"...), true
}
if s, ok := reflect.TypeAssert[[]string](v); ok {
return appendStringSliceBestSafe(b, s, flags)
}
if s, ok := reflect.TypeAssert[[]int](v); ok {
return appendIntSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]int64](v); ok {
return appendIntSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]float64](v); ok {
return appendFloatSliceBestSafe(b, s, 64)
}
if s, ok := reflect.TypeAssert[[]bool](v); ok {
return appendBoolSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]int32](v); ok {
return appendIntSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint](v); ok {
return appendUintSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint64](v); ok {
return appendUintSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint32](v); ok {
return appendUintSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]float32](v); ok {
return appendFloatSliceBestSafe(b, s, 32)
}
if s, ok := reflect.TypeAssert[[]int16](v); ok {
return appendIntSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]int8](v); ok {
return appendIntSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint16](v); ok {
return appendUintSliceBestSafe(b, s), true
}
if s, ok := reflect.TypeAssert[[]uintptr](v); ok {
return appendUintSliceBestSafe(b, s), true
}
return b, false
}
const digits2Table = "00010203040506070809" +
"10111213141516171819" +
"20212223242526272829" +
"30313233343536373839" +
"40414243444546474849" +
"50515253545556575859" +
"60616263646566676869" +
"70717273747576777879" +
"80818283848586878889" +
"90919293949596979899"
var pow10Bounds = [20]uint64{
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000,
1000000000000,
10000000000000,
100000000000000,
1000000000000000,
10000000000000000,
100000000000000000,
1000000000000000000,
10000000000000000000,
}
// base10Digits returns the exact base-10 digit count of u in O(1) using bits.Len64.
func base10Digits(u uint64) int {
t := ((bits.Len64(u | 1)) * 1233) >> 12
if u >= pow10Bounds[t] {
t++
}
return t
}
func appendBoolSliceBestSafe(b []byte, s []bool) []byte {
if len(s) == 0 {
return append(b, "[]"...)
}
// Each element is at most 6 bytes ("false,"), plus 1 for '[' and +2 padding
// so the final 8-byte store never exceeds capacity.
need := 1 + 6*len(s) + 2
b = slices.Grow(b, need)
pos := len(b)
buf := b[:pos+need]
buf[pos] = '['
pos++
for _, x := range s {
if x {
copy(buf[pos:pos+8], "true, ")
pos += 5
} else {
copy(buf[pos:pos+8], "false, ")
pos += 6
}
}
buf[pos-1] = ']'
return buf[:pos]
}
func appendIntSliceBestSafe[T ~int | ~int8 | ~int16 | ~int32 | ~int64](b []byte, s []T) []byte {
if len(s) == 0 {
return append(b, "[]"...)
}
if len(s) < 8 {
// Short slices: single-pass conservative pre-grow (21 bytes/elem max).
need := 1 + 21*len(s)
b = slices.Grow(b, need)
pos := len(b)
buf := b[:pos+need]
buf[pos] = '['
pos++
for _, x := range s {
v := int64(x)
u := uint64(v)
if v < 0 {
buf[pos] = '-'
pos++
u = -u
}
pos = formatUintForward(buf, pos, u)
}
buf[pos-1] = ']'
return buf[:pos]
}
// Pass 1: compute exact byte length using bits.Len64.
need := 1 + len(s)
for _, x := range s {
v := int64(x)
u := uint64(v)
if v < 0 {
need++
u = -u
}
need += base10Digits(u)
}
b = slices.Grow(b, need)
start := len(b)
end := start + need
buf := b[:end]
buf[start] = '['
// Pass 2: format backwards from `end` without needing per-element digit counts
// or stack-buffer reversal.
p := end
for i := len(s) - 1; i >= 0; i-- {
p--
buf[p] = ','
v := int64(s[i])
u := uint64(v)
neg := v < 0
if neg {
u = -u
}
for u >= 100 {
is := (u % 100) * 2
u /= 100
p -= 2
buf[p] = digits2Table[is]
buf[p+1] = digits2Table[is+1]
}
if u < 10 {
p--
buf[p] = byte('0' + u)
} else {
is := u * 2
p -= 2
buf[p] = digits2Table[is]
buf[p+1] = digits2Table[is+1]
}
if neg {
p--
buf[p] = '-'
}
}
buf[end-1] = ']'
return buf
}
func appendUintSliceBestSafe[T ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr](b []byte, s []T) []byte {
if len(s) == 0 {
return append(b, "[]"...)
}
if len(s) < 8 {
need := 1 + 21*len(s)
b = slices.Grow(b, need)
pos := len(b)
buf := b[:pos+need]
buf[pos] = '['
pos++
for _, x := range s {
pos = formatUintForward(buf, pos, uint64(x))
}
buf[pos-1] = ']'
return buf[:pos]
}
need := 1 + len(s)
for _, x := range s {
need += base10Digits(uint64(x))
}
b = slices.Grow(b, need)
start := len(b)
end := start + need
buf := b[:end]
buf[start] = '['
p := end
for i := len(s) - 1; i >= 0; i-- {
p--
buf[p] = ','
u := uint64(s[i])
for u >= 100 {
is := (u % 100) * 2
u /= 100
p -= 2
buf[p] = digits2Table[is]
buf[p+1] = digits2Table[is+1]
}
if u < 10 {
p--
buf[p] = byte('0' + u)
} else {
is := u * 2
p -= 2
buf[p] = digits2Table[is]
buf[p+1] = digits2Table[is+1]
}
}
buf[end-1] = ']'
return buf
}
func formatUintForward(buf []byte, pos int, u uint64) int {
if u < 10 {
buf[pos] = byte('0' + u)
buf[pos+1] = ','
return pos + 2
}
if u < 100 {
i := u * 2
buf[pos] = digits2Table[i]
buf[pos+1] = digits2Table[i+1]
buf[pos+2] = ','
return pos + 3
}
d := base10Digits(u)
end := pos + d
p := end
for u >= 100 {
is := (u % 100) * 2
u /= 100
p -= 2
buf[p] = digits2Table[is]
buf[p+1] = digits2Table[is+1]
}
if u < 10 {
p--
buf[p] = byte('0' + u)
} else {
is := u * 2
p -= 2
buf[p] = digits2Table[is]
buf[p+1] = digits2Table[is+1]
}
buf[end] = ','
return end + 1
}
func appendStringSliceBestSafe(b []byte, s []string, flags *Flags) ([]byte, bool) {
if len(s) == 0 {
return append(b, "[]"...), true
}
const chunkBytes = 256
b = slices.Grow(b, chunkBytes)
pos := len(b)
buf := b[:cap(b)]
buf[pos] = '['
pos++
escapeHTML := flags.Get(EscapeForHTML)
for _, x := range s {
if len(buf)-pos < len(x)+3 {
b = slices.Grow(buf[:pos], max(chunkBytes, len(x)+3))
buf = b[:cap(b)]
}
needsEscape := false
for i := 0; i < len(x); i++ {
c := x[i]
if c >= utf8.RuneSelf || (escapeASCII[c] != 0 && (!(c == '<' || c == '>' || c == '&') || escapeHTML)) {
needsEscape = true
break
}
}
if !needsEscape {
buf[pos] = '"'
pos++
pos += copy(buf[pos:], x)
buf[pos] = '"'
buf[pos+1] = ','
pos += 2
continue
}
var err error
b, err = appendQuote(buf[:pos], x, flags)
if err != nil {
return b, false
}
b = append(b, ',')
pos = len(b)
buf = b[:cap(b)]
}
buf[pos-1] = ']'
return buf[:pos], true
}
func appendFloatSliceBestSafe[T ~float32 | ~float64](b []byte, s []T, bits int) ([]byte, bool) {
if len(s) == 0 {
return append(b, "[]"...), true
}
b = slices.Grow(b, 1+26*len(s))
b = b[:len(b)+1]
b[len(b)-1] = '['
for _, x := range s {
fv := float64(x)
if math.IsNaN(fv) || math.IsInf(fv, 0) {
return b, false
}
b = appendFloat(b, fv, bits)
b = b[:len(b)+1]
b[len(b)-1] = ','
}
b[len(b)-1] = ']'
return b, true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment