summaryrefslogtreecommitdiff
path: root/vendor/github.com/bytedance/sonic/internal/resolver
diff options
context:
space:
mode:
authorLibravatar Terin Stock <terinjokes@gmail.com>2025-03-09 17:47:56 +0100
committerLibravatar Terin Stock <terinjokes@gmail.com>2025-12-01 22:08:04 +0100
commitb1af8fd87760b34e3ff2fd3bda38f211815a0473 (patch)
tree9317fad1a7ec298d7a8d2678e4e422953bbc6f33 /vendor/github.com/bytedance/sonic/internal/resolver
parent[chore] update URLs to forked source (diff)
downloadgotosocial-b1af8fd87760b34e3ff2fd3bda38f211815a0473.tar.xz
[chore] remove vendor
Diffstat (limited to 'vendor/github.com/bytedance/sonic/internal/resolver')
-rw-r--r--vendor/github.com/bytedance/sonic/internal/resolver/asm.s0
-rw-r--r--vendor/github.com/bytedance/sonic/internal/resolver/fields.go388
-rw-r--r--vendor/github.com/bytedance/sonic/internal/resolver/resolver.go226
3 files changed, 0 insertions, 614 deletions
diff --git a/vendor/github.com/bytedance/sonic/internal/resolver/asm.s b/vendor/github.com/bytedance/sonic/internal/resolver/asm.s
deleted file mode 100644
index e69de29bb..000000000
--- a/vendor/github.com/bytedance/sonic/internal/resolver/asm.s
+++ /dev/null
diff --git a/vendor/github.com/bytedance/sonic/internal/resolver/fields.go b/vendor/github.com/bytedance/sonic/internal/resolver/fields.go
deleted file mode 100644
index 614bef4e5..000000000
--- a/vendor/github.com/bytedance/sonic/internal/resolver/fields.go
+++ /dev/null
@@ -1,388 +0,0 @@
-/**
- * Copyright 2025 ByteDance Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package resolver
-
-import (
- "reflect"
- "sort"
- "strings"
- "unicode"
- "unicode/utf8"
-
- "github.com/bytedance/sonic/internal/encoder/alg"
-)
-
-type StdField struct {
- name string
- nameBytes []byte
- nameNonEsc string
- nameEscHTML string
- tag bool
- index []int
- typ reflect.Type
- omitEmpty bool
- omitZero bool
- isZero func(reflect.Value) bool
- quoted bool
-}
-
-type StdStructFields struct {
- list []StdField
- nameIndex map[string]*StdField
- byFoldedName map[string]*StdField
-}
-
-func typeFields(t reflect.Type) StdStructFields {
- // Anonymous fields to explore at the current level and the next.
- current := []StdField{}
- next := []StdField{{typ: t}}
-
- // Count of queued names for current level and the next.
- var count, nextCount map[reflect.Type]int
-
- // Types already visited at an earlier level.
- visited := map[reflect.Type]bool{}
-
- // Fields found.
- var fields []StdField
-
- // Buffer to run appendHTMLEscape on field names.
- var nameEscBuf []byte
-
- for len(next) > 0 {
- current, next = next, current[:0]
- count, nextCount = nextCount, map[reflect.Type]int{}
-
- for _, f := range current {
- if visited[f.typ] {
- continue
- }
- visited[f.typ] = true
-
- // Scan f.typ for fields to include.
- for i := 0; i < f.typ.NumField(); i++ {
- sf := f.typ.Field(i)
- if sf.Anonymous {
- t := sf.Type
- if t.Kind() == reflect.Pointer {
- t = t.Elem()
- }
- if !sf.IsExported() && t.Kind() != reflect.Struct {
- // Ignore embedded fields of unexported non-struct types.
- continue
- }
- // Do not ignore embedded fields of unexported struct types
- // since they may have exported fields.
- } else if !sf.IsExported() {
- // Ignore unexported non-embedded fields.
- continue
- }
- tag := sf.Tag.Get("json")
- if tag == "-" {
- continue
- }
- name, opts := parseTag(tag)
- if !isValidTag(name) {
- name = ""
- }
- index := make([]int, len(f.index)+1)
- copy(index, f.index)
- index[len(f.index)] = i
-
- ft := sf.Type
- if ft.Name() == "" && ft.Kind() == reflect.Pointer {
- // Follow pointer.
- ft = ft.Elem()
- }
-
- // Only strings, floats, integers, and booleans can be quoted.
- quoted := false
- if opts.Contains("string") {
- switch ft.Kind() {
- case reflect.Bool,
- reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
- reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
- reflect.Float32, reflect.Float64,
- reflect.String:
- quoted = true
- }
- }
-
- // Record found field and index sequence.
- if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
- tagged := name != ""
- if name == "" {
- name = sf.Name
- }
- field := StdField{
- name: name,
- tag: tagged,
- index: index,
- typ: ft,
- omitEmpty: opts.Contains("omitempty"),
- omitZero: opts.Contains("omitzero"),
- quoted: quoted,
- }
- field.nameBytes = []byte(field.name)
-
- // Build nameEscHTML and nameNonEsc ahead of time.
- nameEscBuf = alg.HtmlEscape(nameEscBuf[:0], field.nameBytes)
- field.nameEscHTML = `"` + string(nameEscBuf) + `":`
- field.nameNonEsc = `"` + field.name + `":`
-
- if field.omitZero {
- t := sf.Type
- // Provide a function that uses a type's IsZero method.
- switch {
- case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
- field.isZero = func(v reflect.Value) bool {
- // Avoid panics calling IsZero on a nil interface or
- // non-nil interface with nil pointer.
- return v.IsNil() ||
- (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
- v.Interface().(isZeroer).IsZero()
- }
- case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
- field.isZero = func(v reflect.Value) bool {
- // Avoid panics calling IsZero on nil pointer.
- return v.IsNil() || v.Interface().(isZeroer).IsZero()
- }
- case t.Implements(isZeroerType):
- field.isZero = func(v reflect.Value) bool {
- return v.Interface().(isZeroer).IsZero()
- }
- case reflect.PointerTo(t).Implements(isZeroerType):
- field.isZero = func(v reflect.Value) bool {
- if !v.CanAddr() {
- // Temporarily box v so we can take the address.
- v2 := reflect.New(v.Type()).Elem()
- v2.Set(v)
- v = v2
- }
- return v.Addr().Interface().(isZeroer).IsZero()
- }
- }
- }
-
- fields = append(fields, field)
- if count[f.typ] > 1 {
- // If there were multiple instances, add a second,
- // so that the annihilation code will see a duplicate.
- // It only cares about the distinction between 1 and 2,
- // so don't bother generating any more copies.
- fields = append(fields, fields[len(fields)-1])
- }
- continue
- }
-
- // Record new anonymous struct to explore in next round.
- nextCount[ft]++
- if nextCount[ft] == 1 {
- next = append(next, StdField{name: ft.Name(), index: index, typ: ft})
- }
- }
- }
- }
-
- sort.Slice(fields, func(i, j int) bool {
- a, b := fields[i], fields[j]
- // sort field by name, breaking ties with depth, then
- // breaking ties with "name came from json tag", then
- // breaking ties with index sequence.
- if c := strings.Compare(a.name, b.name); c != 0 {
- return c < 0
- }
- if len(a.index) != len(b.index) {
- return len(a.index) < len(b.index)
- }
- if a.tag != b.tag {
- if a.tag {
- return true
- }
- return false
- }
- return compare(a.index, b.index) < 0
- })
-
- // Delete all fields that are hidden by the Go rules for embedded fields,
- // except that fields with JSON tags are promoted.
-
- // The fields are sorted in primary order of name, secondary order
- // of field index length. Loop over names; for each name, delete
- // hidden fields by choosing the one dominant field that survives.
- out := fields[:0]
- for advance, i := 0, 0; i < len(fields); i += advance {
- // One iteration per name.
- // Find the sequence of fields with the name of this first field.
- fi := fields[i]
- name := fi.name
- for advance = 1; i+advance < len(fields); advance++ {
- fj := fields[i+advance]
- if fj.name != name {
- break
- }
- }
- if advance == 1 { // Only one field with this name
- out = append(out, fi)
- continue
- }
- dominant, ok := dominantField(fields[i : i+advance])
- if ok {
- out = append(out, dominant)
- }
- }
-
- fields = out
- sort.Slice(fields, func(i, j int) bool {
- a, b := fields[i], fields[j]
- return compare(a.index, b.index) < 0
- })
-
- exactNameIndex := make(map[string]*StdField, len(fields))
- foldedNameIndex := make(map[string]*StdField, len(fields))
- for i, field := range fields {
- exactNameIndex[field.name] = &fields[i]
- // For historical reasons, first folded match takes precedence.
- if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
- foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
- }
- }
- return StdStructFields{fields, exactNameIndex, foldedNameIndex}
-}
-
-func compare(s1, s2 []int) int {
- for i, v1 := range s1 {
- if i >= len(s2) {
- return +1
- }
- v2 := s2[i]
- if v1 != v2 {
- return v1 - v2
- }
- }
- if len(s1) < len(s2) {
- return -1
- }
- return 0
-}
-
-type isZeroer interface {
- IsZero() bool
-}
-
-var isZeroerType = reflect.TypeOf((*isZeroer)(nil)).Elem()
-
-// tagOptions is the string following a comma in a struct field's "json"
-// tag, or the empty string. It does not include the leading comma.
-type tagOptions string
-
-// parseTag splits a struct field's json tag into its name and
-// comma-separated options.
-func parseTag(tag string) (string, tagOptions) {
- tag, opt, _ := strings.Cut(tag, ",")
- return tag, tagOptions(opt)
-}
-
-// Contains reports whether a comma-separated list of options
-// contains a particular substr flag. substr must be surrounded by a
-// string boundary or commas.
-func (o tagOptions) Contains(optionName string) bool {
- if len(o) == 0 {
- return false
- }
- s := string(o)
- for s != "" {
- var name string
- name, s, _ = strings.Cut(s, ",")
- if name == optionName {
- return true
- }
- }
- return false
-}
-
-func isValidTag(s string) bool {
- if s == "" {
- return false
- }
- for _, c := range s {
- switch {
- case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
- // Backslash and quote chars are reserved, but
- // otherwise any punctuation chars are allowed
- // in a tag name.
- case !unicode.IsLetter(c) && !unicode.IsDigit(c):
- return false
- }
- }
- return true
-}
-
-// dominantField looks through the fields, all of which are known to
-// have the same name, to find the single field that dominates the
-// others using Go's embedding rules, modified by the presence of
-// JSON tags. If there are multiple top-level fields, the boolean
-// will be false: This condition is an error in Go and we skip all
-// the fields.
-func dominantField(fields []StdField) (StdField, bool) {
- // The fields are sorted in increasing index-length order, then by presence of tag.
- // That means that the first field is the dominant one. We need only check
- // for error cases: two fields at top level, either both tagged or neither tagged.
- if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
- return StdField{}, false
- }
- return fields[0], true
-}
-
-
-// foldName returns a folded string such that foldName(x) == foldName(y)
-// is identical to bytes.EqualFold(x, y).
-func foldName(in []byte) []byte {
- // This is inlinable to take advantage of "function outlining".
- var arr [32]byte // large enough for most JSON names
- return appendFoldedName(arr[:0], in)
-}
-
-func appendFoldedName(out, in []byte) []byte {
- for i := 0; i < len(in); {
- // Handle single-byte ASCII.
- if c := in[i]; c < utf8.RuneSelf {
- if 'a' <= c && c <= 'z' {
- c -= 'a' - 'A'
- }
- out = append(out, c)
- i++
- continue
- }
- // Handle multi-byte Unicode.
- r, n := utf8.DecodeRune(in[i:])
- out = utf8.AppendRune(out, foldRune(r))
- i += n
- }
- return out
-}
-
-// foldRune is returns the smallest rune for all runes in the same fold set.
-func foldRune(r rune) rune {
- for {
- r2 := unicode.SimpleFold(r)
- if r2 <= r {
- return r2
- }
- r = r2
- }
-}
diff --git a/vendor/github.com/bytedance/sonic/internal/resolver/resolver.go b/vendor/github.com/bytedance/sonic/internal/resolver/resolver.go
deleted file mode 100644
index 4303c6744..000000000
--- a/vendor/github.com/bytedance/sonic/internal/resolver/resolver.go
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2021 ByteDance Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package resolver
-
-import (
- "fmt"
- "reflect"
- "strings"
- "sync"
- _ "unsafe"
-)
-
-type FieldOpts int
-type OffsetType int
-
-const (
- F_omitempty FieldOpts = 1 << iota
- F_stringize
- F_omitzero
-)
-
-const (
- F_offset OffsetType = iota
- F_deref
-)
-
-type Offset struct {
- Size uintptr
- Kind OffsetType
- Type reflect.Type
-}
-
-type FieldMeta struct {
- Name string
- Path []Offset
- Opts FieldOpts
- Type reflect.Type
- IsZero func(reflect.Value) bool
-}
-
-func (self *FieldMeta) String() string {
- var path []string
- var opts []string
-
- /* dump the field path */
- for _, off := range self.Path {
- if off.Kind == F_offset {
- path = append(path, fmt.Sprintf("%d", off.Size))
- } else {
- path = append(path, fmt.Sprintf("%d.(*%s)", off.Size, off.Type))
- }
- }
-
- /* check for "string" */
- if (self.Opts & F_stringize) != 0 {
- opts = append(opts, "string")
- }
-
- /* check for "omitempty" */
- if (self.Opts & F_omitempty) != 0 {
- opts = append(opts, "omitempty")
- }
-
- /* format the field */
- return fmt.Sprintf(
- "{Field \"%s\" @ %s, opts=%s, type=%s}",
- self.Name,
- strings.Join(path, "."),
- strings.Join(opts, ","),
- self.Type,
- )
-}
-
-func (self *FieldMeta) optimize() {
- var n int
- var v uintptr
-
- /* merge adjacent offsets */
- for _, o := range self.Path {
- if v += o.Size; o.Kind == F_deref {
- self.Path[n].Size = v
- self.Path[n].Type, v = o.Type, 0
- self.Path[n].Kind, n = F_deref, n + 1
- }
- }
-
- /* last offset value */
- if v != 0 {
- self.Path[n].Size = v
- self.Path[n].Type = nil
- self.Path[n].Kind = F_offset
- n++
- }
-
- /* must be at least 1 offset */
- if n != 0 {
- self.Path = self.Path[:n]
- } else {
- self.Path = []Offset{{Kind: F_offset}}
- }
-}
-
-func resolveFields(vt reflect.Type) []FieldMeta {
- tfv := typeFields(vt)
- ret := []FieldMeta(nil)
-
- /* convert each field */
- for _, fv := range tfv.list {
- /* add to result */
- ret = append(ret, FieldMeta{})
- fm := &ret[len(ret)-1]
-
- item := vt
- path := []Offset(nil)
-
- /* check for "string" */
- if fv.quoted {
- fm.Opts |= F_stringize
- }
-
- /* check for "omitempty" */
- if fv.omitEmpty {
- fm.Opts |= F_omitempty
- }
-
- /* handle the "omitzero" */
- handleOmitZero(fv, fm)
-
- /* dump the field path */
- for _, i := range fv.index {
- kind := F_offset
- fval := item.Field(i)
- item = fval.Type
-
- /* deref the pointer if needed */
- if item.Kind() == reflect.Ptr {
- kind = F_deref
- item = item.Elem()
- }
-
- /* add to path */
- path = append(path, Offset {
- Kind: kind,
- Type: item,
- Size: fval.Offset,
- })
- }
-
- /* get the index to the last offset */
- idx := len(path) - 1
- fvt := path[idx].Type
-
- /* do not dereference into fields */
- if path[idx].Kind == F_deref {
- fvt = reflect.PtrTo(fvt)
- path[idx].Kind = F_offset
- }
-
- fm.Type = fvt
- fm.Path = path
- fm.Name = fv.name
- }
-
- /* optimize the offsets */
- for i := range ret {
- ret[i].optimize()
- }
-
- /* all done */
- return ret
-}
-
-var (
- fieldLock = sync.RWMutex{}
- fieldCache = map[reflect.Type][]FieldMeta{}
-)
-
-func ResolveStruct(vt reflect.Type) []FieldMeta {
- var ok bool
- var fm []FieldMeta
-
- /* attempt to read from cache */
- fieldLock.RLock()
- fm, ok = fieldCache[vt]
- fieldLock.RUnlock()
-
- /* check if it was cached */
- if ok {
- return fm
- }
-
- /* otherwise use write-lock */
- fieldLock.Lock()
- defer fieldLock.Unlock()
-
- /* double check */
- if fm, ok = fieldCache[vt]; ok {
- return fm
- }
-
- /* resolve the field */
- fm = resolveFields(vt)
- fieldCache[vt] = fm
- return fm
-}
-
-func handleOmitZero(fv StdField, fm *FieldMeta) {
- if fv.omitZero {
- fm.Opts |= F_omitzero
- fm.IsZero = fv.isZero
- }
-}