github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/runtime/deep_copy_generator.go (about)

     1  /*
     2  Copyright 2015 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 runtime
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"path"
    23  	"reflect"
    24  	"sort"
    25  	"strings"
    26  
    27  	"k8s.io/kubernetes/pkg/conversion"
    28  	"k8s.io/kubernetes/pkg/util/sets"
    29  )
    30  
    31  // TODO(wojtek-t): As suggested in #8320, we should consider the strategy
    32  // to first do the shallow copy and then recurse into things that need a
    33  // deep copy (maps, pointers, slices). That sort of copy function would
    34  // need one parameter - a pointer to the thing it's supposed to expand,
    35  // and it would involve a lot less memory copying.
    36  type DeepCopyGenerator interface {
    37  	// Adds a type to a generator.
    38  	// If the type is non-struct, it will return an error, otherwise deep-copy
    39  	// functions for this type and all nested types will be generated.
    40  	AddType(inType reflect.Type) error
    41  
    42  	// ReplaceType registers a type that should be used instead of the type
    43  	// with the provided pkgPath and name.
    44  	ReplaceType(pkgPath, name string, in interface{})
    45  
    46  	// AddImport registers a package name with the generator and returns its
    47  	// short name.
    48  	AddImport(pkgPath string) string
    49  
    50  	// RepackImports creates a stable ordering of import short names
    51  	RepackImports()
    52  
    53  	// Writes all imports that are necessary for deep-copy function and
    54  	// their registration.
    55  	WriteImports(w io.Writer) error
    56  
    57  	// Writes deel-copy functions for all types added via AddType() method
    58  	// and their nested types.
    59  	WriteDeepCopyFunctions(w io.Writer) error
    60  
    61  	// Writes an init() function that registers all the generated deep-copy
    62  	// functions.
    63  	RegisterDeepCopyFunctions(w io.Writer, pkg string) error
    64  
    65  	// When generating code, all references to "pkg" package name will be
    66  	// replaced with "overwrite". It is used mainly to replace references
    67  	// to name of the package in which the code will be created with empty
    68  	// string.
    69  	OverwritePackage(pkg, overwrite string)
    70  }
    71  
    72  func NewDeepCopyGenerator(scheme *conversion.Scheme, targetPkg string, include sets.String) DeepCopyGenerator {
    73  	g := &deepCopyGenerator{
    74  		scheme:        scheme,
    75  		targetPkg:     targetPkg,
    76  		copyables:     make(map[reflect.Type]bool),
    77  		imports:       make(map[string]string),
    78  		shortImports:  make(map[string]string),
    79  		pkgOverwrites: make(map[string]string),
    80  		replace:       make(map[pkgPathNamePair]reflect.Type),
    81  		include:       include,
    82  	}
    83  	g.targetPackage(targetPkg)
    84  	g.AddImport("k8s.io/kubernetes/pkg/conversion")
    85  	return g
    86  }
    87  
    88  type pkgPathNamePair struct {
    89  	PkgPath string
    90  	Name    string
    91  }
    92  
    93  type deepCopyGenerator struct {
    94  	scheme    *conversion.Scheme
    95  	targetPkg string
    96  	copyables map[reflect.Type]bool
    97  	// map of package names to shortname
    98  	imports map[string]string
    99  	// map of short names to package names
   100  	shortImports  map[string]string
   101  	pkgOverwrites map[string]string
   102  	replace       map[pkgPathNamePair]reflect.Type
   103  	include       sets.String
   104  }
   105  
   106  func (g *deepCopyGenerator) addImportByPath(pkg string) string {
   107  	if name, ok := g.imports[pkg]; ok {
   108  		return name
   109  	}
   110  	name := path.Base(pkg)
   111  	if _, ok := g.shortImports[name]; !ok {
   112  		g.imports[pkg] = name
   113  		g.shortImports[name] = pkg
   114  		return name
   115  	}
   116  	if dirname := path.Base(path.Dir(pkg)); len(dirname) > 0 {
   117  		name = dirname + name
   118  		if _, ok := g.shortImports[name]; !ok {
   119  			g.imports[pkg] = name
   120  			g.shortImports[name] = pkg
   121  			return name
   122  		}
   123  		if subdirname := path.Base(path.Dir(path.Dir(pkg))); len(subdirname) > 0 {
   124  			name = subdirname + name
   125  			if _, ok := g.shortImports[name]; !ok {
   126  				g.imports[pkg] = name
   127  				g.shortImports[name] = pkg
   128  				return name
   129  			}
   130  		}
   131  	}
   132  	for i := 2; i < 100; i++ {
   133  		generatedName := fmt.Sprintf("%s%d", name, i)
   134  		if _, ok := g.shortImports[generatedName]; !ok {
   135  			g.imports[pkg] = generatedName
   136  			g.shortImports[generatedName] = pkg
   137  			return generatedName
   138  		}
   139  	}
   140  	panic(fmt.Sprintf("unable to find a unique name for the package path %q: %v", pkg, g.shortImports))
   141  }
   142  
   143  func (g *deepCopyGenerator) targetPackage(pkg string) {
   144  	g.imports[pkg] = ""
   145  	g.shortImports[""] = pkg
   146  }
   147  
   148  func (g *deepCopyGenerator) addAllRecursiveTypes(inType reflect.Type) error {
   149  	if _, found := g.copyables[inType]; found {
   150  		return nil
   151  	}
   152  	switch inType.Kind() {
   153  	case reflect.Map:
   154  		if err := g.addAllRecursiveTypes(inType.Key()); err != nil {
   155  			return err
   156  		}
   157  		if err := g.addAllRecursiveTypes(inType.Elem()); err != nil {
   158  			return err
   159  		}
   160  	case reflect.Slice, reflect.Ptr:
   161  		if err := g.addAllRecursiveTypes(inType.Elem()); err != nil {
   162  			return err
   163  		}
   164  	case reflect.Interface:
   165  		g.addImportByPath(inType.PkgPath())
   166  		return nil
   167  	case reflect.Struct:
   168  		g.addImportByPath(inType.PkgPath())
   169  		found := false
   170  		for s := range g.include {
   171  			if strings.HasPrefix(inType.PkgPath(), s) {
   172  				found = true
   173  				break
   174  			}
   175  		}
   176  		if !found {
   177  			return nil
   178  		}
   179  		for i := 0; i < inType.NumField(); i++ {
   180  			inField := inType.Field(i)
   181  			if err := g.addAllRecursiveTypes(inField.Type); err != nil {
   182  				return err
   183  			}
   184  		}
   185  		g.copyables[inType] = true
   186  	default:
   187  		// Simple types should be copied automatically.
   188  	}
   189  	return nil
   190  }
   191  
   192  func (g *deepCopyGenerator) AddImport(pkg string) string {
   193  	return g.addImportByPath(pkg)
   194  }
   195  
   196  // ReplaceType registers a replacement type to be used instead of the named type
   197  func (g *deepCopyGenerator) ReplaceType(pkgPath, name string, t interface{}) {
   198  	g.replace[pkgPathNamePair{pkgPath, name}] = reflect.TypeOf(t)
   199  }
   200  
   201  func (g *deepCopyGenerator) AddType(inType reflect.Type) error {
   202  	if inType.Kind() != reflect.Struct {
   203  		return fmt.Errorf("non-struct copies are not supported")
   204  	}
   205  	return g.addAllRecursiveTypes(inType)
   206  }
   207  
   208  func (g *deepCopyGenerator) RepackImports() {
   209  	var packages []string
   210  	for key := range g.imports {
   211  		packages = append(packages, key)
   212  	}
   213  	sort.Strings(packages)
   214  	g.imports = make(map[string]string)
   215  	g.shortImports = make(map[string]string)
   216  
   217  	g.targetPackage(g.targetPkg)
   218  	for _, pkg := range packages {
   219  		g.addImportByPath(pkg)
   220  	}
   221  }
   222  
   223  func (g *deepCopyGenerator) WriteImports(w io.Writer) error {
   224  	var packages []string
   225  	for key := range g.imports {
   226  		packages = append(packages, key)
   227  	}
   228  	sort.Strings(packages)
   229  
   230  	buffer := newBuffer()
   231  	indent := 0
   232  	buffer.addLine("import (\n", indent)
   233  	for _, importPkg := range packages {
   234  		if len(importPkg) == 0 {
   235  			continue
   236  		}
   237  		if len(g.imports[importPkg]) == 0 {
   238  			continue
   239  		}
   240  		buffer.addLine(fmt.Sprintf("%s \"%s\"\n", g.imports[importPkg], importPkg), indent+1)
   241  	}
   242  	buffer.addLine(")\n", indent)
   243  	buffer.addLine("\n", indent)
   244  	if err := buffer.flushLines(w); err != nil {
   245  		return err
   246  	}
   247  	return nil
   248  }
   249  
   250  type byPkgAndName []reflect.Type
   251  
   252  func (s byPkgAndName) Len() int {
   253  	return len(s)
   254  }
   255  
   256  func (s byPkgAndName) Less(i, j int) bool {
   257  	fullNameI := s[i].PkgPath() + "/" + s[i].Name()
   258  	fullNameJ := s[j].PkgPath() + "/" + s[j].Name()
   259  	return fullNameI < fullNameJ
   260  }
   261  
   262  func (s byPkgAndName) Swap(i, j int) {
   263  	s[i], s[j] = s[j], s[i]
   264  }
   265  
   266  func (g *deepCopyGenerator) nameForType(inType reflect.Type) string {
   267  	switch inType.Kind() {
   268  	case reflect.Slice:
   269  		return fmt.Sprintf("[]%s", g.typeName(inType.Elem()))
   270  	case reflect.Ptr:
   271  		return fmt.Sprintf("*%s", g.typeName(inType.Elem()))
   272  	case reflect.Map:
   273  		if len(inType.Name()) == 0 {
   274  			return fmt.Sprintf("map[%s]%s", g.typeName(inType.Key()), g.typeName(inType.Elem()))
   275  		}
   276  		fallthrough
   277  	default:
   278  		pkg, name := inType.PkgPath(), inType.Name()
   279  		if len(name) == 0 && inType.Kind() == reflect.Struct {
   280  			return "struct{}"
   281  		}
   282  		if len(pkg) == 0 {
   283  			// Default package.
   284  			return name
   285  		}
   286  		if val, found := g.pkgOverwrites[pkg]; found {
   287  			pkg = val
   288  		}
   289  		if len(pkg) == 0 {
   290  			return name
   291  		}
   292  		short := g.addImportByPath(pkg)
   293  		if len(short) > 0 {
   294  			return fmt.Sprintf("%s.%s", short, name)
   295  		}
   296  		return name
   297  	}
   298  }
   299  
   300  func (g *deepCopyGenerator) typeName(inType reflect.Type) string {
   301  	if t, ok := g.replace[pkgPathNamePair{inType.PkgPath(), inType.Name()}]; ok {
   302  		return g.nameForType(t)
   303  	}
   304  	return g.nameForType(inType)
   305  }
   306  
   307  func (g *deepCopyGenerator) deepCopyFunctionName(inType reflect.Type) string {
   308  	funcNameFormat := "deepCopy_%s_%s"
   309  	inPkg := packageForName(inType)
   310  	funcName := fmt.Sprintf(funcNameFormat, inPkg, inType.Name())
   311  	return funcName
   312  }
   313  
   314  func (g *deepCopyGenerator) writeHeader(b *buffer, inType reflect.Type, indent int) {
   315  	format := "func %s(in %s, out *%s, c *conversion.Cloner) error {\n"
   316  	stmt := fmt.Sprintf(format, g.deepCopyFunctionName(inType), g.typeName(inType), g.typeName(inType))
   317  	b.addLine(stmt, indent)
   318  }
   319  
   320  func (g *deepCopyGenerator) writeFooter(b *buffer, indent int) {
   321  	b.addLine("return nil\n", indent+1)
   322  	b.addLine("}\n", indent)
   323  }
   324  
   325  func (g *deepCopyGenerator) WriteDeepCopyFunctions(w io.Writer) error {
   326  	var keys []reflect.Type
   327  	for key := range g.copyables {
   328  		keys = append(keys, key)
   329  	}
   330  	sort.Sort(byPkgAndName(keys))
   331  
   332  	buffer := newBuffer()
   333  	indent := 0
   334  	for _, inType := range keys {
   335  		if err := g.writeDeepCopyForType(buffer, inType, indent); err != nil {
   336  			return err
   337  		}
   338  		buffer.addLine("\n", 0)
   339  	}
   340  	if err := buffer.flushLines(w); err != nil {
   341  		return err
   342  	}
   343  	return nil
   344  }
   345  
   346  func (g *deepCopyGenerator) writeDeepCopyForMap(b *buffer, inField reflect.StructField, indent int) error {
   347  	ifFormat := "if in.%s != nil {\n"
   348  	ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   349  	b.addLine(ifStmt, indent)
   350  	newFormat := "out.%s = make(%s)\n"
   351  	newStmt := fmt.Sprintf(newFormat, inField.Name, g.typeName(inField.Type))
   352  	b.addLine(newStmt, indent+1)
   353  	forFormat := "for key, val := range in.%s {\n"
   354  	forStmt := fmt.Sprintf(forFormat, inField.Name)
   355  	b.addLine(forStmt, indent+1)
   356  
   357  	switch inField.Type.Key().Kind() {
   358  	case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
   359  		return fmt.Errorf("not supported")
   360  	default:
   361  		switch inField.Type.Elem().Kind() {
   362  		case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
   363  			if _, found := g.copyables[inField.Type.Elem()]; found {
   364  				newFormat := "newVal := new(%s)\n"
   365  				newStmt := fmt.Sprintf(newFormat, g.typeName(inField.Type.Elem()))
   366  				b.addLine(newStmt, indent+2)
   367  				assignFormat := "if err := %s(val, newVal, c); err != nil {\n"
   368  				funcName := g.deepCopyFunctionName(inField.Type.Elem())
   369  				assignStmt := fmt.Sprintf(assignFormat, funcName)
   370  				b.addLine(assignStmt, indent+2)
   371  				b.addLine("return err\n", indent+3)
   372  				b.addLine("}\n", indent+2)
   373  				setFormat := "out.%s[key] = *newVal\n"
   374  				setStmt := fmt.Sprintf(setFormat, inField.Name)
   375  				b.addLine(setStmt, indent+2)
   376  			} else {
   377  				ifStmt := "if newVal, err := c.DeepCopy(val); err != nil {\n"
   378  				b.addLine(ifStmt, indent+2)
   379  				b.addLine("return err\n", indent+3)
   380  				b.addLine("} else {\n", indent+2)
   381  				assignFormat := "out.%s[key] = newVal.(%s)\n"
   382  				assignStmt := fmt.Sprintf(assignFormat, inField.Name, g.typeName(inField.Type.Elem()))
   383  				b.addLine(assignStmt, indent+3)
   384  				b.addLine("}\n", indent+2)
   385  			}
   386  		default:
   387  			assignFormat := "out.%s[key] = val\n"
   388  			assignStmt := fmt.Sprintf(assignFormat, inField.Name)
   389  			b.addLine(assignStmt, indent+2)
   390  		}
   391  	}
   392  	b.addLine("}\n", indent+1)
   393  	b.addLine("} else {\n", indent)
   394  	elseFormat := "out.%s = nil\n"
   395  	elseStmt := fmt.Sprintf(elseFormat, inField.Name)
   396  	b.addLine(elseStmt, indent+1)
   397  	b.addLine("}\n", indent)
   398  	return nil
   399  }
   400  
   401  func (g *deepCopyGenerator) writeDeepCopyForPtr(b *buffer, inField reflect.StructField, indent int) error {
   402  	ifFormat := "if in.%s != nil {\n"
   403  	ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   404  	b.addLine(ifStmt, indent)
   405  
   406  	kind := inField.Type.Elem().Kind()
   407  	switch kind {
   408  	case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
   409  		if _, found := g.copyables[inField.Type.Elem()]; found {
   410  			newFormat := "out.%s = new(%s)\n"
   411  			newStmt := fmt.Sprintf(newFormat, inField.Name, g.typeName(inField.Type.Elem()))
   412  			b.addLine(newStmt, indent+1)
   413  			assignFormat := "if err := %s(*in.%s, out.%s, c); err != nil {\n"
   414  			funcName := g.deepCopyFunctionName(inField.Type.Elem())
   415  			assignStmt := fmt.Sprintf(assignFormat, funcName, inField.Name, inField.Name)
   416  			b.addLine(assignStmt, indent+1)
   417  			b.addLine("return err\n", indent+2)
   418  			b.addLine("}\n", indent+1)
   419  		} else {
   420  			ifFormat := "if newVal, err := c.DeepCopy(in.%s); err != nil {\n"
   421  			ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   422  			b.addLine(ifStmt, indent+1)
   423  			b.addLine("return err\n", indent+2)
   424  			if kind != reflect.Struct {
   425  				b.addLine("} else if newVal == nil {\n", indent+1)
   426  				b.addLine(fmt.Sprintf("out.%s = nil\n", inField.Name), indent+2)
   427  			}
   428  			b.addLine("} else {\n", indent+1)
   429  			assignFormat := "out.%s = newVal.(%s)\n"
   430  			assignStmt := fmt.Sprintf(assignFormat, inField.Name, g.typeName(inField.Type))
   431  			b.addLine(assignStmt, indent+2)
   432  			b.addLine("}\n", indent+1)
   433  		}
   434  	default:
   435  		newFormat := "out.%s = new(%s)\n"
   436  		newStmt := fmt.Sprintf(newFormat, inField.Name, g.typeName(inField.Type.Elem()))
   437  		b.addLine(newStmt, indent+1)
   438  		assignFormat := "*out.%s = *in.%s\n"
   439  		assignStmt := fmt.Sprintf(assignFormat, inField.Name, inField.Name)
   440  		b.addLine(assignStmt, indent+1)
   441  	}
   442  	b.addLine("} else {\n", indent)
   443  	elseFormat := "out.%s = nil\n"
   444  	elseStmt := fmt.Sprintf(elseFormat, inField.Name)
   445  	b.addLine(elseStmt, indent+1)
   446  	b.addLine("}\n", indent)
   447  	return nil
   448  }
   449  
   450  func (g *deepCopyGenerator) writeDeepCopyForSlice(b *buffer, inField reflect.StructField, indent int) error {
   451  	ifFormat := "if in.%s != nil {\n"
   452  	ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   453  	b.addLine(ifStmt, indent)
   454  	newFormat := "out.%s = make(%s, len(in.%s))\n"
   455  	newStmt := fmt.Sprintf(newFormat, inField.Name, g.typeName(inField.Type), inField.Name)
   456  	b.addLine(newStmt, indent+1)
   457  	forFormat := "for i := range in.%s {\n"
   458  	forStmt := fmt.Sprintf(forFormat, inField.Name)
   459  	b.addLine(forStmt, indent+1)
   460  
   461  	kind := inField.Type.Elem().Kind()
   462  	switch kind {
   463  	case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface, reflect.Struct:
   464  		if _, found := g.copyables[inField.Type.Elem()]; found {
   465  			assignFormat := "if err := %s(in.%s[i], &out.%s[i], c); err != nil {\n"
   466  			funcName := g.deepCopyFunctionName(inField.Type.Elem())
   467  			assignStmt := fmt.Sprintf(assignFormat, funcName, inField.Name, inField.Name)
   468  			b.addLine(assignStmt, indent+2)
   469  			b.addLine("return err\n", indent+3)
   470  			b.addLine("}\n", indent+2)
   471  		} else {
   472  			ifFormat := "if newVal, err := c.DeepCopy(in.%s[i]); err != nil {\n"
   473  			ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   474  			b.addLine(ifStmt, indent+2)
   475  			b.addLine("return err\n", indent+3)
   476  			if kind != reflect.Struct {
   477  				b.addLine("} else if newVal == nil {\n", indent+2)
   478  				b.addLine(fmt.Sprintf("out.%s[i] = nil\n", inField.Name), indent+3)
   479  			}
   480  			b.addLine("} else {\n", indent+2)
   481  			assignFormat := "out.%s[i] = newVal.(%s)\n"
   482  			assignStmt := fmt.Sprintf(assignFormat, inField.Name, g.typeName(inField.Type.Elem()))
   483  			b.addLine(assignStmt, indent+3)
   484  			b.addLine("}\n", indent+2)
   485  		}
   486  	default:
   487  		assignFormat := "out.%s[i] = in.%s[i]\n"
   488  		assignStmt := fmt.Sprintf(assignFormat, inField.Name, inField.Name)
   489  		b.addLine(assignStmt, indent+2)
   490  	}
   491  	b.addLine("}\n", indent+1)
   492  	b.addLine("} else {\n", indent)
   493  	elseFormat := "out.%s = nil\n"
   494  	elseStmt := fmt.Sprintf(elseFormat, inField.Name)
   495  	b.addLine(elseStmt, indent+1)
   496  	b.addLine("}\n", indent)
   497  	return nil
   498  }
   499  
   500  func (g *deepCopyGenerator) writeDeepCopyForStruct(b *buffer, inType reflect.Type, indent int) error {
   501  	for i := 0; i < inType.NumField(); i++ {
   502  		inField := inType.Field(i)
   503  		switch inField.Type.Kind() {
   504  		case reflect.Map:
   505  			if err := g.writeDeepCopyForMap(b, inField, indent); err != nil {
   506  				return err
   507  			}
   508  		case reflect.Ptr:
   509  			if err := g.writeDeepCopyForPtr(b, inField, indent); err != nil {
   510  				return err
   511  			}
   512  		case reflect.Slice:
   513  			if err := g.writeDeepCopyForSlice(b, inField, indent); err != nil {
   514  				return err
   515  			}
   516  		case reflect.Interface:
   517  			ifFormat := "if newVal, err := c.DeepCopy(in.%s); err != nil {\n"
   518  			ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   519  			b.addLine(ifStmt, indent)
   520  			b.addLine("return err\n", indent+1)
   521  			b.addLine("} else if newVal == nil {\n", indent)
   522  			b.addLine(fmt.Sprintf("out.%s = nil\n", inField.Name), indent+1)
   523  			b.addLine("} else {\n", indent)
   524  			copyFormat := "out.%s = newVal.(%s)\n"
   525  			copyStmt := fmt.Sprintf(copyFormat, inField.Name, g.typeName(inField.Type))
   526  			b.addLine(copyStmt, indent+1)
   527  			b.addLine("}\n", indent)
   528  		case reflect.Struct:
   529  			if _, found := g.copyables[inField.Type]; found {
   530  				ifFormat := "if err := %s(in.%s, &out.%s, c); err != nil {\n"
   531  				funcName := g.deepCopyFunctionName(inField.Type)
   532  				ifStmt := fmt.Sprintf(ifFormat, funcName, inField.Name, inField.Name)
   533  				b.addLine(ifStmt, indent)
   534  				b.addLine("return err\n", indent+1)
   535  				b.addLine("}\n", indent)
   536  			} else {
   537  				ifFormat := "if newVal, err := c.DeepCopy(in.%s); err != nil {\n"
   538  				ifStmt := fmt.Sprintf(ifFormat, inField.Name)
   539  				b.addLine(ifStmt, indent)
   540  				b.addLine("return err\n", indent+1)
   541  				b.addLine("} else {\n", indent)
   542  				assignFormat := "out.%s = newVal.(%s)\n"
   543  				assignStmt := fmt.Sprintf(assignFormat, inField.Name, g.typeName(inField.Type))
   544  				b.addLine(assignStmt, indent+1)
   545  				b.addLine("}\n", indent)
   546  			}
   547  		default:
   548  			// This should handle all simple types.
   549  			assignFormat := "out.%s = in.%s\n"
   550  			assignStmt := fmt.Sprintf(assignFormat, inField.Name, inField.Name)
   551  			b.addLine(assignStmt, indent)
   552  		}
   553  	}
   554  	return nil
   555  }
   556  
   557  func (g *deepCopyGenerator) writeDeepCopyForType(b *buffer, inType reflect.Type, indent int) error {
   558  	g.writeHeader(b, inType, indent)
   559  	switch inType.Kind() {
   560  	case reflect.Struct:
   561  		if err := g.writeDeepCopyForStruct(b, inType, indent+1); err != nil {
   562  			return err
   563  		}
   564  	default:
   565  		return fmt.Errorf("type not supported: %v", inType)
   566  	}
   567  	g.writeFooter(b, indent)
   568  	return nil
   569  }
   570  
   571  func (g *deepCopyGenerator) writeRegisterHeader(b *buffer, pkg string, indent int) {
   572  	b.addLine("func init() {\n", indent)
   573  	registerFormat := "err := %s.AddGeneratedDeepCopyFuncs(\n"
   574  	b.addLine(fmt.Sprintf(registerFormat, pkg), indent+1)
   575  }
   576  
   577  func (g *deepCopyGenerator) writeRegisterFooter(b *buffer, indent int) {
   578  	b.addLine(")\n", indent+1)
   579  	b.addLine("if err != nil {\n", indent+1)
   580  	b.addLine("// if one of the deep copy functions is malformed, detect it immediately.\n", indent+2)
   581  	b.addLine("panic(err)\n", indent+2)
   582  	b.addLine("}\n", indent+1)
   583  	b.addLine("}\n", indent)
   584  	b.addLine("\n", indent)
   585  }
   586  
   587  func (g *deepCopyGenerator) RegisterDeepCopyFunctions(w io.Writer, pkg string) error {
   588  	var keys []reflect.Type
   589  	for key := range g.copyables {
   590  		keys = append(keys, key)
   591  	}
   592  	sort.Sort(byPkgAndName(keys))
   593  
   594  	buffer := newBuffer()
   595  	indent := 0
   596  	g.writeRegisterHeader(buffer, pkg, indent)
   597  	for _, inType := range keys {
   598  		funcStmt := fmt.Sprintf("%s,\n", g.deepCopyFunctionName(inType))
   599  		buffer.addLine(funcStmt, indent+2)
   600  	}
   601  	g.writeRegisterFooter(buffer, indent)
   602  	if err := buffer.flushLines(w); err != nil {
   603  		return err
   604  	}
   605  	return nil
   606  }
   607  
   608  func (g *deepCopyGenerator) OverwritePackage(pkg, overwrite string) {
   609  	g.pkgOverwrites[pkg] = overwrite
   610  }