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 `