mirror of https://github.com/k3s-io/k3s
Turn first deepcopy parameter into a pointer
parent
dbab1a8477
commit
6049623a13
|
@ -425,7 +425,7 @@ func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Wri
|
||||||
|
|
||||||
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
sw := generator.NewSnippetWriter(w, c, "$", "$")
|
||||||
funcName := g.funcNameTmpl(t)
|
funcName := g.funcNameTmpl(t)
|
||||||
sw.Do(fmt.Sprintf("func %s(in $.type|raw$, out *$.type|raw$, c *$.Cloner|raw$) error {\n", funcName), g.withGlobals(argsFromType(t)))
|
sw.Do(fmt.Sprintf("func %s(in *$.type|raw$, out *$.type|raw$, c *$.Cloner|raw$) error {\n", funcName), g.withGlobals(argsFromType(t)))
|
||||||
g.generateFor(t, sw)
|
g.generateFor(t, sw)
|
||||||
sw.Do("return nil\n", nil)
|
sw.Do("return nil\n", nil)
|
||||||
sw.Do("}\n\n", nil)
|
sw.Do("}\n\n", nil)
|
||||||
|
@ -459,7 +459,7 @@ func (g *genDeepCopy) generateFor(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) doBuiltin(t *types.Type, sw *generator.SnippetWriter) {
|
func (g *genDeepCopy) doBuiltin(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("*out = in\n", nil)
|
sw.Do("*out = *in\n", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
|
@ -467,63 +467,63 @@ func (g *genDeepCopy) doMap(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
if t.Key.IsAssignable() {
|
if t.Key.IsAssignable() {
|
||||||
switch {
|
switch {
|
||||||
case hasDeepCopyMethod(t.Elem):
|
case hasDeepCopyMethod(t.Elem):
|
||||||
sw.Do("for key, val := range in {\n", nil)
|
sw.Do("for key, val := range *in {\n", nil)
|
||||||
sw.Do("(*out)[key] = val.DeepCopy()\n", nil)
|
sw.Do("(*out)[key] = val.DeepCopy()\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
case t.Elem.IsAnonymousStruct():
|
case t.Elem.IsAnonymousStruct():
|
||||||
sw.Do("for key := range in {\n", nil)
|
sw.Do("for key := range *in {\n", nil)
|
||||||
sw.Do("(*out)[key] = struct{}{}\n", nil)
|
sw.Do("(*out)[key] = struct{}{}\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
case t.Elem.IsAssignable():
|
case t.Elem.IsAssignable():
|
||||||
sw.Do("for key, val := range in {\n", nil)
|
sw.Do("for key, val := range *in {\n", nil)
|
||||||
sw.Do("(*out)[key] = val\n", nil)
|
sw.Do("(*out)[key] = val\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
default:
|
default:
|
||||||
sw.Do("for key, val := range in {\n", nil)
|
sw.Do("for key, val := range *in {\n", nil)
|
||||||
if g.copyableAndInBounds(t.Elem) {
|
if g.copyableAndInBounds(t.Elem) {
|
||||||
sw.Do("newVal := new($.|raw$)\n", t.Elem)
|
sw.Do("newVal := new($.|raw$)\n", t.Elem)
|
||||||
funcName := g.funcNameTmpl(t.Elem)
|
funcName := g.funcNameTmpl(t.Elem)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(val, newVal, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
sw.Do(fmt.Sprintf("if err := %s(&val, newVal, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
sw.Do("(*out)[key] = *newVal\n", nil)
|
sw.Do("(*out)[key] = *newVal\n", nil)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("if newVal, err := c.DeepCopy(val); err != nil {\n", nil)
|
sw.Do("if newVal, err := c.DeepCopy(&val); err != nil {\n", nil)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("(*out)[key] = newVal.($.|raw$)\n", t.Elem)
|
sw.Do("(*out)[key] = *newVal.(*$.|raw$)\n", t.Elem)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: Implement it when necessary.
|
// TODO: Implement it when necessary.
|
||||||
sw.Do("for range in {\n", nil)
|
sw.Do("for range *in {\n", nil)
|
||||||
sw.Do("// FIXME: Copying unassignable keys unsupported $.|raw$\n", t.Key)
|
sw.Do("// FIXME: Copying unassignable keys unsupported $.|raw$\n", t.Key)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
|
func (g *genDeepCopy) doSlice(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("*out = make($.|raw$, len(in))\n", t)
|
sw.Do("*out = make($.|raw$, len(*in))\n", t)
|
||||||
if t.Elem.Kind == types.Builtin {
|
if t.Elem.Kind == types.Builtin {
|
||||||
sw.Do("copy(*out, in)\n", nil)
|
sw.Do("copy(*out, *in)\n", nil)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("for i := range in {\n", nil)
|
sw.Do("for i := range *in {\n", nil)
|
||||||
if hasDeepCopyMethod(t.Elem) {
|
if hasDeepCopyMethod(t.Elem) {
|
||||||
sw.Do("(*out)[i] = in[i].DeepCopy()\n", nil)
|
sw.Do("(*out)[i] = (*in)[i].DeepCopy()\n", nil)
|
||||||
} else if t.Elem.IsAssignable() {
|
} else if t.Elem.IsAssignable() {
|
||||||
sw.Do("(*out)[i] = in[i]\n", nil)
|
sw.Do("(*out)[i] = (*in)[i]\n", nil)
|
||||||
} else if g.copyableAndInBounds(t.Elem) {
|
} else if g.copyableAndInBounds(t.Elem) {
|
||||||
funcName := g.funcNameTmpl(t.Elem)
|
funcName := g.funcNameTmpl(t.Elem)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(in[i], &(*out)[i], c); err != nil {\n", funcName), argsFromType(t.Elem))
|
sw.Do(fmt.Sprintf("if err := %s(&(*in)[i], &(*out)[i], c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("if newVal, err := c.DeepCopy(in[i]); err != nil {\n", nil)
|
sw.Do("if newVal, err := c.DeepCopy(&(*in)[i]); err != nil {\n", nil)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("(*out)[i] = newVal.($.|raw$)\n", t.Elem)
|
sw.Do("(*out)[i] = *newVal.(*$.|raw$)\n", t.Elem)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
|
@ -547,7 +547,7 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
case types.Map, types.Slice, types.Pointer:
|
case types.Map, types.Slice, types.Pointer:
|
||||||
sw.Do("if in.$.name$ != nil {\n", args)
|
sw.Do("if in.$.name$ != nil {\n", args)
|
||||||
sw.Do("in, out := in.$.name$, &out.$.name$\n", args)
|
sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)
|
||||||
g.generateFor(t, sw)
|
g.generateFor(t, sw)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("out.$.name$ = nil\n", args)
|
sw.Do("out.$.name$ = nil\n", args)
|
||||||
|
@ -559,23 +559,23 @@ func (g *genDeepCopy) doStruct(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("out.$.name$ = in.$.name$\n", args)
|
sw.Do("out.$.name$ = in.$.name$\n", args)
|
||||||
} else if g.copyableAndInBounds(t) {
|
} else if g.copyableAndInBounds(t) {
|
||||||
funcName := g.funcNameTmpl(t)
|
funcName := g.funcNameTmpl(t)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, c); err != nil {\n", funcName), args)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
} else {
|
} else {
|
||||||
sw.Do("if newVal, err := c.DeepCopy(in.$.name$); err != nil {\n", args)
|
sw.Do("if newVal, err := c.DeepCopy(&in.$.name$); err != nil {\n", args)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("out.$.name$ = newVal.($.type|raw$)\n", args)
|
sw.Do("out.$.name$ = *newVal.(*$.type|raw$)\n", args)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
sw.Do("if in.$.name$ == nil {\n", args)
|
sw.Do("if in.$.name$ == nil {\n", args)
|
||||||
sw.Do("out.$.name$ = nil\n", args)
|
sw.Do("out.$.name$ = nil\n", args)
|
||||||
sw.Do("} else if newVal, err := c.DeepCopy(in.$.name$); err != nil {\n", args)
|
sw.Do("} else if newVal, err := c.DeepCopy(&in.$.name$); err != nil {\n", args)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("out.$.name$ = newVal.($.type|raw$)\n", args)
|
sw.Do("out.$.name$ = *newVal.(*$.type|raw$)\n", args)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -587,13 +587,15 @@ func (g *genDeepCopy) doInterface(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) {
|
func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("*out = new($.Elem|raw$)\n", t)
|
|
||||||
if hasDeepCopyMethod(t.Elem) {
|
if hasDeepCopyMethod(t.Elem) {
|
||||||
sw.Do("**out = in.DeepCopy()\n", nil)
|
sw.Do("*out = new($.Elem|raw$)\n", t)
|
||||||
|
sw.Do("**out = (*in).DeepCopy()\n", nil)
|
||||||
} else if t.Elem.IsAssignable() {
|
} else if t.Elem.IsAssignable() {
|
||||||
sw.Do("**out = *in", nil)
|
sw.Do("*out = new($.Elem|raw$)\n", t)
|
||||||
|
sw.Do("**out = **in", nil)
|
||||||
} else if g.copyableAndInBounds(t.Elem) {
|
} else if g.copyableAndInBounds(t.Elem) {
|
||||||
funcName := g.funcNameTmpl(t.Elem)
|
funcName := g.funcNameTmpl(t.Elem)
|
||||||
|
sw.Do("*out = new($.Elem|raw$)\n", t)
|
||||||
sw.Do(fmt.Sprintf("if err := %s(*in, *out, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
sw.Do(fmt.Sprintf("if err := %s(*in, *out, c); err != nil {\n", funcName), argsFromType(t.Elem))
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
|
@ -601,7 +603,7 @@ func (g *genDeepCopy) doPointer(t *types.Type, sw *generator.SnippetWriter) {
|
||||||
sw.Do("if newVal, err := c.DeepCopy(*in); err != nil {\n", nil)
|
sw.Do("if newVal, err := c.DeepCopy(*in); err != nil {\n", nil)
|
||||||
sw.Do("return err\n", nil)
|
sw.Do("return err\n", nil)
|
||||||
sw.Do("} else {\n", nil)
|
sw.Do("} else {\n", nil)
|
||||||
sw.Do("**out = newVal.($.|raw$)\n", t.Elem)
|
sw.Do("*out = newVal.($.|raw$)\n", t.Elem)
|
||||||
sw.Do("}\n", nil)
|
sw.Do("}\n", nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,10 +42,10 @@ func NewCloner() *Cloner {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent recursing into every byte...
|
// Prevent recursing into every byte...
|
||||||
func byteSliceDeepCopy(in []byte, out *[]byte, c *Cloner) error {
|
func byteSliceDeepCopy(in *[]byte, out *[]byte, c *Cloner) error {
|
||||||
if in != nil {
|
if *in != nil {
|
||||||
*out = make([]byte, len(in))
|
*out = make([]byte, len(*in))
|
||||||
copy(*out, in)
|
copy(*out, *in)
|
||||||
} else {
|
} else {
|
||||||
*out = nil
|
*out = nil
|
||||||
}
|
}
|
||||||
|
@ -63,10 +63,10 @@ func verifyDeepCopyFunctionSignature(ft reflect.Type) error {
|
||||||
if ft.NumOut() != 1 {
|
if ft.NumOut() != 1 {
|
||||||
return fmt.Errorf("expected one 'out' param, got %v", ft)
|
return fmt.Errorf("expected one 'out' param, got %v", ft)
|
||||||
}
|
}
|
||||||
if ft.In(1).Kind() != reflect.Ptr {
|
if ft.In(0).Kind() != reflect.Ptr {
|
||||||
return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft)
|
return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft)
|
||||||
}
|
}
|
||||||
if ft.In(1).Elem() != ft.In(0) {
|
if ft.In(1) != ft.In(0) {
|
||||||
return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft)
|
return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft)
|
||||||
}
|
}
|
||||||
var forClonerType Cloner
|
var forClonerType Cloner
|
||||||
|
@ -135,6 +135,13 @@ func (c *Cloner) DeepCopy(in interface{}) (interface{}, error) {
|
||||||
func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) {
|
func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) {
|
||||||
inType := src.Type()
|
inType := src.Type()
|
||||||
|
|
||||||
|
switch src.Kind() {
|
||||||
|
case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
|
||||||
|
if src.IsNil() {
|
||||||
|
return src, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if fv, ok := c.deepCopyFuncs[inType]; ok {
|
if fv, ok := c.deepCopyFuncs[inType]; ok {
|
||||||
return c.customDeepCopy(src, fv)
|
return c.customDeepCopy(src, fv)
|
||||||
}
|
}
|
||||||
|
@ -145,15 +152,15 @@ func (c *Cloner) deepCopy(src reflect.Value) (reflect.Value, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cloner) customDeepCopy(src, fv reflect.Value) (reflect.Value, error) {
|
func (c *Cloner) customDeepCopy(src, fv reflect.Value) (reflect.Value, error) {
|
||||||
outValue := reflect.New(src.Type())
|
outValue := reflect.New(src.Type().Elem())
|
||||||
args := []reflect.Value{src, outValue, reflect.ValueOf(c)}
|
args := []reflect.Value{src, outValue, reflect.ValueOf(c)}
|
||||||
result := fv.Call(args)[0].Interface()
|
result := fv.Call(args)[0].Interface()
|
||||||
// This convolution is necessary because nil interfaces won't convert
|
// This convolution is necessary because nil interfaces won't convert
|
||||||
// to error.
|
// to error.
|
||||||
if result == nil {
|
if result == nil {
|
||||||
return outValue.Elem(), nil
|
return outValue, nil
|
||||||
}
|
}
|
||||||
return outValue.Elem(), result.(error)
|
return outValue, result.(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cloner) defaultDeepCopy(src reflect.Value) (reflect.Value, error) {
|
func (c *Cloner) defaultDeepCopy(src reflect.Value) (reflect.Value, error) {
|
||||||
|
|
Loading…
Reference in New Issue