github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/converter.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package conversion 18 19 import ( 20 "fmt" 21 "reflect" 22 ) 23 24 type typePair struct { 25 source reflect.Type 26 dest reflect.Type 27 } 28 29 type typeNamePair struct { 30 fieldType reflect.Type 31 fieldName string 32 } 33 34 // DebugLogger allows you to get debugging messages if necessary. 35 type DebugLogger interface { 36 Logf(format string, args ...interface{}) 37 } 38 39 type NameFunc func(t reflect.Type) string 40 41 var DefaultNameFunc = func(t reflect.Type) string { return t.Name() } 42 43 type GenericConversionFunc func(a, b interface{}, scope Scope) (bool, error) 44 45 // Converter knows how to convert one type to another. 46 type Converter struct { 47 // Map from the conversion pair to a function which can 48 // do the conversion. 49 conversionFuncs ConversionFuncs 50 generatedConversionFuncs ConversionFuncs 51 52 // genericConversions are called during normal conversion to offer a "fast-path" 53 // that avoids all reflection. These methods are not called outside of the .Convert() 54 // method. 55 genericConversions []GenericConversionFunc 56 57 // Set of conversions that should be treated as a no-op 58 ignoredConversions map[typePair]struct{} 59 60 // This is a map from a source field type and name, to a list of destination 61 // field type and name. 62 structFieldDests map[typeNamePair][]typeNamePair 63 64 // Allows for the opposite lookup of structFieldDests. So that SourceFromDest 65 // copy flag also works. So this is a map of destination field name, to potential 66 // source field name and type to look for. 67 structFieldSources map[typeNamePair][]typeNamePair 68 69 // Map from a type to a function which applies defaults. 70 defaultingFuncs map[reflect.Type]reflect.Value 71 72 // Similar to above, but function is stored as interface{}. 73 defaultingInterfaces map[reflect.Type]interface{} 74 75 // Map from an input type to a function which can apply a key name mapping 76 inputFieldMappingFuncs map[reflect.Type]FieldMappingFunc 77 78 // Map from an input type to a set of default conversion flags. 79 inputDefaultFlags map[reflect.Type]FieldMatchingFlags 80 81 // If non-nil, will be called to print helpful debugging info. Quite verbose. 82 Debug DebugLogger 83 84 // nameFunc is called to retrieve the name of a type; this name is used for the 85 // purpose of deciding whether two types match or not (i.e., will we attempt to 86 // do a conversion). The default returns the go type name. 87 nameFunc func(t reflect.Type) string 88 } 89 90 // NewConverter creates a new Converter object. 91 func NewConverter(nameFn NameFunc) *Converter { 92 c := &Converter{ 93 conversionFuncs: NewConversionFuncs(), 94 generatedConversionFuncs: NewConversionFuncs(), 95 ignoredConversions: make(map[typePair]struct{}), 96 defaultingFuncs: make(map[reflect.Type]reflect.Value), 97 defaultingInterfaces: make(map[reflect.Type]interface{}), 98 nameFunc: nameFn, 99 structFieldDests: make(map[typeNamePair][]typeNamePair), 100 structFieldSources: make(map[typeNamePair][]typeNamePair), 101 102 inputFieldMappingFuncs: make(map[reflect.Type]FieldMappingFunc), 103 inputDefaultFlags: make(map[reflect.Type]FieldMatchingFlags), 104 } 105 c.RegisterConversionFunc(Convert_Slice_byte_To_Slice_byte) 106 return c 107 } 108 109 // AddGenericConversionFunc adds a function that accepts the ConversionFunc call pattern 110 // (for two conversion types) to the converter. These functions are checked first during 111 // a normal conversion, but are otherwise not called. Use AddConversionFuncs when registering 112 // typed conversions. 113 func (c *Converter) AddGenericConversionFunc(fn GenericConversionFunc) { 114 c.genericConversions = append(c.genericConversions, fn) 115 } 116 117 // WithConversions returns a Converter that is a copy of c but with the additional 118 // fns merged on top. 119 func (c *Converter) WithConversions(fns ConversionFuncs) *Converter { 120 copied := *c 121 copied.conversionFuncs = c.conversionFuncs.Merge(fns) 122 return &copied 123 } 124 125 // DefaultMeta returns the conversion FieldMappingFunc and meta for a given type. 126 func (c *Converter) DefaultMeta(t reflect.Type) (FieldMatchingFlags, *Meta) { 127 return c.inputDefaultFlags[t], &Meta{ 128 KeyNameMapping: c.inputFieldMappingFuncs[t], 129 } 130 } 131 132 // Convert_Slice_byte_To_Slice_byte prevents recursing into every byte 133 func Convert_Slice_byte_To_Slice_byte(in *[]byte, out *[]byte, s Scope) error { 134 if *in == nil { 135 *out = nil 136 return nil 137 } 138 *out = make([]byte, len(*in)) 139 copy(*out, *in) 140 return nil 141 } 142 143 // Scope is passed to conversion funcs to allow them to continue an ongoing conversion. 144 // If multiple converters exist in the system, Scope will allow you to use the correct one 145 // from a conversion function--that is, the one your conversion function was called by. 146 type Scope interface { 147 // Call Convert to convert sub-objects. Note that if you call it with your own exact 148 // parameters, you'll run out of stack space before anything useful happens. 149 Convert(src, dest interface{}, flags FieldMatchingFlags) error 150 151 // DefaultConvert performs the default conversion, without calling a conversion func 152 // on the current stack frame. This makes it safe to call from a conversion func. 153 DefaultConvert(src, dest interface{}, flags FieldMatchingFlags) error 154 155 // If registered, returns a function applying defaults for objects of a given type. 156 // Used for automatically generating conversion functions. 157 DefaultingInterface(inType reflect.Type) (interface{}, bool) 158 159 // SrcTags and DestTags contain the struct tags that src and dest had, respectively. 160 // If the enclosing object was not a struct, then these will contain no tags, of course. 161 SrcTag() reflect.StructTag 162 DestTag() reflect.StructTag 163 164 // Flags returns the flags with which the conversion was started. 165 Flags() FieldMatchingFlags 166 167 // Meta returns any information originally passed to Convert. 168 Meta() *Meta 169 } 170 171 // FieldMappingFunc can convert an input field value into different values, depending on 172 // the value of the source or destination struct tags. 173 type FieldMappingFunc func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string) 174 175 func NewConversionFuncs() ConversionFuncs { 176 return ConversionFuncs{fns: make(map[typePair]reflect.Value)} 177 } 178 179 type ConversionFuncs struct { 180 fns map[typePair]reflect.Value 181 } 182 183 // Add adds the provided conversion functions to the lookup table - they must have the signature 184 // `func(type1, type2, Scope) error`. Functions are added in the order passed and will override 185 // previously registered pairs. 186 func (c ConversionFuncs) Add(fns ...interface{}) error { 187 for _, fn := range fns { 188 fv := reflect.ValueOf(fn) 189 ft := fv.Type() 190 if err := verifyConversionFunctionSignature(ft); err != nil { 191 return err 192 } 193 c.fns[typePair{ft.In(0).Elem(), ft.In(1).Elem()}] = fv 194 } 195 return nil 196 } 197 198 // Merge returns a new ConversionFuncs that contains all conversions from 199 // both other and c, with other conversions taking precedence. 200 func (c ConversionFuncs) Merge(other ConversionFuncs) ConversionFuncs { 201 merged := NewConversionFuncs() 202 for k, v := range c.fns { 203 merged.fns[k] = v 204 } 205 for k, v := range other.fns { 206 merged.fns[k] = v 207 } 208 return merged 209 } 210 211 // Meta is supplied by Scheme, when it calls Convert. 212 type Meta struct { 213 // KeyNameMapping is an optional function which may map the listed key (field name) 214 // into a source and destination value. 215 KeyNameMapping FieldMappingFunc 216 } 217 218 // scope contains information about an ongoing conversion. 219 type scope struct { 220 converter *Converter 221 meta *Meta 222 flags FieldMatchingFlags 223 224 // srcStack & destStack are separate because they may not have a 1:1 225 // relationship. 226 srcStack scopeStack 227 destStack scopeStack 228 } 229 230 type scopeStackElem struct { 231 tag reflect.StructTag 232 value reflect.Value 233 key string 234 } 235 236 type scopeStack []scopeStackElem 237 238 func (s *scopeStack) pop() { 239 n := len(*s) 240 *s = (*s)[:n-1] 241 } 242 243 func (s *scopeStack) push(e scopeStackElem) { 244 *s = append(*s, e) 245 } 246 247 func (s *scopeStack) top() *scopeStackElem { 248 return &(*s)[len(*s)-1] 249 } 250 251 func (s scopeStack) describe() string { 252 desc := "" 253 if len(s) > 1 { 254 desc = "(" + s[1].value.Type().String() + ")" 255 } 256 for i, v := range s { 257 if i < 2 { 258 // First layer on stack is not real; second is handled specially above. 259 continue 260 } 261 if v.key == "" { 262 desc += fmt.Sprintf(".%v", v.value.Type()) 263 } else { 264 desc += fmt.Sprintf(".%v", v.key) 265 } 266 } 267 return desc 268 } 269 270 func (s *scope) DefaultingInterface(inType reflect.Type) (interface{}, bool) { 271 value, found := s.converter.defaultingInterfaces[inType] 272 return value, found 273 } 274 275 // Formats src & dest as indices for printing. 276 func (s *scope) setIndices(src, dest int) { 277 s.srcStack.top().key = fmt.Sprintf("[%v]", src) 278 s.destStack.top().key = fmt.Sprintf("[%v]", dest) 279 } 280 281 // Formats src & dest as map keys for printing. 282 func (s *scope) setKeys(src, dest interface{}) { 283 s.srcStack.top().key = fmt.Sprintf(`["%v"]`, src) 284 s.destStack.top().key = fmt.Sprintf(`["%v"]`, dest) 285 } 286 287 // Convert continues a conversion. 288 func (s *scope) Convert(src, dest interface{}, flags FieldMatchingFlags) error { 289 return s.converter.Convert(src, dest, flags, s.meta) 290 } 291 292 // DefaultConvert continues a conversion, performing a default conversion (no conversion func) 293 // for the current stack frame. 294 func (s *scope) DefaultConvert(src, dest interface{}, flags FieldMatchingFlags) error { 295 return s.converter.DefaultConvert(src, dest, flags, s.meta) 296 } 297 298 // SrcTag returns the tag of the struct containing the current source item, if any. 299 func (s *scope) SrcTag() reflect.StructTag { 300 return s.srcStack.top().tag 301 } 302 303 // DestTag returns the tag of the struct containing the current dest item, if any. 304 func (s *scope) DestTag() reflect.StructTag { 305 return s.destStack.top().tag 306 } 307 308 // Flags returns the flags with which the current conversion was started. 309 func (s *scope) Flags() FieldMatchingFlags { 310 return s.flags 311 } 312 313 // Meta returns the meta object that was originally passed to Convert. 314 func (s *scope) Meta() *Meta { 315 return s.meta 316 } 317 318 // describe prints the path to get to the current (source, dest) values. 319 func (s *scope) describe() (src, dest string) { 320 return s.srcStack.describe(), s.destStack.describe() 321 } 322 323 // error makes an error that includes information about where we were in the objects 324 // we were asked to convert. 325 func (s *scope) errorf(message string, args ...interface{}) error { 326 srcPath, destPath := s.describe() 327 where := fmt.Sprintf("converting %v to %v: ", srcPath, destPath) 328 return fmt.Errorf(where+message, args...) 329 } 330 331 // Verifies whether a conversion function has a correct signature. 332 func verifyConversionFunctionSignature(ft reflect.Type) error { 333 if ft.Kind() != reflect.Func { 334 return fmt.Errorf("expected func, got: %v", ft) 335 } 336 if ft.NumIn() != 3 { 337 return fmt.Errorf("expected three 'in' params, got: %v", ft) 338 } 339 if ft.NumOut() != 1 { 340 return fmt.Errorf("expected one 'out' param, got: %v", ft) 341 } 342 if ft.In(0).Kind() != reflect.Ptr { 343 return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft) 344 } 345 if ft.In(1).Kind() != reflect.Ptr { 346 return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) 347 } 348 scopeType := Scope(nil) 349 if e, a := reflect.TypeOf(&scopeType).Elem(), ft.In(2); e != a { 350 return fmt.Errorf("expected '%v' arg for 'in' param 2, got '%v' (%v)", e, a, ft) 351 } 352 var forErrorType error 353 // This convolution is necessary, otherwise TypeOf picks up on the fact 354 // that forErrorType is nil. 355 errorType := reflect.TypeOf(&forErrorType).Elem() 356 if ft.Out(0) != errorType { 357 return fmt.Errorf("expected error return, got: %v", ft) 358 } 359 return nil 360 } 361 362 // RegisterConversionFunc registers a conversion func with the 363 // Converter. conversionFunc must take three parameters: a pointer to the input 364 // type, a pointer to the output type, and a conversion.Scope (which should be 365 // used if recursive conversion calls are desired). It must return an error. 366 // 367 // Example: 368 // c.RegisterConversionFunc( 369 // func(in *Pod, out *v1.Pod, s Scope) error { 370 // // conversion logic... 371 // return nil 372 // }) 373 func (c *Converter) RegisterConversionFunc(conversionFunc interface{}) error { 374 return c.conversionFuncs.Add(conversionFunc) 375 } 376 377 // Similar to RegisterConversionFunc, but registers conversion function that were 378 // automatically generated. 379 func (c *Converter) RegisterGeneratedConversionFunc(conversionFunc interface{}) error { 380 return c.generatedConversionFuncs.Add(conversionFunc) 381 } 382 383 // RegisterIgnoredConversion registers a "no-op" for conversion, where any requested 384 // conversion between from and to is ignored. 385 func (c *Converter) RegisterIgnoredConversion(from, to interface{}) error { 386 typeFrom := reflect.TypeOf(from) 387 typeTo := reflect.TypeOf(to) 388 if reflect.TypeOf(from).Kind() != reflect.Ptr { 389 return fmt.Errorf("expected pointer arg for 'from' param 0, got: %v", typeFrom) 390 } 391 if typeTo.Kind() != reflect.Ptr { 392 return fmt.Errorf("expected pointer arg for 'to' param 1, got: %v", typeTo) 393 } 394 c.ignoredConversions[typePair{typeFrom.Elem(), typeTo.Elem()}] = struct{}{} 395 return nil 396 } 397 398 // IsConversionIgnored returns true if the specified objects should be dropped during 399 // conversion. 400 func (c *Converter) IsConversionIgnored(inType, outType reflect.Type) bool { 401 _, found := c.ignoredConversions[typePair{inType, outType}] 402 return found 403 } 404 405 func (c *Converter) HasConversionFunc(inType, outType reflect.Type) bool { 406 _, found := c.conversionFuncs.fns[typePair{inType, outType}] 407 return found 408 } 409 410 func (c *Converter) ConversionFuncValue(inType, outType reflect.Type) (reflect.Value, bool) { 411 value, found := c.conversionFuncs.fns[typePair{inType, outType}] 412 return value, found 413 } 414 415 // SetStructFieldCopy registers a correspondence. Whenever a struct field is encountered 416 // which has a type and name matching srcFieldType and srcFieldName, it wil be copied 417 // into the field in the destination struct matching destFieldType & Name, if such a 418 // field exists. 419 // May be called multiple times, even for the same source field & type--all applicable 420 // copies will be performed. 421 func (c *Converter) SetStructFieldCopy(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error { 422 st := reflect.TypeOf(srcFieldType) 423 dt := reflect.TypeOf(destFieldType) 424 srcKey := typeNamePair{st, srcFieldName} 425 destKey := typeNamePair{dt, destFieldName} 426 c.structFieldDests[srcKey] = append(c.structFieldDests[srcKey], destKey) 427 c.structFieldSources[destKey] = append(c.structFieldSources[destKey], srcKey) 428 return nil 429 } 430 431 // RegisterDefaultingFunc registers a value-defaulting func with the Converter. 432 // defaultingFunc must take one parameters: a pointer to the input type. 433 // 434 // Example: 435 // c.RegisteDefaultingFunc( 436 // func(in *v1.Pod) { 437 // // defaulting logic... 438 // }) 439 func (c *Converter) RegisterDefaultingFunc(defaultingFunc interface{}) error { 440 fv := reflect.ValueOf(defaultingFunc) 441 ft := fv.Type() 442 if ft.Kind() != reflect.Func { 443 return fmt.Errorf("expected func, got: %v", ft) 444 } 445 if ft.NumIn() != 1 { 446 return fmt.Errorf("expected one 'in' param, got: %v", ft) 447 } 448 if ft.NumOut() != 0 { 449 return fmt.Errorf("expected zero 'out' params, got: %v", ft) 450 } 451 if ft.In(0).Kind() != reflect.Ptr { 452 return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft) 453 } 454 inType := ft.In(0).Elem() 455 c.defaultingFuncs[inType] = fv 456 c.defaultingInterfaces[inType] = defaultingFunc 457 return nil 458 } 459 460 // RegisterInputDefaults registers a field name mapping function, used when converting 461 // from maps to structs. Inputs to the conversion methods are checked for this type and a mapping 462 // applied automatically if the input matches in. A set of default flags for the input conversion 463 // may also be provided, which will be used when no explicit flags are requested. 464 func (c *Converter) RegisterInputDefaults(in interface{}, fn FieldMappingFunc, defaultFlags FieldMatchingFlags) error { 465 fv := reflect.ValueOf(in) 466 ft := fv.Type() 467 if ft.Kind() != reflect.Ptr { 468 return fmt.Errorf("expected pointer 'in' argument, got: %v", ft) 469 } 470 c.inputFieldMappingFuncs[ft] = fn 471 c.inputDefaultFlags[ft] = defaultFlags 472 return nil 473 } 474 475 // FieldMatchingFlags contains a list of ways in which struct fields could be 476 // copied. These constants may be | combined. 477 type FieldMatchingFlags int 478 479 const ( 480 // Loop through destination fields, search for matching source 481 // field to copy it from. Source fields with no corresponding 482 // destination field will be ignored. If SourceToDest is 483 // specified, this flag is ignored. If neither is specified, 484 // or no flags are passed, this flag is the default. 485 DestFromSource FieldMatchingFlags = 0 486 // Loop through source fields, search for matching dest field 487 // to copy it into. Destination fields with no corresponding 488 // source field will be ignored. 489 SourceToDest FieldMatchingFlags = 1 << iota 490 // Don't treat it as an error if the corresponding source or 491 // dest field can't be found. 492 IgnoreMissingFields 493 // Don't require type names to match. 494 AllowDifferentFieldTypeNames 495 ) 496 497 // IsSet returns true if the given flag or combination of flags is set. 498 func (f FieldMatchingFlags) IsSet(flag FieldMatchingFlags) bool { 499 if flag == DestFromSource { 500 // The bit logic doesn't work on the default value. 501 return f&SourceToDest != SourceToDest 502 } 503 return f&flag == flag 504 } 505 506 // Convert will translate src to dest if it knows how. Both must be pointers. 507 // If no conversion func is registered and the default copying mechanism 508 // doesn't work on this type pair, an error will be returned. 509 // Read the comments on the various FieldMatchingFlags constants to understand 510 // what the 'flags' parameter does. 511 // 'meta' is given to allow you to pass information to conversion functions, 512 // it is not used by Convert() other than storing it in the scope. 513 // Not safe for objects with cyclic references! 514 func (c *Converter) Convert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error { 515 if len(c.genericConversions) > 0 { 516 // TODO: avoid scope allocation 517 s := &scope{converter: c, flags: flags, meta: meta} 518 for _, fn := range c.genericConversions { 519 if ok, err := fn(src, dest, s); ok { 520 return err 521 } 522 } 523 } 524 return c.doConversion(src, dest, flags, meta, c.convert) 525 } 526 527 // DefaultConvert will translate src to dest if it knows how. Both must be pointers. 528 // No conversion func is used. If the default copying mechanism 529 // doesn't work on this type pair, an error will be returned. 530 // Read the comments on the various FieldMatchingFlags constants to understand 531 // what the 'flags' parameter does. 532 // 'meta' is given to allow you to pass information to conversion functions, 533 // it is not used by DefaultConvert() other than storing it in the scope. 534 // Not safe for objects with cyclic references! 535 func (c *Converter) DefaultConvert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error { 536 return c.doConversion(src, dest, flags, meta, c.defaultConvert) 537 } 538 539 type conversionFunc func(sv, dv reflect.Value, scope *scope) error 540 541 func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags, meta *Meta, f conversionFunc) error { 542 dv, err := EnforcePtr(dest) 543 if err != nil { 544 return err 545 } 546 if !dv.CanAddr() && !dv.CanSet() { 547 return fmt.Errorf("can't write to dest") 548 } 549 sv, err := EnforcePtr(src) 550 if err != nil { 551 return err 552 } 553 s := &scope{ 554 converter: c, 555 flags: flags, 556 meta: meta, 557 } 558 // Leave something on the stack, so that calls to struct tag getters never fail. 559 s.srcStack.push(scopeStackElem{}) 560 s.destStack.push(scopeStackElem{}) 561 return f(sv, dv, s) 562 } 563 564 // callCustom calls 'custom' with sv & dv. custom must be a conversion function. 565 func (c *Converter) callCustom(sv, dv, custom reflect.Value, scope *scope) error { 566 if !sv.CanAddr() { 567 sv2 := reflect.New(sv.Type()) 568 sv2.Elem().Set(sv) 569 sv = sv2 570 } else { 571 sv = sv.Addr() 572 } 573 if !dv.CanAddr() { 574 if !dv.CanSet() { 575 return scope.errorf("can't addr or set dest.") 576 } 577 dvOrig := dv 578 dv := reflect.New(dvOrig.Type()) 579 defer func() { dvOrig.Set(dv) }() 580 } else { 581 dv = dv.Addr() 582 } 583 args := []reflect.Value{sv, dv, reflect.ValueOf(scope)} 584 ret := custom.Call(args)[0].Interface() 585 // This convolution is necessary because nil interfaces won't convert 586 // to errors. 587 if ret == nil { 588 return nil 589 } 590 return ret.(error) 591 } 592 593 // convert recursively copies sv into dv, calling an appropriate conversion function if 594 // one is registered. 595 func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error { 596 dt, st := dv.Type(), sv.Type() 597 // Apply default values. 598 if fv, ok := c.defaultingFuncs[st]; ok { 599 if c.Debug != nil { 600 c.Debug.Logf("Applying defaults for '%v'", st) 601 } 602 args := []reflect.Value{sv.Addr()} 603 fv.Call(args) 604 } 605 606 pair := typePair{st, dt} 607 608 // ignore conversions of this type 609 if _, ok := c.ignoredConversions[pair]; ok { 610 if c.Debug != nil { 611 c.Debug.Logf("Ignoring conversion of '%v' to '%v'", st, dt) 612 } 613 return nil 614 } 615 616 // Convert sv to dv. 617 if fv, ok := c.conversionFuncs.fns[pair]; ok { 618 if c.Debug != nil { 619 c.Debug.Logf("Calling custom conversion of '%v' to '%v'", st, dt) 620 } 621 return c.callCustom(sv, dv, fv, scope) 622 } 623 if fv, ok := c.generatedConversionFuncs.fns[pair]; ok { 624 if c.Debug != nil { 625 c.Debug.Logf("Calling generated conversion of '%v' to '%v'", st, dt) 626 } 627 return c.callCustom(sv, dv, fv, scope) 628 } 629 630 return c.defaultConvert(sv, dv, scope) 631 } 632 633 // defaultConvert recursively copies sv into dv. no conversion function is called 634 // for the current stack frame (but conversion functions may be called for nested objects) 635 func (c *Converter) defaultConvert(sv, dv reflect.Value, scope *scope) error { 636 dt, st := dv.Type(), sv.Type() 637 638 if !dv.CanSet() { 639 return scope.errorf("Cannot set dest. (Tried to deep copy something with unexported fields?)") 640 } 641 642 if !scope.flags.IsSet(AllowDifferentFieldTypeNames) && c.nameFunc(dt) != c.nameFunc(st) { 643 return scope.errorf( 644 "type names don't match (%v, %v), and no conversion 'func (%v, %v) error' registered.", 645 c.nameFunc(st), c.nameFunc(dt), st, dt) 646 } 647 648 switch st.Kind() { 649 case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct: 650 // Don't copy these via assignment/conversion! 651 default: 652 // This should handle all simple types. 653 if st.AssignableTo(dt) { 654 dv.Set(sv) 655 return nil 656 } 657 if st.ConvertibleTo(dt) { 658 dv.Set(sv.Convert(dt)) 659 return nil 660 } 661 } 662 663 if c.Debug != nil { 664 c.Debug.Logf("Trying to convert '%v' to '%v'", st, dt) 665 } 666 667 scope.srcStack.push(scopeStackElem{value: sv}) 668 scope.destStack.push(scopeStackElem{value: dv}) 669 defer scope.srcStack.pop() 670 defer scope.destStack.pop() 671 672 switch dv.Kind() { 673 case reflect.Struct: 674 return c.convertKV(toKVValue(sv), toKVValue(dv), scope) 675 case reflect.Slice: 676 if sv.IsNil() { 677 // Don't make a zero-length slice. 678 dv.Set(reflect.Zero(dt)) 679 return nil 680 } 681 dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap())) 682 for i := 0; i < sv.Len(); i++ { 683 scope.setIndices(i, i) 684 if err := c.convert(sv.Index(i), dv.Index(i), scope); err != nil { 685 return err 686 } 687 } 688 case reflect.Ptr: 689 if sv.IsNil() { 690 // Don't copy a nil ptr! 691 dv.Set(reflect.Zero(dt)) 692 return nil 693 } 694 dv.Set(reflect.New(dt.Elem())) 695 switch st.Kind() { 696 case reflect.Ptr, reflect.Interface: 697 return c.convert(sv.Elem(), dv.Elem(), scope) 698 default: 699 return c.convert(sv, dv.Elem(), scope) 700 } 701 case reflect.Map: 702 if sv.IsNil() { 703 // Don't copy a nil ptr! 704 dv.Set(reflect.Zero(dt)) 705 return nil 706 } 707 dv.Set(reflect.MakeMap(dt)) 708 for _, sk := range sv.MapKeys() { 709 dk := reflect.New(dt.Key()).Elem() 710 if err := c.convert(sk, dk, scope); err != nil { 711 return err 712 } 713 dkv := reflect.New(dt.Elem()).Elem() 714 scope.setKeys(sk.Interface(), dk.Interface()) 715 // TODO: sv.MapIndex(sk) may return a value with CanAddr() == false, 716 // because a map[string]struct{} does not allow a pointer reference. 717 // Calling a custom conversion function defined for the map value 718 // will panic. Example is PodInfo map[string]ContainerStatus. 719 if err := c.convert(sv.MapIndex(sk), dkv, scope); err != nil { 720 return err 721 } 722 dv.SetMapIndex(dk, dkv) 723 } 724 case reflect.Interface: 725 if sv.IsNil() { 726 // Don't copy a nil interface! 727 dv.Set(reflect.Zero(dt)) 728 return nil 729 } 730 tmpdv := reflect.New(sv.Elem().Type()).Elem() 731 if err := c.convert(sv.Elem(), tmpdv, scope); err != nil { 732 return err 733 } 734 dv.Set(reflect.ValueOf(tmpdv.Interface())) 735 return nil 736 default: 737 return scope.errorf("couldn't copy '%v' into '%v'; didn't understand types", st, dt) 738 } 739 return nil 740 } 741 742 var stringType = reflect.TypeOf("") 743 744 func toKVValue(v reflect.Value) kvValue { 745 switch v.Kind() { 746 case reflect.Struct: 747 return structAdaptor(v) 748 case reflect.Map: 749 if v.Type().Key().AssignableTo(stringType) { 750 return stringMapAdaptor(v) 751 } 752 } 753 754 return nil 755 } 756 757 // kvValue lets us write the same conversion logic to work with both maps 758 // and structs. Only maps with string keys make sense for this. 759 type kvValue interface { 760 // returns all keys, as a []string. 761 keys() []string 762 // Will just return "" for maps. 763 tagOf(key string) reflect.StructTag 764 // Will return the zero Value if the key doesn't exist. 765 value(key string) reflect.Value 766 // Maps require explicit setting-- will do nothing for structs. 767 // Returns false on failure. 768 confirmSet(key string, v reflect.Value) bool 769 } 770 771 type stringMapAdaptor reflect.Value 772 773 func (a stringMapAdaptor) len() int { 774 return reflect.Value(a).Len() 775 } 776 777 func (a stringMapAdaptor) keys() []string { 778 v := reflect.Value(a) 779 keys := make([]string, v.Len()) 780 for i, v := range v.MapKeys() { 781 if v.IsNil() { 782 continue 783 } 784 switch t := v.Interface().(type) { 785 case string: 786 keys[i] = t 787 } 788 } 789 return keys 790 } 791 792 func (a stringMapAdaptor) tagOf(key string) reflect.StructTag { 793 return "" 794 } 795 796 func (a stringMapAdaptor) value(key string) reflect.Value { 797 return reflect.Value(a).MapIndex(reflect.ValueOf(key)) 798 } 799 800 func (a stringMapAdaptor) confirmSet(key string, v reflect.Value) bool { 801 return true 802 } 803 804 type structAdaptor reflect.Value 805 806 func (a structAdaptor) len() int { 807 v := reflect.Value(a) 808 return v.Type().NumField() 809 } 810 811 func (a structAdaptor) keys() []string { 812 v := reflect.Value(a) 813 t := v.Type() 814 keys := make([]string, t.NumField()) 815 for i := range keys { 816 keys[i] = t.Field(i).Name 817 } 818 return keys 819 } 820 821 func (a structAdaptor) tagOf(key string) reflect.StructTag { 822 v := reflect.Value(a) 823 field, ok := v.Type().FieldByName(key) 824 if ok { 825 return field.Tag 826 } 827 return "" 828 } 829 830 func (a structAdaptor) value(key string) reflect.Value { 831 v := reflect.Value(a) 832 return v.FieldByName(key) 833 } 834 835 func (a structAdaptor) confirmSet(key string, v reflect.Value) bool { 836 return true 837 } 838 839 // convertKV can convert things that consist of key/value pairs, like structs 840 // and some maps. 841 func (c *Converter) convertKV(skv, dkv kvValue, scope *scope) error { 842 if skv == nil || dkv == nil { 843 // TODO: add keys to stack to support really understandable error messages. 844 return fmt.Errorf("Unable to convert %#v to %#v", skv, dkv) 845 } 846 847 lister := dkv 848 if scope.flags.IsSet(SourceToDest) { 849 lister = skv 850 } 851 852 var mapping FieldMappingFunc 853 if scope.meta != nil && scope.meta.KeyNameMapping != nil { 854 mapping = scope.meta.KeyNameMapping 855 } 856 857 for _, key := range lister.keys() { 858 if found, err := c.checkField(key, skv, dkv, scope); found { 859 if err != nil { 860 return err 861 } 862 continue 863 } 864 stag := skv.tagOf(key) 865 dtag := dkv.tagOf(key) 866 skey := key 867 dkey := key 868 if mapping != nil { 869 skey, dkey = scope.meta.KeyNameMapping(key, stag, dtag) 870 } 871 872 df := dkv.value(dkey) 873 sf := skv.value(skey) 874 if !df.IsValid() || !sf.IsValid() { 875 switch { 876 case scope.flags.IsSet(IgnoreMissingFields): 877 // No error. 878 case scope.flags.IsSet(SourceToDest): 879 return scope.errorf("%v not present in dest", dkey) 880 default: 881 return scope.errorf("%v not present in src", skey) 882 } 883 continue 884 } 885 scope.srcStack.top().key = skey 886 scope.srcStack.top().tag = stag 887 scope.destStack.top().key = dkey 888 scope.destStack.top().tag = dtag 889 if err := c.convert(sf, df, scope); err != nil { 890 return err 891 } 892 } 893 return nil 894 } 895 896 // checkField returns true if the field name matches any of the struct 897 // field copying rules. The error should be ignored if it returns false. 898 func (c *Converter) checkField(fieldName string, skv, dkv kvValue, scope *scope) (bool, error) { 899 replacementMade := false 900 if scope.flags.IsSet(DestFromSource) { 901 df := dkv.value(fieldName) 902 if !df.IsValid() { 903 return false, nil 904 } 905 destKey := typeNamePair{df.Type(), fieldName} 906 // Check each of the potential source (type, name) pairs to see if they're 907 // present in sv. 908 for _, potentialSourceKey := range c.structFieldSources[destKey] { 909 sf := skv.value(potentialSourceKey.fieldName) 910 if !sf.IsValid() { 911 continue 912 } 913 if sf.Type() == potentialSourceKey.fieldType { 914 // Both the source's name and type matched, so copy. 915 scope.srcStack.top().key = potentialSourceKey.fieldName 916 scope.destStack.top().key = fieldName 917 if err := c.convert(sf, df, scope); err != nil { 918 return true, err 919 } 920 dkv.confirmSet(fieldName, df) 921 replacementMade = true 922 } 923 } 924 return replacementMade, nil 925 } 926 927 sf := skv.value(fieldName) 928 if !sf.IsValid() { 929 return false, nil 930 } 931 srcKey := typeNamePair{sf.Type(), fieldName} 932 // Check each of the potential dest (type, name) pairs to see if they're 933 // present in dv. 934 for _, potentialDestKey := range c.structFieldDests[srcKey] { 935 df := dkv.value(potentialDestKey.fieldName) 936 if !df.IsValid() { 937 continue 938 } 939 if df.Type() == potentialDestKey.fieldType { 940 // Both the dest's name and type matched, so copy. 941 scope.srcStack.top().key = fieldName 942 scope.destStack.top().key = potentialDestKey.fieldName 943 if err := c.convert(sf, df, scope); err != nil { 944 return true, err 945 } 946 dkv.confirmSet(potentialDestKey.fieldName, df) 947 replacementMade = true 948 } 949 } 950 return replacementMade, nil 951 }