github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/encoding/gob/encgen.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 //go:build ignore 6 // +build ignore 7 8 // encgen writes the helper functions for encoding. Intended to be 9 // used with go generate; see the invocation in encode.go. 10 11 // TODO: We could do more by being unsafe. Add a -unsafe flag? 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 // uint8 Handled separately. 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 `