Copyright 2020 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package codec

import (
	
	
	
	
	
	
	
	
	
	
)
GenerateFile writes encoders and decoders to filename. It generates code for the type of each given value, as well as any types they depend on. packageName is the name following the file's package declaration.
func (,  string,  ...interface{}) error {
	if !strings.HasSuffix(, ".go") {
		 += ".go"
	}
	,  := readFieldNames()
	if  != nil {
		return 
	}
	,  := os.Create()
	if  != nil {
		return 
	}
	 = generate(, , , ...)
	 := .Close()
	if  != nil {
		return 
	}
	return 
}
readFieldNames scan filename, if it exists, to get the previous field names for structs. It returns a map from struct name to list of field names.
func ( string) (map[string][]string, error) {
	,  := os.Open()
	if  != nil {
		if os.IsNotExist() {
			return nil, nil
		}
		return nil, 
	}
	defer .Close()
	 := map[string][]string{}
	 := bufio.NewScanner()
	for .Scan() {
		 := .Text()
form of line: // Fields of STRUCTNAME: NAME1 NAME2 ...
			 := strings.Fields()
			 := [3][:len([3])-1] // remove final colon
			[] = [4:]
		}
	}
	if  := .Err();  != nil {
		return nil, 
	}
	return , nil
}

func ( io.Writer,  string,  map[string][]string,  ...interface{}) error {
	 := &generator{
		pkg:        ,
		done:       map[reflect.Type]bool{},
		fieldNames: ,
	}
	if .fieldNames == nil {
		.fieldNames = map[string][]string{}
	}
	 := template.FuncMap{
		"funcName":   .funcName,
		"goName":     .goName,
		"encodeStmt": .encodeStatement,
		"decodeStmt": .decodeStatement,
	}

	 := func(,  string) *template.Template {
		return template.Must(template.New().Delims("«", "»").Funcs().Parse())
	}

	.initialTemplate = ("initial", initialBody)
	.sliceTemplate = ("slice", sliceBody)
	.mapTemplate = ("map", mapBody)
	.structTemplate = ("struct", structBody)

	for ,  := range  {
		.todo = append(.todo, reflect.TypeOf())
	}
Mark the built-in types as done.
	for ,  := range builtinTypes {
		.done[] = true
		if .Kind() == reflect.Ptr && .Elem().Kind() == reflect.Struct {
			.done[.Elem()] = true
		}
The empty interface doesn't need any additional code. It's tricky to get its reflect.Type: we need to dereference the pointer type.
	var  interface{}
	.done[reflect.TypeOf(&).Elem()] = true

	,  := .generate()
	if  != nil {
		return 
	}
	,  = format.Source()
	if  != nil {
		return fmt.Errorf("format.Source: %v", )
	}
	_,  = .Write()
	return 
}

type generator struct {
	pkg             string
	todo            []reflect.Type
	done            map[reflect.Type]bool
	fieldNames      map[string][]string
	initialTemplate *template.Template
	sliceTemplate   *template.Template
	mapTemplate     *template.Template
	structTemplate  *template.Template
}

func ( *generator) () ([]byte, error) {
	 := map[string]bool{
		"golang.org/x/pkgsite/internal/godoc/codec": true,
	}
	var  []byte
	for len(.todo) > 0 {
		 := .todo[0]
		.todo = .todo[1:]
		if !.done[] {
			if .PkgPath() != "" {
				[.PkgPath()] = true
			}
			,  := .gen()
			if  != nil {
				return nil, 
			}
			if  != nil {
				 = append(, ...)
We use the same code for T and *T, so both are done.
			.done[] = true
			.done[reflect.PtrTo()] = true
		}
	}

	var  []string
	for  := range  {
		 = append(, )
	}
	sort.Strings()
	,  := execute(.initialTemplate, struct {
		 string
		 []string
	}{
		: .pkg,
		: ,
	})
	if  != nil {
		return nil, 
	}
	return append(, ...), nil
}

func ( *generator) ( reflect.Type) ([]byte, error) {
	switch .Kind() {
	case reflect.Slice:
		return .genSlice()
	case reflect.Map:
		return .genMap()
	case reflect.Struct:
		return .genStruct()
	case reflect.Ptr:
		return .(.Elem())
	}
	return nil, nil
}

func ( *generator) ( reflect.Type) ([]byte, error) {
	 := .Elem()
	.todo = append(.todo, )
	return execute(.sliceTemplate, struct {
		,  reflect.Type
	}{
		:   ,
		: ,
	})
}

func ( *generator) ( reflect.Type) ([]byte, error) {
	 := .Elem()
	 := .Key()
	.todo = append(.todo, , )
	return execute(.mapTemplate, struct {
		, ,  reflect.Type
	}{
		:    ,
		:  ,
		: ,
	})
}

func ( *generator) ( reflect.Type) ([]byte, error) {
	 := .funcName()
	var  []field
	 = exportedFields(, .fieldNames[])
	var  []string
	for ,  := range  {
		 = append(, .Name)
		 := .Type
		if  == nil {
			continue
		}
		if .Kind() == reflect.Ptr {
			 = .Elem()
		}
		.todo = append(.todo, )
	}
	.fieldNames[] =  // Update list field names.
	return execute(.structTemplate, struct {
		   reflect.Type
		 []field
	}{
		:   ,
		: ,
	})
}
A field holds the information necessary to generate the encoder for a struct field.
type field struct {
	Name string
	Type reflect.Type
	Zero string // representation of the type's zero value
}

const fieldTagKey = "codec"
exportedFields returns the exported fields of the struct type t that should be encoded, in the proper order. Exported fields of embedded, unexported types are not included. If there was a previous ordering, it is preserved, and new fields are added to the end. If a field was removed, we keep its number so as not to break existing encoded values. It will appear in the return value with an empty type. One drawback of this scheme is that it is not possible to rename a field. A rename will look like an addition and a removal.
Record the positions of the field names previously used for this struct, so we can preserve them.
	 := map[string]int{}
	for ,  := range  {
		[] = 
	}
If there are any new exported fields, assign them positions after the existing ones.
	for  := 0;  < .NumField(); ++ {
		 := .Field()
		if .PkgPath != "" { // Ignore unexported fields. A field is exported if its PkgPath is empty.
			continue
Ignore a field if it has a struct tag with "-", like encoding/json.
		if ,  := .Tag.Lookup(fieldTagKey);  == "-" {
			continue
Ignore fields of function and channel type.
		if .Type.Kind() == reflect.Chan || .Type.Kind() == reflect.Func {
			continue
		}
		if ,  := [.Name]; ! {
			[.Name] = len()
		}
	}
Populate the field structs, in the right order.
	 := make([]field, len())
	for  := 0;  < .NumField(); ++ {
		 := .Field()
		if ,  := [.Name];  {
			[] = field{
				Name: .Name,
				Type: .Type,
				Zero: zeroValue(.Type),
			}
		}
Add back in the removed names, so their positions can be preserved in the future.
	for ,  := range  {
		if [].Name == "" {
			[].Name = 
		}
	}
	return 
}
zeroValue returns the string representation of a zero value of type t, or the empty string if there isn't one.
func ( reflect.Type) string {
	switch .Kind() {
	case reflect.Bool:
		return "false"
	case reflect.String:
		return `""`
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return "0"
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return "0"
	case reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
		return "0"
	case reflect.Ptr, reflect.Slice, reflect.Map, reflect.Interface:
		return "nil"
	default:
		return ""
	}
}

func ( *template.Template,  interface{}) ([]byte, error) {
	var  bytes.Buffer
	if  := .Execute(&, );  != nil {
		return nil, 
	}
	return .Bytes(), nil
}
encodeStatement returns a Go statement that encodes a value denoted by arg, of type t.
func ( *generator) ( reflect.Type,  string) string {
	,  := builtinName()
t can be handled by an Encoder method.
t is not the Encoder method's argument type, so we must cast.
			 = fmt.Sprintf("%s(%s)", , )
		}
		return fmt.Sprintf("e.Encode%s(%s)", , )
	}
	if .Kind() == reflect.Interface {
		return fmt.Sprintf("e.EncodeAny(%s)", )
	}
	return fmt.Sprintf("encode_%s(e, %s)", .funcName(), )
}

func ( *generator) ( reflect.Type,  string) string {
	,  := builtinName()
t can be handled by a Decoder method.
t is not the Decoder method's return type, so we must cast.
			return fmt.Sprintf("%s = %s(d.Decode%s())", , .goName(), )
		}
		return fmt.Sprintf("%s = d.Decode%s()", , )
	}
t is an interface, so use DecodeAny, possibly with a type assertion.
		if .NumMethod() == 0 {
			return fmt.Sprintf("%s = d.DecodeAny()", )
		}
		return fmt.Sprintf("%s = d.DecodeAny().(%s)", , .goName())
Assume we will generate a decode method for t.
	return fmt.Sprintf("decode_%s(d, &%s)", .funcName(), )
}
builtinName returns the suffix to append to "encode" or "decode" to get the Encoder/Decoder method name for t. If t cannot be encoded by an Encoder method, the suffix is "". The second return value is the "native" type of the method: the argument to the Encoder method, and the return value of the Decoder method.
func ( reflect.Type) ( string,  reflect.Type) {
	switch .Kind() {
	case reflect.String:
		return "String", reflect.TypeOf("")
	case reflect.Bool:
		return "Bool", reflect.TypeOf(true)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return "Int", reflect.TypeOf(int64(0))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return "Uint", reflect.TypeOf(uint64(0))
	case reflect.Float32, reflect.Float64:
		return "Float64", reflect.TypeOf(0.0)
	case reflect.Slice:
		if .Elem() == reflect.TypeOf(byte(0)) {
			return "Bytes", reflect.TypeOf([]byte(nil))
		}
	}
	return "", nil
}
goName returns the name of t as it should appear in a Go program. E.g. "go/ast.File" => ast.File It assumes all package paths are represented in the file by their last element.
func ( *generator) ( reflect.Type) string {
	switch .Kind() {
	case reflect.Slice:
		return fmt.Sprintf("[]%s", .(.Elem()))
	case reflect.Map:
		return fmt.Sprintf("map[%s]%s", .(.Key()), .(.Elem()))
	case reflect.Ptr:
		return fmt.Sprintf("*%s", .(.Elem()))
	default:
		 := .String()
		if strings.HasPrefix(, .pkg+".") {
			 = [len(.pkg)+1:]
		}
		return 
	}
}

