github.com/enmand/kubernetes@v1.2.0-alpha.0/third_party/forked/json/fields.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package json is forked from the Go standard library to enable us to find the
     6  // field of a struct that a given JSON key maps to.
     7  package json
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"reflect"
    13  	"sort"
    14  	"strings"
    15  	"sync"
    16  	"unicode"
    17  	"unicode/utf8"
    18  )
    19  
    20  // Finds the patchStrategy and patchMergeKey struct tag fields on a given
    21  // struct field given the struct type and the JSON name of the field.
    22  // TODO: fix the returned errors to be introspectable.
    23  func LookupPatchMetadata(t reflect.Type, jsonField string) (reflect.Type, string, string, error) {
    24  	if t.Kind() == reflect.Map {
    25  		return t.Elem(), "", "", nil
    26  	}
    27  	if t.Kind() != reflect.Struct {
    28  		return nil, "", "", fmt.Errorf("merging an object in json but data type is not map or struct, instead is: %s",
    29  			t.Kind().String())
    30  	}
    31  	jf := []byte(jsonField)
    32  	// Find the field that the JSON library would use.
    33  	var f *field
    34  	fields := cachedTypeFields(t)
    35  	for i := range fields {
    36  		ff := &fields[i]
    37  		if bytes.Equal(ff.nameBytes, jf) {
    38  			f = ff
    39  			break
    40  		}
    41  		// Do case-insensitive comparison.
    42  		if f == nil && ff.equalFold(ff.nameBytes, jf) {
    43  			f = ff
    44  		}
    45  	}
    46  	if f != nil {
    47  		// Find the reflect.Value of the most preferential
    48  		// struct field.
    49  		tjf := t.Field(f.index[0])
    50  		patchStrategy := tjf.Tag.Get("patchStrategy")
    51  		patchMergeKey := tjf.Tag.Get("patchMergeKey")
    52  		return tjf.Type, patchStrategy, patchMergeKey, nil
    53  	}
    54  	return nil, "", "", fmt.Errorf("unable to find api field in struct %s for the json field %q", t.Name(), jsonField)
    55  }
    56  
    57  // A field represents a single field found in a struct.
    58  type field struct {
    59  	name      string
    60  	nameBytes []byte                 // []byte(name)
    61  	equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
    62  
    63  	tag       bool
    64  	index     []int
    65  	typ       reflect.Type
    66  	omitEmpty bool
    67  	quoted    bool
    68  }
    69  
    70  func fillField(f field) field {
    71  	f.nameBytes = []byte(f.name)
    72  	f.equalFold = foldFunc(f.nameBytes)
    73  	return f
    74  }
    75  
    76  // byName sorts field by name, breaking ties with depth,
    77  // then breaking ties with "name came from json tag", then
    78  // breaking ties with index sequence.
    79  type byName []field
    80  
    81  func (x byName) Len() int { return len(x) }
    82  
    83  func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    84  
    85  func (x byName) Less(i, j int) bool {
    86  	if x[i].name != x[j].name {
    87  		return x[i].name < x[j].name
    88  	}
    89  	if len(x[i].index) != len(x[j].index) {
    90  		return len(x[i].index) < len(x[j].index)
    91  	}
    92  	if x[i].tag != x[j].tag {
    93  		return x[i].tag
    94  	}
    95  	return byIndex(x).Less(i, j)
    96  }
    97  
    98  // byIndex sorts field by index sequence.
    99  type byIndex []field
   100  
   101  func (x byIndex) Len() int { return len(x) }
   102  
   103  func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   104  
   105  func (x byIndex) Less(i, j int) bool {
   106  	for k, xik := range x[i].index {
   107  		if k >= len(x[j].index) {
   108  			return false
   109  		}
   110  		if xik != x[j].index[k] {
   111  			return xik < x[j].index[k]
   112  		}
   113  	}
   114  	return len(x[i].index) < len(x[j].index)
   115  }
   116  
   117  // typeFields returns a list of fields that JSON should recognize for the given type.
   118  // The algorithm is breadth-first search over the set of structs to include - the top struct
   119  // and then any reachable anonymous structs.
   120  func typeFields(t reflect.Type) []field {
   121  	// Anonymous fields to explore at the current level and the next.
   122  	current := []field{}
   123  	next := []field{{typ: t}}
   124  
   125  	// Count of queued names for current level and the next.
   126  	count := map[reflect.Type]int{}
   127  	nextCount := map[reflect.Type]int{}
   128  
   129  	// Types already visited at an earlier level.
   130  	visited := map[reflect.Type]bool{}
   131  
   132  	// Fields found.
   133  	var fields []field
   134  
   135  	for len(next) > 0 {
   136  		current, next = next, current[:0]
   137  		count, nextCount = nextCount, map[reflect.Type]int{}
   138  
   139  		for _, f := range current {
   140  			if visited[f.typ] {
   141  				continue
   142  			}
   143  			visited[f.typ] = true
   144  
   145  			// Scan f.typ for fields to include.
   146  			for i := 0; i < f.typ.NumField(); i++ {
   147  				sf := f.typ.Field(i)
   148  				if sf.PkgPath != "" { // unexported
   149  					continue
   150  				}
   151  				tag := sf.Tag.Get("json")
   152  				if tag == "-" {
   153  					continue
   154  				}
   155  				name, opts := parseTag(tag)
   156  				if !isValidTag(name) {
   157  					name = ""
   158  				}
   159  				index := make([]int, len(f.index)+1)
   160  				copy(index, f.index)
   161  				index[len(f.index)] = i
   162  
   163  				ft := sf.Type
   164  				if ft.Name() == "" && ft.Kind() == reflect.Ptr {
   165  					// Follow pointer.
   166  					ft = ft.Elem()
   167  				}
   168  
   169  				// Record found field and index sequence.
   170  				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
   171  					tagged := name != ""
   172  					if name == "" {
   173  						name = sf.Name
   174  					}
   175  					fields = append(fields, fillField(field{
   176  						name:      name,
   177  						tag:       tagged,
   178  						index:     index,
   179  						typ:       ft,
   180  						omitEmpty: opts.Contains("omitempty"),
   181  						quoted:    opts.Contains("string"),
   182  					}))
   183  					if count[f.typ] > 1 {
   184  						// If there were multiple instances, add a second,
   185  						// so that the annihilation code will see a duplicate.
   186  						// It only cares about the distinction between 1 or 2,
   187  						// so don't bother generating any more copies.
   188  						fields = append(fields, fields[len(fields)-1])
   189  					}
   190  					continue
   191  				}
   192  
   193  				// Record new anonymous struct to explore in next round.
   194  				nextCount[ft]++
   195  				if nextCount[ft] == 1 {
   196  					next = append(next, fillField(field{name: ft.Name(), index: index, typ: ft}))
   197  				}
   198  			}
   199  		}
   200  	}
   201  
   202  	sort.Sort(byName(fields))
   203  
   204  	// Delete all fields that are hidden by the Go rules for embedded fields,
   205  	// except that fields with JSON tags are promoted.
   206  
   207  	// The fields are sorted in primary order of name, secondary order
   208  	// of field index length. Loop over names; for each name, delete
   209  	// hidden fields by choosing the one dominant field that survives.
   210  	out := fields[:0]
   211  	for advance, i := 0, 0; i < len(fields); i += advance {
   212  		// One iteration per name.
   213  		// Find the sequence of fields with the name of this first field.
   214  		fi := fields[i]
   215  		name := fi.name
   216  		for advance = 1; i+advance < len(fields); advance++ {
   217  			fj := fields[i+advance]
   218  			if fj.name != name {
   219  				break
   220  			}
   221  		}
   222  		if advance == 1 { // Only one field with this name
   223  			out = append(out, fi)
   224  			continue
   225  		}
   226  		dominant, ok := dominantField(fields[i : i+advance])
   227  		if ok {
   228  			out = append(out, dominant)
   229  		}
   230  	}
   231  
   232  	fields = out
   233  	sort.Sort(byIndex(fields))
   234  
   235  	return fields
   236  }
   237  
   238  // dominantField looks through the fields, all of which are known to
   239  // have the same name, to find the single field that dominates the
   240  // others using Go's embedding rules, modified by the presence of
   241  // JSON tags. If there are multiple top-level fields, the boolean
   242  // will be false: This condition is an error in Go and we skip all
   243  // the fields.
   244  func dominantField(fields []field) (field, bool) {
   245  	// The fields are sorted in increasing index-length order. The winner
   246  	// must therefore be one with the shortest index length. Drop all
   247  	// longer entries, which is easy: just truncate the slice.
   248  	length := len(fields[0].index)
   249  	tagged := -1 // Index of first tagged field.
   250  	for i, f := range fields {
   251  		if len(f.index) > length {
   252  			fields = fields[:i]
   253  			break
   254  		}
   255  		if f.tag {
   256  			if tagged >= 0 {
   257  				// Multiple tagged fields at the same level: conflict.
   258  				// Return no field.
   259  				return field{}, false
   260  			}
   261  			tagged = i
   262  		}
   263  	}
   264  	if tagged >= 0 {
   265  		return fields[tagged], true
   266  	}
   267  	// All remaining fields have the same length. If there's more than one,
   268  	// we have a conflict (two fields named "X" at the same level) and we
   269  	// return no field.
   270  	if len(fields) > 1 {
   271  		return field{}, false
   272  	}
   273  	return fields[0], true
   274  }
   275  
   276  var fieldCache struct {
   277  	sync.RWMutex
   278  	m map[reflect.Type][]field
   279  }
   280  
   281  // cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
   282  func cachedTypeFields(t reflect.Type) []field {
   283  	fieldCache.RLock()
   284  	f := fieldCache.m[t]
   285  	fieldCache.RUnlock()
   286  	if f != nil {
   287  		return f
   288  	}
   289  
   290  	// Compute fields without lock.
   291  	// Might duplicate effort but won't hold other computations back.
   292  	f = typeFields(t)
   293  	if f == nil {
   294  		f = []field{}
   295  	}
   296  
   297  	fieldCache.Lock()
   298  	if fieldCache.m == nil {
   299  		fieldCache.m = map[reflect.Type][]field{}
   300  	}
   301  	fieldCache.m[t] = f
   302  	fieldCache.Unlock()
   303  	return f
   304  }
   305  
   306  func isValidTag(s string) bool {
   307  	if s == "" {
   308  		return false
   309  	}
   310  	for _, c := range s {
   311  		switch {
   312  		case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
   313  			// Backslash and quote chars are reserved, but
   314  			// otherwise any punctuation chars are allowed
   315  			// in a tag name.
   316  		default:
   317  			if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
   318  				return false
   319  			}
   320  		}
   321  	}
   322  	return true
   323  }
   324  
   325  const (
   326  	caseMask     = ^byte(0x20) // Mask to ignore case in ASCII.
   327  	kelvin       = '\u212a'
   328  	smallLongEss = '\u017f'
   329  )
   330  
   331  // foldFunc returns one of four different case folding equivalence
   332  // functions, from most general (and slow) to fastest:
   333  //
   334  // 1) bytes.EqualFold, if the key s contains any non-ASCII UTF-8
   335  // 2) equalFoldRight, if s contains special folding ASCII ('k', 'K', 's', 'S')
   336  // 3) asciiEqualFold, no special, but includes non-letters (including _)
   337  // 4) simpleLetterEqualFold, no specials, no non-letters.
   338  //
   339  // The letters S and K are special because they map to 3 runes, not just 2:
   340  //  * S maps to s and to U+017F 'ſ' Latin small letter long s
   341  //  * k maps to K and to U+212A 'K' Kelvin sign
   342  // See http://play.golang.org/p/tTxjOc0OGo
   343  //
   344  // The returned function is specialized for matching against s and
   345  // should only be given s. It's not curried for performance reasons.
   346  func foldFunc(s []byte) func(s, t []byte) bool {
   347  	nonLetter := false
   348  	special := false // special letter
   349  	for _, b := range s {
   350  		if b >= utf8.RuneSelf {
   351  			return bytes.EqualFold
   352  		}
   353  		upper := b & caseMask
   354  		if upper < 'A' || upper > 'Z' {
   355  			nonLetter = true
   356  		} else if upper == 'K' || upper == 'S' {
   357  			// See above for why these letters are special.
   358  			special = true
   359  		}
   360  	}
   361  	if special {
   362  		return equalFoldRight
   363  	}
   364  	if nonLetter {
   365  		return asciiEqualFold
   366  	}
   367  	return simpleLetterEqualFold
   368  }
   369  
   370  // equalFoldRight is a specialization of bytes.EqualFold when s is
   371  // known to be all ASCII (including punctuation), but contains an 's',
   372  // 'S', 'k', or 'K', requiring a Unicode fold on the bytes in t.
   373  // See comments on foldFunc.
   374  func equalFoldRight(s, t []byte) bool {
   375  	for _, sb := range s {
   376  		if len(t) == 0 {
   377  			return false
   378  		}
   379  		tb := t[0]
   380  		if tb < utf8.RuneSelf {
   381  			if sb != tb {
   382  				sbUpper := sb & caseMask
   383  				if 'A' <= sbUpper && sbUpper <= 'Z' {
   384  					if sbUpper != tb&caseMask {
   385  						return false
   386  					}
   387  				} else {
   388  					return false
   389  				}
   390  			}
   391  			t = t[1:]
   392  			continue
   393  		}
   394  		// sb is ASCII and t is not. t must be either kelvin
   395  		// sign or long s; sb must be s, S, k, or K.
   396  		tr, size := utf8.DecodeRune(t)
   397  		switch sb {
   398  		case 's', 'S':
   399  			if tr != smallLongEss {
   400  				return false
   401  			}
   402  		case 'k', 'K':
   403  			if tr != kelvin {
   404  				return false
   405  			}
   406  		default:
   407  			return false
   408  		}
   409  		t = t[size:]
   410  
   411  	}
   412  	if len(t) > 0 {
   413  		return false
   414  	}
   415  	return true
   416  }
   417  
   418  // asciiEqualFold is a specialization of bytes.EqualFold for use when
   419  // s is all ASCII (but may contain non-letters) and contains no
   420  // special-folding letters.
   421  // See comments on foldFunc.
   422  func asciiEqualFold(s, t []byte) bool {
   423  	if len(s) != len(t) {
   424  		return false
   425  	}
   426  	for i, sb := range s {
   427  		tb := t[i]
   428  		if sb == tb {
   429  			continue
   430  		}
   431  		if ('a' <= sb && sb <= 'z') || ('A' <= sb && sb <= 'Z') {
   432  			if sb&caseMask != tb&caseMask {
   433  				return false
   434  			}
   435  		} else {
   436  			return false
   437  		}
   438  	}
   439  	return true
   440  }
   441  
   442  // simpleLetterEqualFold is a specialization of bytes.EqualFold for
   443  // use when s is all ASCII letters (no underscores, etc) and also
   444  // doesn't contain 'k', 'K', 's', or 'S'.
   445  // See comments on foldFunc.
   446  func simpleLetterEqualFold(s, t []byte) bool {
   447  	if len(s) != len(t) {
   448  		return false
   449  	}
   450  	for i, b := range s {
   451  		if b&caseMask != t[i]&caseMask {
   452  			return false
   453  		}
   454  	}
   455  	return true
   456  }
   457  
   458  // tagOptions is the string following a comma in a struct field's "json"
   459  // tag, or the empty string. It does not include the leading comma.
   460  type tagOptions string
   461  
   462  // parseTag splits a struct field's json tag into its name and
   463  // comma-separated options.
   464  func parseTag(tag string) (string, tagOptions) {
   465  	if idx := strings.Index(tag, ","); idx != -1 {
   466  		return tag[:idx], tagOptions(tag[idx+1:])
   467  	}
   468  	return tag, tagOptions("")
   469  }
   470  
   471  // Contains reports whether a comma-separated list of options
   472  // contains a particular substr flag. substr must be surrounded by a
   473  // string boundary or commas.
   474  func (o tagOptions) Contains(optionName string) bool {
   475  	if len(o) == 0 {
   476  		return false
   477  	}
   478  	s := string(o)
   479  	for s != "" {
   480  		var next string
   481  		i := strings.Index(s, ",")
   482  		if i >= 0 {
   483  			s, next = s[:i], s[i+1:]
   484  		}
   485  		if s == optionName {
   486  			return true
   487  		}
   488  		s = next
   489  	}
   490  	return false
   491  }