parsemxh.mx raw
1 package main
2
3 import (
4 "bytes"
5 "unsafe"
6 )
7
8 type mxhData struct {
9 hash string
10 types []mxhType
11 }
12
13 type mxhType struct {
14 name string
15 fields []mxhField
16 hasEncodeTo bool
17 hasDecodeFrom bool
18 }
19
20 type mxhField struct {
21 name string
22 typ string
23 }
24
25 var handles []*mxhData
26
27 //export moxie_mxh_parse
28 func moxie_mxh_parse(dataPtr unsafe.Pointer, dataLen int32) int32 {
29 data := unsafe.Slice((*byte)(dataPtr), dataLen)
30 lines := bytes.Split(data, "\n")
31 if len(lines) == 0 {
32 return -1
33 }
34
35 header := bytes.TrimSpace(lines[0])
36 if !bytes.HasPrefix(header, "// mxh v1 ") {
37 return -1
38 }
39 hash := bytes.TrimSpace(header[10:])
40 if len(hash) == 0 {
41 return -1
42 }
43
44 m := &mxhData{hash: hash}
45 curIdx := int32(-1)
46
47 for i := 1; i < len(lines); i++ {
48 line := bytes.TrimSpace(lines[i])
49 if len(line) == 0 || bytes.HasPrefix(line, "//") {
50 continue
51 }
52
53 if bytes.HasPrefix(line, "type ") && bytes.HasSuffix(line, " struct {") {
54 name := bytes.TrimSpace(line[5 : len(line)-9])
55 m.types = append(m.types, mxhType{name: name})
56 curIdx = int32(len(m.types) - 1)
57 continue
58 }
59
60 if line == "}" {
61 curIdx = -1
62 continue
63 }
64
65 if bytes.HasPrefix(line, "func (") && bytes.Contains(line, ") EncodeTo(") {
66 if curIdx == -1 {
67 start := bytes.IndexByte(line, '(')
68 end := bytes.IndexByte(line, ')')
69 if start >= 0 && end > start+1 {
70 name := bytes.TrimSpace(line[start+1 : end])
71 for j := range m.types {
72 if m.types[j].name == name {
73 m.types[j].hasEncodeTo = true
74 break
75 }
76 }
77 }
78 } else {
79 m.types[curIdx].hasEncodeTo = true
80 curIdx = -1
81 }
82 continue
83 }
84
85 if bytes.HasPrefix(line, "func (*") && bytes.Contains(line, ") DecodeFrom(") {
86 start := bytes.Index(line, "(*")
87 end := bytes.IndexByte(line, ')')
88 if start >= 0 && end > start+2 {
89 name := bytes.TrimSpace(line[start+2 : end])
90 for j := range m.types {
91 if m.types[j].name == name {
92 m.types[j].hasDecodeFrom = true
93 break
94 }
95 }
96 }
97 continue
98 }
99
100 if curIdx >= 0 {
101 parts := bytes.Fields(line)
102 if len(parts) == 2 {
103 m.types[curIdx].fields = append(m.types[curIdx].fields, mxhField{
104 name: parts[0],
105 typ: parts[1],
106 })
107 }
108 }
109 }
110
111 handles = append(handles, m)
112 return int32(len(handles) - 1)
113 }
114
115 func copyToOut(s string, outPtr unsafe.Pointer, outCap int32) int32 {
116 n := int32(len(s))
117 if n > outCap {
118 n = outCap
119 }
120 out := unsafe.Slice((*byte)(outPtr), outCap)
121 copy(out[:n], s)
122 return n
123 }
124
125 func validHandle(handle int32) *mxhData {
126 if handle < 0 || handle >= int32(len(handles)) {
127 return nil
128 }
129 return handles[handle]
130 }
131
132 //export moxie_mxh_hash
133 func moxie_mxh_hash(handle int32, outPtr unsafe.Pointer, outCap int32) int32 {
134 m := validHandle(handle)
135 if m == nil {
136 return -1
137 }
138 return copyToOut(m.hash, outPtr, outCap)
139 }
140
141 //export moxie_mxh_type_count
142 func moxie_mxh_type_count(handle int32) int32 {
143 m := validHandle(handle)
144 if m == nil {
145 return -1
146 }
147 return int32(len(m.types))
148 }
149
150 //export moxie_mxh_type_name
151 func moxie_mxh_type_name(handle int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 {
152 m := validHandle(handle)
153 if m == nil || idx < 0 || idx >= int32(len(m.types)) {
154 return -1
155 }
156 return copyToOut(m.types[idx].name, outPtr, outCap)
157 }
158
159 //export moxie_mxh_type_field_count
160 func moxie_mxh_type_field_count(handle int32, idx int32) int32 {
161 m := validHandle(handle)
162 if m == nil || idx < 0 || idx >= int32(len(m.types)) {
163 return -1
164 }
165 return int32(len(m.types[idx].fields))
166 }
167
168 //export moxie_mxh_type_field_name
169 func moxie_mxh_type_field_name(handle int32, tidx int32, fidx int32, outPtr unsafe.Pointer, outCap int32) int32 {
170 m := validHandle(handle)
171 if m == nil || tidx < 0 || tidx >= int32(len(m.types)) {
172 return -1
173 }
174 t := m.types[tidx]
175 if fidx < 0 || fidx >= int32(len(t.fields)) {
176 return -1
177 }
178 return copyToOut(t.fields[fidx].name, outPtr, outCap)
179 }
180
181 //export moxie_mxh_type_field_type
182 func moxie_mxh_type_field_type(handle int32, tidx int32, fidx int32, outPtr unsafe.Pointer, outCap int32) int32 {
183 m := validHandle(handle)
184 if m == nil || tidx < 0 || tidx >= int32(len(m.types)) {
185 return -1
186 }
187 t := m.types[tidx]
188 if fidx < 0 || fidx >= int32(len(t.fields)) {
189 return -1
190 }
191 return copyToOut(t.fields[fidx].typ, outPtr, outCap)
192 }
193
194 //export moxie_mxh_type_has_encode
195 func moxie_mxh_type_has_encode(handle int32, idx int32) int32 {
196 m := validHandle(handle)
197 if m == nil || idx < 0 || idx >= int32(len(m.types)) {
198 return -1
199 }
200 if m.types[idx].hasEncodeTo {
201 return 1
202 }
203 return 0
204 }
205
206 //export moxie_mxh_type_has_decode
207 func moxie_mxh_type_has_decode(handle int32, idx int32) int32 {
208 m := validHandle(handle)
209 if m == nil || idx < 0 || idx >= int32(len(m.types)) {
210 return -1
211 }
212 if m.types[idx].hasDecodeFrom {
213 return 1
214 }
215 return 0
216 }
217
218 //export moxie_mxh_free
219 func moxie_mxh_free(handle int32) {
220 if handle >= 0 && handle < int32(len(handles)) {
221 handles[handle] = nil
222 }
223 }
224
225 func main() {}
226