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