github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/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 := 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, "// Created by decgen --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 `