...
Run Format

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  // +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 := state.b.Bytes()
   116  		if len(data) < n {
   117  			errorf("invalid string length %d: exceeds input size %d", n, len(data))
   118  		}
   119  		slice[i] = string(data[:n])
   120  		state.b.Drop(n)`,
   121  	},
   122  	{
   123  		"uint",
   124  		"Uint",
   125  		`x := state.decodeUint()
   126  		/*TODO if math.MaxUint32 < x {
   127  			error_(ovfl)
   128  		}*/
   129  		slice[i] = uint(x)`,
   130  	},
   131  	{
   132  		"uint16",
   133  		"Uint16",
   134  		`x := state.decodeUint()
   135  		if math.MaxUint16 < x {
   136  			error_(ovfl)
   137  		}
   138  		slice[i] = uint16(x)`,
   139  	},
   140  	{
   141  		"uint32",
   142  		"Uint32",
   143  		`x := state.decodeUint()
   144  		if math.MaxUint32 < x {
   145  			error_(ovfl)
   146  		}
   147  		slice[i] = uint32(x)`,
   148  	},
   149  	{
   150  		"uint64",
   151  		"Uint64",
   152  		`slice[i] = state.decodeUint()`,
   153  	},
   154  	{
   155  		"uintptr",
   156  		"Uintptr",
   157  		`x := state.decodeUint()
   158  		if uint64(^uintptr(0)) < x {
   159  			error_(ovfl)
   160  		}
   161  		slice[i] = uintptr(x)`,
   162  	},
   163  	// uint8 Handled separately.
   164  }
   165  
   166  func main() {
   167  	log.SetFlags(0)
   168  	log.SetPrefix("decgen: ")
   169  	flag.Parse()
   170  	if flag.NArg() != 0 {
   171  		log.Fatal("usage: decgen [--output filename]")
   172  	}
   173  	var b bytes.Buffer
   174  	fmt.Fprintf(&b, "// Code generated by go run decgen.go -output %s; DO NOT EDIT.\n", *output)
   175  	fmt.Fprint(&b, header)
   176  	printMaps(&b, "Array")
   177  	fmt.Fprint(&b, "\n")
   178  	printMaps(&b, "Slice")
   179  	for _, t := range types {
   180  		fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
   181  		fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder)
   182  	}
   183  	source, err := format.Source(b.Bytes())
   184  	if err != nil {
   185  		log.Fatal("source format error:", err)
   186  	}
   187  	fd, err := os.Create(*output)
   188  	_, err = fd.Write(source)
   189  	if err != nil {
   190  		log.Fatal(err)
   191  	}
   192  }
   193  
   194  func printMaps(b *bytes.Buffer, upperClass string) {
   195  	fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass)
   196  	for _, t := range types {
   197  		fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass)
   198  	}
   199  	fmt.Fprintf(b, "}\n")
   200  }
   201  
   202  const header = `
   203  // Copyright 2014 The Go Authors. All rights reserved.
   204  // Use of this source code is governed by a BSD-style
   205  // license that can be found in the LICENSE file.
   206  
   207  package gob
   208  
   209  import (
   210  	"math"
   211  	"reflect"
   212  )
   213  
   214  `
   215  
   216  const arrayHelper = `
   217  func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   218  	// Can only slice if it is addressable.
   219  	if !v.CanAddr() {
   220  		return false
   221  	}
   222  	return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl)
   223  }
   224  `
   225  
   226  const sliceHelper = `
   227  func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   228  	slice, ok := v.Interface().([]%[1]s)
   229  	if !ok {
   230  		// It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
   231  		return false
   232  	}
   233  	for i := 0; i < length; i++ {
   234  		if state.b.Len() == 0 {
   235  			errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length)
   236  		}
   237  		%[3]s
   238  	}
   239  	return true
   240  }
   241  `
   242  

View as plain text