var funcNameReplacer = strings.NewReplacer("[]", "slice_", "[", "_", "]", "_", ".", "_", "*", "")
funcName returns the name for t that is used as part of the encode/decode function name. E.g. "ast.File" => "ast_File".
Template body for the beginning of the file.
const initialBody = `
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated by the codec package. DO NOT EDIT.

package «.Package»

import (
	«range .Imports»
		"«.»"
	«- end»
)

`
Template body for a sliceBody type.
const sliceBody = `
« $funcName := funcName .Type »
« $goName := goName .Type »
func encode_«$funcName»(e *codec.Encoder, s «$goName») {
	if s == nil {
		e.EncodeNil()
		return
	}
	e.StartList(len(s))
	for _, x := range s {
		«encodeStmt .ElType "x"»
	}
}

func decode_«$funcName»(d *codec.Decoder, p *«$goName») {
	n := d.StartList()
	if n < 0 { return }
	s := make([]«goName .ElType», n)
	for i := 0; i < n; i++ {
		«decodeStmt .ElType "s[i]"»
	}
	*p = s
}

func init() {
  codec.Register(«$goName»(nil),
    func(e *codec.Encoder, x interface{}) { encode_«$funcName»(e, x.(«$goName»)) },
    func(d *codec.Decoder) interface{} { var x «$goName»; decode_«$funcName»(d, &x); return x })
}
`
Template body for a map type. A nil map is encoded as a zero. A map of size N is encoded as a list of length 2N, containing alternating keys and values. In the decode function, we declare a variable v to hold the decoded map value rather than decoding directly into m[v]. This is necessary for decode functions that take pointers: you can't take a pointer to a map element.
const mapBody = `
« $funcName := funcName .Type »
« $goName := goName .Type »
func encode_«$funcName»(e *codec.Encoder, m «$goName») {
	if m == nil {
		e.EncodeNil()
		return
	}
	e.StartList(2*len(m))
	for k, v := range m {
		«encodeStmt .KeyType "k"»
		«encodeStmt .ElType "v"»
	}
}

func decode_«$funcName»(d *codec.Decoder, p *«$goName») {
	n2 := d.StartList()
	if n2 < 0 { return }
	n := n2/2
	m := make(«$goName», n)
	var k «goName .KeyType»
	var v «goName .ElType»
	for i := 0; i < n; i++ {
		«decodeStmt .KeyType "k"»
		«decodeStmt .ElType "v"»
		m[k] = v
	}
	*p = m
}

func init() {
	codec.Register(«$goName»(nil),
	func(e *codec.Encoder, x interface{}) { encode_«$funcName»(e, x.(«$goName»)) },
	func(d *codec.Decoder) interface{} { var x «$goName»; decode_«$funcName»(d, &x); return x })
}
`
Template body for a (pointer to a) struct type. A nil pointer is encoded as a zero. (This is done in Encoder.StartStruct.) Otherwise, a struct is encoded as the start code, its exported fields, then the end code. Each non-zero field is encoded as its field number followed by its value. A field that equals its zero value isn't encoded. The comment listing the field names is used when re-generating the file, to make sure we don't alter the existing mapping from field names to numbers.
const structBody = `
« $funcName := funcName .Type »
« $goName := goName .Type »

// Fields of «$funcName»:«range .Fields» «.Name»«end»

func encode_«$funcName»(e *codec.Encoder, x *«$goName») {
	if !e.StartStruct(x==nil, x) { return }
	«range $i, $f := .Fields»
		«- if $f.Type -»
			«- if $f.Zero -»
				if x.«$f.Name» != «$f.Zero» {
			«- end»
			e.EncodeUint(«$i»)
			«encodeStmt .Type (print "x." $f.Name)»
			«- if $f.Zero -»
			}
			«- end»
		«- end»
	«end -»
	e.EndStruct()
}

func decode_«$funcName»(d *codec.Decoder, p **«$goName») {
	proceed, ref := d.StartStruct()
	if !proceed { return }
	if ref != nil {
		*p = ref.(*«$goName»)
		return
	}
	var x «$goName»
	d.StoreRef(&x)
	for {
		n := d.NextStructField()
		if n < 0 { break }
		switch n {
		«range $i, $f := .Fields -»
			«- if $f.Type -»
				case «$i»:
		        «decodeStmt $f.Type (print "x." $f.Name)»
			«end -»
		«end -»
		default:
			d.UnknownField("«$goName»", n)
		}
		*p = &x
	}
}

func init() {
	codec.Register(&«$goName»{},
		func(e *codec.Encoder, x interface{}) { encode_«$funcName»(e, x.(*«$goName»)) },
		func(d *codec.Decoder) interface{} {
			var x *«$goName»
			decode_«$funcName»(d, &x)
			return x
		})
}