Black Lives Matter. Support the Equal Justice Initiative.

Source file src/encoding/gob/encgen.go

Documentation: encoding/gob

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

View as plain text