Home | History | Annotate | Download | only in 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 := 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 `
    241