Source File
generate.go
Belonging Package
golang.org/x/pkgsite/internal/godoc/codec
package codec
import (
)
:= 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())
}
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(, ...)
.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
}{
: ,
: ,
})
}
if , := .Tag.Lookup(fieldTagKey); == "-" {
continue
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
}
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
}
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_", "[", "_", "]", "_", ".", "_", "*", "")
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»
)
`
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 })
}
`
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 })
}
`
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
})
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |