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 }