diff options
Diffstat (limited to 'vendor/github.com/bytedance/sonic/internal/resolver')
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 - } -} |
