Black Lives Matter. Support the Equal Justice Initiative.

Source file src/encoding/gob/decgen.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", "dec_helpers.go", "file name to write")
    25  
    26  type Type struct {
    27  	lower   string
    28  	upper   string
    29  	decoder string
    30  }
    31  
    32  var types = []Type{
    33  	{
    34  		"bool",
    35  		"Bool",
    36  		`slice[i] = state.decodeUint() != 0`,
    37  	},
    38  	{
    39  		"complex64",
    40  		"Complex64",
    41  		`real := float32FromBits(state.decodeUint(), ovfl)
    42  		imag := float32FromBits(state.decodeUint(), ovfl)
    43  		slice[i] = complex(float32(real), float32(imag))`,
    44  	},
    45  	{
    46  		"complex128",
    47  		"Complex128",
    48  		`real := float64FromBits(state.decodeUint())
    49  		imag := float64FromBits(state.decodeUint())
    50  		slice[i] = complex(real, imag)`,
    51  	},
    52  	{
    53  		"float32",
    54  		"Float32",
    55  		`slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))`,
    56  	},
    57  	{
    58  		"float64",
    59  		"Float64",
    60  		`slice[i] = float64FromBits(state.decodeUint())`,
    61  	},
    62  	{
    63  		"int",
    64  		"Int",
    65  		`x := state.decodeInt()
    66  		// MinInt and MaxInt
    67  		if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x {
    68  			error_(ovfl)
    69  		}
    70  		slice[i] = int(x)`,
    71  	},
    72  	{
    73  		"int16",
    74  		"Int16",
    75  		`x := state.decodeInt()
    76  		if x < math.MinInt16 || math.MaxInt16 < x {
    77  			error_(ovfl)
    78  		}
    79  		slice[i] = int16(x)`,
    80  	},
    81  	{
    82  		"int32",
    83  		"Int32",
    84  		`x := state.decodeInt()
    85  		if x < math.MinInt32 || math.MaxInt32 < x {
    86  			error_(ovfl)
    87  		}
    88  		slice[i] = int32(x)`,
    89  	},
    90  	{
    91  		"int64",
    92  		"Int64",
    93  		`slice[i] = state.decodeInt()`,
    94  	},
    95  	{
    96  		"int8",
    97  		"Int8",
    98  		`x := state.decodeInt()
    99  		if x < math.MinInt8 || math.MaxInt8 < x {
   100  			error_(ovfl)
   101  		}
   102  		slice[i] = int8(x)`,
   103  	},
   104  	{
   105  		"string",
   106  		"String",
   107  		`u := state.decodeUint()
   108  		n := int(u)
   109  		if n < 0 || uint64(n) != u || n > state.b.Len() {
   110  			errorf("length of string exceeds input size (%d bytes)", u)
   111  		}
   112  		if n > state.b.Len() {
   113  			errorf("string data too long for buffer: %d", n)
   114  		}
   115  		// Read the data.
   116  		data := state.b.Bytes()
   117  		if len(data) < n {
   118  			errorf("invalid string length %d: exceeds input size %d", n, len(data))
   119  		}
   120  		slice[i] = string(data[:n])
   121  		state.b.Drop(n)`,
   122  	},
   123  	{
   124  		"uint",
   125  		"Uint",
   126  		`x := state.decodeUint()
   127  		/*TODO if math.MaxUint32 < x {
   128  			error_(ovfl)
   129  		}*/
   130  		slice[i] = uint(x)`,
   131  	},
   132  	{
   133  		"uint16",
   134  		"Uint16",
   135  		`x := state.decodeUint()
   136  		if math.MaxUint16 < x {
   137  			error_(ovfl)
   138  		}
   139  		slice[i] = uint16(x)`,
   140  	},
   141  	{
   142  		"uint32",
   143  		"Uint32",
   144  		`x := state.decodeUint()
   145  		if math.MaxUint32 < x {
   146  			error_(ovfl)
   147  		}
   148  		slice[i] = uint32(x)`,
   149  	},
   150  	{
   151  		"uint64",
   152  		"Uint64",
   153  		`slice[i] = state.decodeUint()`,
   154  	},
   155  	{
   156  		"uintptr",
   157  		"Uintptr",
   158  		`x := state.decodeUint()
   159  		if uint64(^uintptr(0)) < x {
   160  			error_(ovfl)
   161  		}
   162  		slice[i] = uintptr(x)`,
   163  	},
   164  	// uint8 Handled separately.
   165  }
   166  
   167  func main() {
   168  	log.SetFlags(0)
   169  	log.SetPrefix("decgen: ")
   170  	flag.Parse()
   171  	if flag.NArg() != 0 {
   172  		log.Fatal("usage: decgen [--output filename]")
   173  	}
   174  	var b bytes.Buffer
   175  	fmt.Fprintf(&b, "// Code generated by go run decgen.go -output %s; DO NOT EDIT.\n", *output)
   176  	fmt.Fprint(&b, header)
   177  	printMaps(&b, "Array")
   178  	fmt.Fprint(&b, "\n")
   179  	printMaps(&b, "Slice")
   180  	for _, t := range types {
   181  		fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
   182  		fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder)
   183  	}
   184  	source, err := format.Source(b.Bytes())
   185  	if err != nil {
   186  		log.Fatal("source format error:", err)
   187  	}
   188  	fd, err := os.Create(*output)
   189  	if err != nil {
   190  		log.Fatal(err)
   191  	}
   192  	if _, err := fd.Write(source); err != nil {
   193  		log.Fatal(err)
   194  	}
   195  }
   196  
   197  func printMaps(b *bytes.Buffer, upperClass string) {
   198  	fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass)
   199  	for _, t := range types {
   200  		fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass)
   201  	}
   202  	fmt.Fprintf(b, "}\n")
   203  }
   204  
   205  const header = `
   206  // Copyright 2014 The Go Authors. All rights reserved.
   207  // Use of this source code is governed by a BSD-style
   208  // license that can be found in the LICENSE file.
   209  
   210  package gob
   211  
   212  import (
   213  	"math"
   214  	"reflect"
   215  )
   216  
   217  `
   218  
   219  const arrayHelper = `
   220  func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   221  	// Can only slice if it is addressable.
   222  	if !v.CanAddr() {
   223  		return false
   224  	}
   225  	return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl)
   226  }
   227  `
   228  
   229  const sliceHelper = `
   230  func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   231  	slice, ok := v.Interface().([]%[1]s)
   232  	if !ok {
   233  		// It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
   234  		return false
   235  	}
   236  	for i := 0; i < length; i++ {
   237  		if state.b.Len() == 0 {
   238  			errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length)
   239  		}
   240  		%[3]s
   241  	}
   242  	return true
   243  }
   244  `
   245  

View as plain text