/
marshal.go
93 lines (80 loc) · 2 KB
/
marshal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package generator
import (
"fmt"
"github.com/wdvxdr1123/yaproto/internal/types"
"github.com/wdvxdr1123/yaproto/internal/utils"
)
func (g *Generator) marshal(m *types.Message) {
if g.Options.GenMarshal == 1 {
g.Pf(`func (x *%s) Marshal() ([]byte, error) {
if x == nil {
return nil, errors.New("nil message")
}
return proto.Marshal(x)
}`, m.GoType())
g.Pln()
return
}
g.Pf(`func (x *%s) Marshal() ([]byte, error) {
size := x.Size()
buf := make([]byte, size)
n := x.MarshalTo(buf[:size])
return buf[:n], nil
}
func (x *%s) MarshalTo(buf []byte) int {
var i int
_ = i`, utils.CamelCase(m.Name), utils.CamelCase(m.Name))
g.Pln()
for _, field := range m.Fields {
g.marshalField(field)
}
g.Pln(" return i")
g.Pln("}")
g.Pln()
}
func (g *Generator) marshalField(f *types.MessageField) {
wt := types.WireType(f.Type)
key := func(kv uint32) {
for kv >= 0x80 {
x := byte(kv) | 0x80
g.Pf("buf[i] = 0x%x\n", x)
g.Pf("i++\n")
kv >>= 7
}
g.Pf("buf[i] = 0x%x\n", byte(kv))
g.Pf("i++\n")
}
body := func(name string, t types.Type) {
// value
switch wt {
default:
panic(fmt.Errorf("unhandled wire type: %d", wt))
case types.WireVarint:
if f.Type.Name() == "bool" {
g.Pf("proto.PutBool(buf, &i, %s)\n", name)
} else {
g.Pf("proto.PutVarint(buf, &i, %s)\n", types.Convert(name, t, types.ScalarValueTypes[types.TUINT64]))
}
case types.WireBytes:
if f.Type.ScopeClass() == types.CMessage {
g.Pf("l := %s.Size()\n", name)
g.Pf("proto.PutVarint(buf, &i, uint64(l))\n")
g.Pf("i += %s.MarshalTo(buf[i:])\n", name)
} else {
g.Pf("proto.PutVarint(buf, &i, uint64(len(%s)))\n", name)
g.Pf("i += copy(buf[i:], %s)\n", name)
}
}
}
if f.IsRepeated() {
g.Pf(" for _, e := range %s {\n", f.Selector(true))
key(types.KeyValue(f.Sequence, types.WireBytes))
body("e", f.Type)
g.Pf(" }\n")
} else {
g.Pf("if %s != %s {\n", f.Selector(false), f.Null())
key(types.KeyValue(f.Sequence, wt))
body(f.Selector(true), f.Type)
g.Pln("}")
}
}