summaryrefslogtreecommitdiff
path: root/vendor/github.com/pquerna/ffjson/inception/reflect.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pquerna/ffjson/inception/reflect.go')
-rw-r--r--vendor/github.com/pquerna/ffjson/inception/reflect.go290
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
-}