Source file src/encoding/gob/decgen.go

     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  
     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  	fmt.Fprintf(&b, trailer)
   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  		if i >= len(slice) {
   241  			// This is a slice that we only partially allocated.
   242  			growSlice(v, &slice, length)
   243  		}
   244  		%[3]s
   245  	}
   246  	return true
   247  }
   248  `
   249  
   250  const trailer = `
   251  // growSlice is called for a slice that we only partially allocated,
   252  // to grow it up to length.
   253  func growSlice[E any](v reflect.Value, ps *[]E, length int) {
   254  	var zero E
   255  	s := *ps
   256  	s = append(s, zero)
   257  	cp := cap(s)
   258  	if cp > length {
   259  		cp = length
   260  	}
   261  	s = s[:cp]
   262  	v.Set(reflect.ValueOf(s))
   263  	*ps = s
   264  }
   265  `
   266  

View as plain text