diff options
Diffstat (limited to 'vendor/github.com/pquerna/ffjson/inception/reflect.go')
-rw-r--r-- | vendor/github.com/pquerna/ffjson/inception/reflect.go | 290 |
1 files changed, 0 insertions, 290 deletions
diff --git a/vendor/github.com/pquerna/ffjson/inception/reflect.go b/vendor/github.com/pquerna/ffjson/inception/reflect.go deleted file mode 100644 index 8fb0bd5cb..000000000 --- a/vendor/github.com/pquerna/ffjson/inception/reflect.go +++ /dev/null @@ -1,290 +0,0 @@ -/** - * Copyright 2014 Paul Querna - * - * 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 ffjsoninception - -import ( - fflib "github.com/pquerna/ffjson/fflib/v1" - "github.com/pquerna/ffjson/shared" - - "bytes" - "encoding/json" - "reflect" - "unicode/utf8" -) - -type StructField struct { - Name string - JsonName string - FoldFuncName string - Typ reflect.Type - OmitEmpty bool - ForceString bool - HasMarshalJSON bool - HasUnmarshalJSON bool - Pointer bool - Tagged bool -} - -type FieldByJsonName []*StructField - -func (a FieldByJsonName) Len() int { return len(a) } -func (a FieldByJsonName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a FieldByJsonName) Less(i, j int) bool { return a[i].JsonName < a[j].JsonName } - -type StructInfo struct { - Name string - Obj interface{} - Typ reflect.Type - Fields []*StructField - Options shared.StructOptions -} - -func NewStructInfo(obj shared.InceptionType) *StructInfo { - t := reflect.TypeOf(obj.Obj) - return &StructInfo{ - Obj: obj.Obj, - Name: t.Name(), - Typ: t, - Fields: extractFields(obj.Obj), - Options: obj.Options, - } -} - -func (si *StructInfo) FieldsByFirstByte() map[string][]*StructField { - rv := make(map[string][]*StructField) - for _, f := range si.Fields { - b := string(f.JsonName[1]) - rv[b] = append(rv[b], f) - } - return rv -} - -func (si *StructInfo) ReverseFields() []*StructField { - var i int - rv := make([]*StructField, 0) - for i = len(si.Fields) - 1; i >= 0; i-- { - rv = append(rv, si.Fields[i]) - } - return rv -} - -const ( - caseMask = ^byte(0x20) // Mask to ignore case in ASCII. -) - -func foldFunc(key []byte) string { - nonLetter := false - special := false // special letter - for _, b := range key { - if b >= utf8.RuneSelf { - return "bytes.EqualFold" - } - upper := b & caseMask - if upper < 'A' || upper > 'Z' { - nonLetter = true - } else if upper == 'K' || upper == 'S' { - // See above for why these letters are special. - special = true - } - } - if special { - return "fflib.EqualFoldRight" - } - if nonLetter { - return "fflib.AsciiEqualFold" - } - return "fflib.SimpleLetterEqualFold" -} - -type MarshalerFaster interface { - MarshalJSONBuf(buf fflib.EncodingBuffer) error -} - -type UnmarshalFaster interface { - UnmarshalJSONFFLexer(l *fflib.FFLexer, state fflib.FFParseState) error -} - -var marshalerType = reflect.TypeOf(new(json.Marshaler)).Elem() -var marshalerFasterType = reflect.TypeOf(new(MarshalerFaster)).Elem() -var unmarshalerType = reflect.TypeOf(new(json.Unmarshaler)).Elem() -var unmarshalFasterType = reflect.TypeOf(new(UnmarshalFaster)).Elem() - -// extractFields returns a list of fields that JSON should recognize for the given type. -// The algorithm is breadth-first search over the set of structs to include - the top struct -// and then any reachable anonymous structs. -func extractFields(obj interface{}) []*StructField { - t := reflect.TypeOf(obj) - // Anonymous fields to explore at the current level and the next. - current := []StructField{} - next := []StructField{{Typ: t}} - - // Count of queued names for current level and the next. - count := map[reflect.Type]int{} - nextCount := map[reflect.Type]int{} - - // Types already visited at an earlier level. - visited := map[reflect.Type]bool{} - - // Fields found. - var fields []*StructField - - 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.PkgPath != "" { // unexported - continue - } - tag := sf.Tag.Get("json") - if tag == "-" { - continue - } - name, opts := parseTag(tag) - if !isValidTag(name) { - name = "" - } - - ft := sf.Type - ptr := false - if ft.Kind() == reflect.Ptr { - ptr = true - } - - if ft.Name() == "" && ft.Kind() == reflect.Ptr { - // Follow pointer. - ft = ft.Elem() - } - - // Record found field and index sequence. - if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { - tagged := name != "" - if name == "" { - name = sf.Name - } - - var buf bytes.Buffer - fflib.WriteJsonString(&buf, name) - - field := &StructField{ - Name: sf.Name, - JsonName: string(buf.Bytes()), - FoldFuncName: foldFunc([]byte(name)), - Typ: ft, - HasMarshalJSON: ft.Implements(marshalerType), - HasUnmarshalJSON: ft.Implements(unmarshalerType), - OmitEmpty: opts.Contains("omitempty"), - ForceString: opts.Contains("string"), - Pointer: ptr, - Tagged: tagged, - } - - 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 or 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, StructField{ - Name: ft.Name(), - Typ: ft, - }) - } - } - } - } - - // 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.JsonName - for advance = 1; i+advance < len(fields); advance++ { - fj := fields[i+advance] - if fj.JsonName != 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 - - return fields -} - -// 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 []*StructField) (*StructField, bool) { - tagged := -1 // Index of first tagged field. - for i, f := range fields { - if f.Tagged { - if tagged >= 0 { - // Multiple tagged fields at the same level: conflict. - // Return no field. - return nil, false - } - tagged = i - } - } - if tagged >= 0 { - return fields[tagged], true - } - // All remaining fields have the same length. If there's more than one, - // we have a conflict (two fields named "X" at the same level) and we - // return no field. - if len(fields) > 1 { - return nil, false - } - return fields[0], true -} |