1
2
3
4
5
6
7
8
9
10
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", "enc_helpers.go", "file name to write")
24
25 type Type struct {
26 lower string
27 upper string
28 zero string
29 encoder string
30 }
31
32 var types = []Type{
33 {
34 "bool",
35 "Bool",
36 "false",
37 `if x {
38 state.encodeUint(1)
39 } else {
40 state.encodeUint(0)
41 }`,
42 },
43 {
44 "complex64",
45 "Complex64",
46 "0+0i",
47 `rpart := floatBits(float64(real(x)))
48 ipart := floatBits(float64(imag(x)))
49 state.encodeUint(rpart)
50 state.encodeUint(ipart)`,
51 },
52 {
53 "complex128",
54 "Complex128",
55 "0+0i",
56 `rpart := floatBits(real(x))
57 ipart := floatBits(imag(x))
58 state.encodeUint(rpart)
59 state.encodeUint(ipart)`,
60 },
61 {
62 "float32",
63 "Float32",
64 "0",
65 `bits := floatBits(float64(x))
66 state.encodeUint(bits)`,
67 },
68 {
69 "float64",
70 "Float64",
71 "0",
72 `bits := floatBits(x)
73 state.encodeUint(bits)`,
74 },
75 {
76 "int",
77 "Int",
78 "0",
79 `state.encodeInt(int64(x))`,
80 },
81 {
82 "int16",
83 "Int16",
84 "0",
85 `state.encodeInt(int64(x))`,
86 },
87 {
88 "int32",
89 "Int32",
90 "0",
91 `state.encodeInt(int64(x))`,
92 },
93 {
94 "int64",
95 "Int64",
96 "0",
97 `state.encodeInt(x)`,
98 },
99 {
100 "int8",
101 "Int8",
102 "0",
103 `state.encodeInt(int64(x))`,
104 },
105 {
106 "string",
107 "String",
108 `""`,
109 `state.encodeUint(uint64(len(x)))
110 state.b.WriteString(x)`,
111 },
112 {
113 "uint",
114 "Uint",
115 "0",
116 `state.encodeUint(uint64(x))`,
117 },
118 {
119 "uint16",
120 "Uint16",
121 "0",
122 `state.encodeUint(uint64(x))`,
123 },
124 {
125 "uint32",
126 "Uint32",
127 "0",
128 `state.encodeUint(uint64(x))`,
129 },
130 {
131 "uint64",
132 "Uint64",
133 "0",
134 `state.encodeUint(x)`,
135 },
136 {
137 "uintptr",
138 "Uintptr",
139 "0",
140 `state.encodeUint(uint64(x))`,
141 },
142
143 }
144
145 func main() {
146 log.SetFlags(0)
147 log.SetPrefix("encgen: ")
148 flag.Parse()
149 if flag.NArg() != 0 {
150 log.Fatal("usage: encgen [--output filename]")
151 }
152 var b bytes.Buffer
153 fmt.Fprintf(&b, "// Code generated by go run encgen.go -output %s; DO NOT EDIT.\n", *output)
154 fmt.Fprint(&b, header)
155 printMaps(&b, "Array")
156 fmt.Fprint(&b, "\n")
157 printMaps(&b, "Slice")
158 for _, t := range types {
159 fmt.Fprintf(&b, arrayHelper, t.lower, t.upper)
160 fmt.Fprintf(&b, sliceHelper, t.lower, t.upper, t.zero, t.encoder)
161 }
162 source, err := format.Source(b.Bytes())
163 if err != nil {
164 log.Fatal("source format error:", err)
165 }
166 fd, err := os.Create(*output)
167 if err != nil {
168 log.Fatal(err)
169 }
170 if _, err := fd.Write(source); err != nil {
171 log.Fatal(err)
172 }
173 if err := fd.Close(); err != nil {
174 log.Fatal(err)
175 }
176 }
177
178 func printMaps(b *bytes.Buffer, upperClass string) {
179 fmt.Fprintf(b, "var enc%sHelper = map[reflect.Kind]encHelper{\n", upperClass)
180 for _, t := range types {
181 fmt.Fprintf(b, "reflect.%s: enc%s%s,\n", t.upper, t.upper, upperClass)
182 }
183 fmt.Fprintf(b, "}\n")
184 }
185
186 const header = `
187 // Copyright 2014 The Go Authors. All rights reserved.
188 // Use of this source code is governed by a BSD-style
189 // license that can be found in the LICENSE file.
190
191 package gob
192
193 import (
194 "reflect"
195 )
196
197 `
198
199 const arrayHelper = `
200 func enc%[2]sArray(state *encoderState, v reflect.Value) bool {
201 // Can only slice if it is addressable.
202 if !v.CanAddr() {
203 return false
204 }
205 return enc%[2]sSlice(state, v.Slice(0, v.Len()))
206 }
207 `
208
209 const sliceHelper = `
210 func enc%[2]sSlice(state *encoderState, v reflect.Value) bool {
211 slice, ok := v.Interface().([]%[1]s)
212 if !ok {
213 // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
214 return false
215 }
216 for _, x := range slice {
217 if x != %[3]s || state.sendZero {
218 %[4]s
219 }
220 }
221 return true
222 }
223 `
224
View as plain text