...

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  
     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  	if err := fd.Close(); err != nil {
   196  		log.Fatal(err)
   197  	}
   198  }
   199  
   200  func printMaps(b *bytes.Buffer, upperClass string) {
   201  	fmt.Fprintf(b, "var dec%sHelper = map[reflect.Kind]decHelper{\n", upperClass)
   202  	for _, t := range types {
   203  		fmt.Fprintf(b, "reflect.%s: dec%s%s,\n", t.upper, t.upper, upperClass)
   204  	}
   205  	fmt.Fprintf(b, "}\n")
   206  }
   207  
   208  const header = `
   209  // Copyright 2014 The Go Authors. All rights reserved.
   210  // Use of this source code is governed by a BSD-style
   211  // license that can be found in the LICENSE file.
   212  
   213  package gob
   214  
   215  import (
   216  	"math"
   217  	"reflect"
   218  )
   219  
   220  `
   221  
   222  const arrayHelper = `
   223  func dec%[2]sArray(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   224  	// Can only slice if it is addressable.
   225  	if !v.CanAddr() {
   226  		return false
   227  	}
   228  	return dec%[2]sSlice(state, v.Slice(0, v.Len()), length, ovfl)
   229  }
   230  `
   231  
   232  const sliceHelper = `
   233  func dec%[2]sSlice(state *decoderState, v reflect.Value, length int, ovfl error) bool {
   234  	slice, ok := v.Interface().([]%[1]s)
   235  	if !ok {
   236  		// It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
   237  		return false
   238  	}
   239  	for i := 0; i < length; i++ {
   240  		if state.b.Len() == 0 {
   241  			errorf("decoding %[1]s array or slice: length exceeds input size (%%d elements)", length)
   242  		}
   243  		if i >= len(slice) {
   244  			// This is a slice that we only partially allocated.
   245  			growSlice(v, &slice, length)
   246  		}
   247  		%[3]s
   248  	}
   249  	return true
   250  }
   251  `
   252  
   253  const trailer = `
   254  // growSlice is called for a slice that we only partially allocated,
   255  // to grow it up to length.
   256  func growSlice[E any](v reflect.Value, ps *[]E, length int) {
   257  	var zero E
   258  	s := *ps
   259  	s = append(s, zero)
   260  	cp := cap(s)
   261  	if cp > length {
   262  		cp = length
   263  	}
   264  	s = s[:cp]
   265  	v.Set(reflect.ValueOf(s))
   266  	*ps = s
   267  }
   268  `
   269  

View as plain text