...

Source file src/encoding/gob/encgen.go

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build ignore
     6	
     7	// encgen writes the helper functions for encoding. Intended to be
     8	// used with go generate; see the invocation in encode.go.
     9	
    10	// TODO: We could do more by being unsafe. Add a -unsafe flag?
    11	
    12	package main
    13	
    14	import (
    15		"bytes"
    16		"flag"
    17		"fmt"
    18		"go/format"
    19		"log"
    20		"os"
    21	)
    22	
    23	var output = flag.String("output", "enc_helpers.go", "file name to write")
    24	
    25	type Type struct {
    26		lower   string
    27		upper   string
    28		zero    string
    29		encoder string
    30	}
    31	
    32	var types = []Type{
    33		{
    34			"bool",
    35			"Bool",
    36			"false",
    37			`if x {
    38				state.encodeUint(1)
    39			} else {
    40				state.encodeUint(0)
    41			}`,
    42		},
    43		{
    44			"complex64",
    45			"Complex64",
    46			"0+0i",
    47			`rpart := floatBits(float64(real(x)))
    48			ipart := floatBits(float64(imag(x)))
    49			state.encodeUint(rpart)
    50			state.encodeUint(ipart)`,
    51		},
    52		{
    53			"complex128",
    54			"Complex128",
    55			"0+0i",
    56			`rpart := floatBits(real(x))
    57			ipart := floatBits(imag(x))
    58			state.encodeUint(rpart)
    59			state.encodeUint(ipart)`,
    60		},
    61		{
    62			"float32",
    63			"Float32",
    64			"0",
    65			`bits := floatBits(float64(x))
    66			state.encodeUint(bits)`,
    67		},
    68		{
    69			"float64",
    70			"Float64",
    71			"0",
    72			`bits := floatBits(x)
    73			state.encodeUint(bits)`,
    74		},
    75		{
    76			"int",
    77			"Int",
    78			"0",
    79			`state.encodeInt(int64(x))`,
    80		},
    81		{
    82			"int16",
    83			"Int16",
    84			"0",
    85			`state.encodeInt(int64(x))`,
    86		},
    87		{
    88			"int32",
    89			"Int32",
    90			"0",
    91			`state.encodeInt(int64(x))`,
    92		},
    93		{
    94			"int64",
    95			"Int64",
    96			"0",
    97			`state.encodeInt(x)`,
    98		},
    99		{
   100			"int8",
   101			"Int8",
   102			"0",
   103			`state.encodeInt(int64(x))`,
   104		},
   105		{
   106			"string",
   107			"String",
   108			`""`,
   109			`state.encodeUint(uint64(len(x)))
   110			state.b.WriteString(x)`,
   111		},
   112		{
   113			"uint",
   114			"Uint",
   115			"0",
   116			`state.encodeUint(uint64(x))`,
   117		},
   118		{
   119			"uint16",
   120			"Uint16",
   121			"0",
   122			`state.encodeUint(uint64(x))`,
   123		},
   124		{
   125			"uint32",
   126			"Uint32",
   127			"0",
   128			`state.encodeUint(uint64(x))`,
   129		},
   130		{
   131			"uint64",
   132			"Uint64",
   133			"0",
   134			`state.encodeUint(x)`,
   135		},
   136		{
   137			"uintptr",
   138			"Uintptr",
   139			"0",
   140			`state.encodeUint(uint64(x))`,
   141		},
   142		// uint8 Handled separately.
   143	}
   144	
   145	func main() {
   146		log.SetFlags(0)
   147		log.SetPrefix("encgen: ")
   148		flag.Parse()
   149		if flag.NArg() != 0 {
   150			log.Fatal("usage: encgen [--output filename]")
   151		}
   152		var b bytes.Buffer
   153		fmt.Fprintf(&b, "// Code generated by go run encgen.go -output %s; DO NOT EDIT.\n", *output)
   154		fmt.Fprint(&b, header)
   155		printMaps(&b, "Array")
   156		fmt.Fprint(&b, "\n")
   157		printMaps(&b, "Slice")
   158		for _, t := range types {
   159			fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
   160			fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.zero, t.encoder)
   161		}
   162		source, err := format.Source(b.Bytes())
   163		if err != nil {
   164			log.Fatal("source format error:", err)
   165		}
   166		fd, err := os.Create(*output)
   167		if err != nil {
   168			log.Fatal(err)
   169		}
   170		if _, err := fd.Write(source); err != nil {
   171			log.Fatal(err)
   172		}
   173	}
   174	
   175	func printMaps(b *bytes.Buffer, upperClass string) {
   176		fmt.Fprintf(b, "var enc%sHelper = map[reflect.Kind]encHelper{\n", upperClass)
   177		for _, t := range types {
   178			fmt.Fprintf(b, "reflect.%s: enc%s%s,\n", t.upper, t.upper, upperClass)
   179		}
   180		fmt.Fprintf(b, "}\n")
   181	}
   182	
   183	const header = `
   184	// Copyright 2014 The Go Authors. All rights reserved.
   185	// Use of this source code is governed by a BSD-style
   186	// license that can be found in the LICENSE file.
   187	
   188	package gob
   189	
   190	import (
   191		"reflect"
   192	)
   193	
   194	`
   195	
   196	const arrayHelper = `
   197	func enc%[2]sArray(state *encoderState, v reflect.Value) bool {
   198		// Can only slice if it is addressable.
   199		if !v.CanAddr() {
   200			return false
   201		}
   202		return enc%[2]sSlice(state, v.Slice(0, v.Len()))
   203	}
   204	`
   205	
   206	const sliceHelper = `
   207	func enc%[2]sSlice(state *encoderState, v reflect.Value) bool {
   208		slice, ok := v.Interface().([]%[1]s)
   209		if !ok {
   210			// It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
   211			return false
   212		}
   213		for _, x := range slice {
   214			if x != %[3]s || state.sendZero {
   215				%[4]s
   216			}
   217		}
   218		return true
   219	}
   220	`
   221	

View as plain text