1
2
3
4
5
6
7
8
9
10
11
12
13 package main
14
15 import (
16 "bytes"
17 "flag"
18 "fmt"
19 "go/format"
20 "log"
21 "os"
22 )
23
24 var output = flag.String("output", "dec_helpers.go", "file name to write")
25
26 type Type struct {
27 lower string
28 upper string
29 decoder string
30 }
31
32 var types = []Type{
33 {
34 "bool",
35 "Bool",
36 `slice[i] = state.decodeUint() != 0`,
37 },
38 {
39 "complex64",
40 "Complex64",
41 `real := float32FromBits(state.decodeUint(), ovfl)
42 imag := float32FromBits(state.decodeUint(), ovfl)
43 slice[i] = complex(float32(real), float32(imag))`,
44 },
45 {
46 "complex128",
47 "Complex128",
48 `real := float64FromBits(state.decodeUint())
49 imag := float64FromBits(state.decodeUint())
50 slice[i] = complex(real, imag)`,
51 },
52 {
53 "float32",
54 "Float32",
55 `slice[i] = float32(float32FromBits(state.decodeUint(), ovfl))`,
56 },
57 {
58 "float64",
59 "Float64",
60 `slice[i] = float64FromBits(state.decodeUint())`,
61 },
62 {
63 "int",
64 "Int",
65 `x := state.decodeInt()
66 // MinInt and MaxInt
67 if x < ^int64(^uint(0)>>1) || int64(^uint(0)>>1) < x {
68 error_(ovfl)
69 }
70 slice[i] = int(x)`,
71 },
72 {
73 "int16",
74 "Int16",
75 `x := state.decodeInt()
76 if x < math.MinInt16 || math.MaxInt16 < x {
77 error_(ovfl)
78 }
79 slice[i] = int16(x)`,
80 },
81 {
82 "int32",
83 "Int32",
84 `x := state.decodeInt()
85 if x < math.MinInt32 || math.MaxInt32 < x {
86 error_(ovfl)
87 }
88 slice[i] = int32(x)`,
89 },
90 {
91 "int64",
92 "Int64",
93 `slice[i] = state.decodeInt()`,
94 },
95 {
96 "int8",
97 "Int8",
98 `x := state.decodeInt()
99 if x < math.MinInt8 || math.MaxInt8 < x {
100 error_(ovfl)
101 }
102 slice[i] = int8(x)`,
103 },
104 {
105 "string",
106 "String",
107 `u := state.decodeUint()
108 n := int(u)
109 if n < 0 || uint64(n) != u || n > state.b.Len() {
110 errorf("length of string exceeds input size (%d bytes)", u)
111 }
112 if n > state.b.Len() {
113 errorf("string data too long for buffer: %d", n)
114 }
115 // Read the data.
116 data := state.b.Bytes()
117 if len(data) < n {
118 errorf("invalid string length %d: exceeds input size %d", n, len(data))
119 }
120 slice[i] = string(data[:n])
121 state.b.Drop(n)`,
122 },
123 {
124 "uint",
125 "Uint",
126 `x := state.decodeUint()
127 /*TODO if math.MaxUint32 < x {
128 error_(ovfl)
129 }*/
130 slice[i] = uint(x)`,
131 },
132 {
133 "uint16",
134 "Uint16",
135 `x := state.decodeUint()
136 if math.MaxUint16 < x {
137 error_(ovfl)
138 }
139 slice[i] = uint16(x)`,
140 },
141 {
142 "uint32",
143 "Uint32",
144 `x := state.decodeUint()
145 if math.MaxUint32 < x {
146 error_(ovfl)
147 }
148 slice[i] = uint32(x)`,
149 },
150 {
151 "uint64",
152 "Uint64",
153 `slice[i] = state.decodeUint()`,
154 },
155 {
156 "uintptr",
157 "Uintptr",
158 `x := state.decodeUint()
159 if uint64(^uintptr(0)) < x {
160 error_(ovfl)
161 }
162 slice[i] = uintptr(x)`,
163 },
164
165 }
166
167 func main() {
168 log.SetFlags(0)
169 log.SetPrefix("decgen: ")
170 flag.Parse()
171 if flag.NArg() != 0 {
172 log.Fatal("usage: decgen [--output filename]")
173 }
174 var b bytes.Buffer
175 fmt.Fprintf(&b, "// Code generated by go run decgen.go -output %s; DO NOT EDIT.\n", *output)
176 fmt.Fprint(&b, header)
177 printMaps(&b, "Array")
178 fmt.Fprint(&b, "\n")
179 printMaps(&b, "Slice")
180 for _, t := range types {
181 fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
182 fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.decoder)
183 }
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 %[3]s
241 }
242 return true
243 }
244 `
245
View as plain text