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 }
174
175 func printMaps(b *bytes.Buffer, upperClass string) {
176 fmt.Fprintf(b, "var enc%sHelper = map[reflect.Kind]encHelper{\n", upperClass)
177 for _, t := range types {
178 fmt.Fprintf(b, "reflect.%s: enc%s%s,\n", t.upper, t.upper, upperClass)
179 }
180 fmt.Fprintf(b, "}\n")
181 }
182
183 const header = `
184 // Copyright 2014 The Go Authors. All rights reserved.
185 // Use of this source code is governed by a BSD-style
186 // license that can be found in the LICENSE file.
187
188 package gob
189
190 import (
191 "reflect"
192 )
193
194 `
195
196 const arrayHelper = `
197 func enc%[2]sArray(state *encoderState, v reflect.Value) bool {
198 // Can only slice if it is addressable.
199 if !v.CanAddr() {
200 return false
201 }
202 return enc%[2]sSlice(state, v.Slice(0, v.Len()))
203 }
204 `
205
206 const sliceHelper = `
207 func enc%[2]sSlice(state *encoderState, v reflect.Value) bool {
208 slice, ok := v.Interface().([]%[1]s)
209 if !ok {
210 // It is kind %[1]s but not type %[1]s. TODO: We can handle this unsafely.
211 return false
212 }
213 for _, x := range slice {
214 if x != %[3]s || state.sendZero {
215 %[4]s
216 }
217 }
218 return true
219 }
220 `
221
View as plain text