github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/conversion/cloner.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 // Cloner knows how to copy one type to another. 25 type Cloner struct { 26 // Map from the type to a function which can do the deep copy. 27 deepCopyFuncs map[reflect.Type]reflect.Value 28 generatedDeepCopyFuncs map[reflect.Type]reflect.Value 29 } 30 31 // NewCloner creates a new Cloner object. 32 func NewCloner() *Cloner { 33 c := &Cloner{ 34 deepCopyFuncs: map[reflect.Type]reflect.Value{}, 35 generatedDeepCopyFuncs: map[reflect.Type]reflect.Value{}, 36 } 37 if err := c.RegisterDeepCopyFunc(byteSliceDeepCopy); err != nil { 38 // If one of the deep-copy functions is malformed, detect it immediately. 39 panic(err) 40 } 41 return c 42 } 43 44 // Prevent recursing into every byte... 45 func byteSliceDeepCopy(in []byte, out *[]byte, c *Cloner) error { 46 if in != nil { 47 *out = make([]byte, len(in)) 48 copy(*out, in) 49 } else { 50 *out = nil 51 } 52 return nil 53 } 54 55 // Verifies whether a deep-copy function has a correct signature. 56 func verifyDeepCopyFunctionSignature(ft reflect.Type) error { 57 if ft.Kind() != reflect.Func { 58 return fmt.Errorf("expected func, got: %v", ft) 59 } 60 if ft.NumIn() != 3 { 61 return fmt.Errorf("expected three 'in' params, got %v", ft) 62 } 63 if ft.NumOut() != 1 { 64 return fmt.Errorf("expected one 'out' param, got %v", ft) 65 } 66 if ft.In(1).Kind() != reflect.Ptr { 67 return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) 68 } 69 if ft.In(1).Elem() != ft.In(0) { 70 return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft) 71 } 72 var forClonerType Cloner 73 if expected := reflect.TypeOf(&forClonerType); ft.In(2) != expected { 74 return fmt.Errorf("expected '%v' arg for 'in' param 2, got: '%v'", expected, ft.In(2)) 75 } 76 var forErrorType error 77 // This convolution is necessary, otherwise TypeOf picks up on the fact 78 // that forErrorType is nil 79 errorType := reflect.TypeOf(&forErrorType).Elem() 80 if ft.Out(0) != errorType { 81 return fmt.Errorf("expected error return, got: %v", ft) 82 } 83 return nil 84 } 85 86 // RegisterGeneratedDeepCopyFunc registers a copying func with the Cloner. 87 // deepCopyFunc must take three parameters: a type input, a pointer to a 88 // type output, and a pointer to Cloner. It should return an error. 89 // 90 // Example: 91 // c.RegisterGeneratedDeepCopyFunc( 92 // func(in Pod, out *Pod, c *Cloner) error { 93 // // deep copy logic... 94 // return nil 95 // }) 96 func (c *Cloner) RegisterDeepCopyFunc(deepCopyFunc interface{}) error { 97 fv := reflect.ValueOf(deepCopyFunc) 98 ft := fv.Type() 99 if err := verifyDeepCopyFunctionSignature(ft); err != nil { 100 return err 101 } 102 c.deepCopyFuncs[ft.In(0)] = fv 103 return nil 104 } 105 106 // Similar to RegisterDeepCopyFunc, but registers deep copy function that were 107 // automatically generated. 108 func (c *Cloner) RegisterGeneratedDeepCopyFunc(deepCopyFunc interface{}) error { 109 fv := reflect.ValueOf(deepCopyFunc) 110 ft := fv.Type() 111 if err := verifyDeepCopyFunctionSignature(ft); err != nil { 112 return err 113 } 114 c.generatedDeepCopyFuncs[ft.In(0)] = fv 115 return nil 116 } 117 118 // DeepCopy will perform a deep copy of a given object. 119 func (c *Cloner) DeepCopy(in interface{}) (interface{}, error) { 120 // Can be invalid if we run DeepCopy(X) where X is a nil interface type. 121 // For example, we get an invalid value when someone tries to deep-copy 122 // a nil labels.Selector. 123 // This does not occur if X is nil and is a pointer to a concrete type. 124 if in == nil { 125 return nil, nil 126 } 127 inValue := reflect.ValueOf(in) 128 outValue, err := c.deepCopy(inValue) 129 if err != nil { 130 return nil, err 131 } 132 return outValue.Interface(), nil 133 } 134 135 func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) { 136 inType := src.Type() 137 138 if fv, ok := c.deepCopyFuncs[inType]; ok { 139 return c.customDeepCopy(src, fv) 140 } 141 if fv, ok := c.generatedDeepCopyFuncs[inType]; ok { 142 return c.customDeepCopy(src, fv) 143 } 144 return c.defaultDeepCopy(src) 145 } 146 147 func (c *Cloner) customDeepCopy(src, fv reflect.Value) (reflect.Value, error) { 148 outValue := reflect.New(src.Type()) 149 args := []reflect.Value{src, outValue, reflect.ValueOf(c)} 150 result := fv.Call(args)[0].Interface() 151 // This convolution is necessary because nil interfaces won't convert 152 // to error. 153 if result == nil { 154 return outValue.Elem(), nil 155 } 156 return outValue.Elem(), result.(error) 157 } 158 159 func (c *Cloner) defaultDeepCopy(src reflect.Value) (reflect.Value, error) { 160 switch src.Kind() { 161 case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Uintptr: 162 return src, fmt.Errorf("cannot deep copy kind: %s", src.Kind()) 163 case reflect.Array: 164 dst := reflect.New(src.Type()) 165 for i := 0; i < src.Len(); i++ { 166 copyVal, err := c.deepCopy(src.Index(i)) 167 if err != nil { 168 return src, err 169 } 170 dst.Elem().Index(i).Set(copyVal) 171 } 172 return dst.Elem(), nil 173 case reflect.Interface: 174 if src.IsNil() { 175 return src, nil 176 } 177 return c.deepCopy(src.Elem()) 178 case reflect.Map: 179 if src.IsNil() { 180 return src, nil 181 } 182 dst := reflect.MakeMap(src.Type()) 183 for _, k := range src.MapKeys() { 184 copyVal, err := c.deepCopy(src.MapIndex(k)) 185 if err != nil { 186 return src, err 187 } 188 dst.SetMapIndex(k, copyVal) 189 } 190 return dst, nil 191 case reflect.Ptr: 192 if src.IsNil() { 193 return src, nil 194 } 195 dst := reflect.New(src.Type().Elem()) 196 copyVal, err := c.deepCopy(src.Elem()) 197 if err != nil { 198 return src, err 199 } 200 dst.Elem().Set(copyVal) 201 return dst, nil 202 case reflect.Slice: 203 if src.IsNil() { 204 return src, nil 205 } 206 dst := reflect.MakeSlice(src.Type(), 0, src.Len()) 207 for i := 0; i < src.Len(); i++ { 208 copyVal, err := c.deepCopy(src.Index(i)) 209 if err != nil { 210 return src, err 211 } 212 dst = reflect.Append(dst, copyVal) 213 } 214 return dst, nil 215 case reflect.Struct: 216 dst := reflect.New(src.Type()) 217 for i := 0; i < src.NumField(); i++ { 218 if !dst.Elem().Field(i).CanSet() { 219 // Can't set private fields. At this point, the 220 // best we can do is a shallow copy. For 221 // example, time.Time is a value type with 222 // private members that can be shallow copied. 223 return src, nil 224 } 225 copyVal, err := c.deepCopy(src.Field(i)) 226 if err != nil { 227 return src, err 228 } 229 dst.Elem().Field(i).Set(copyVal) 230 } 231 return dst.Elem(), nil 232 233 default: 234 // Value types like numbers, booleans, and strings. 235 return src, nil 236 } 237 }