github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/encoding/gob/decgen.go (about)

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