package main import ( "bytes" "unsafe" ) type mxhData struct { hash string types []mxhType } type mxhType struct { name string fields []mxhField hasEncodeTo bool hasDecodeFrom bool } type mxhField struct { name string typ string } var handles []*mxhData //export moxie_mxh_parse func moxie_mxh_parse(dataPtr unsafe.Pointer, dataLen int32) int32 { data := unsafe.Slice((*byte)(dataPtr), dataLen) lines := bytes.Split(data, "\n") if len(lines) == 0 { return -1 } header := bytes.TrimSpace(lines[0]) if !bytes.HasPrefix(header, "// mxh v1 ") { return -1 } hash := bytes.TrimSpace(header[10:]) if len(hash) == 0 { return -1 } m := &mxhData{hash: hash} curIdx := int32(-1) for i := 1; i < len(lines); i++ { line := bytes.TrimSpace(lines[i]) if len(line) == 0 || bytes.HasPrefix(line, "//") { continue } if bytes.HasPrefix(line, "type ") && bytes.HasSuffix(line, " struct {") { name := bytes.TrimSpace(line[5 : len(line)-9]) m.types = append(m.types, mxhType{name: name}) curIdx = int32(len(m.types) - 1) continue } if line == "}" { curIdx = -1 continue } if bytes.HasPrefix(line, "func (") && bytes.Contains(line, ") EncodeTo(") { if curIdx == -1 { start := bytes.IndexByte(line, '(') end := bytes.IndexByte(line, ')') if start >= 0 && end > start+1 { name := bytes.TrimSpace(line[start+1 : end]) for j := range m.types { if m.types[j].name == name { m.types[j].hasEncodeTo = true break } } } } else { m.types[curIdx].hasEncodeTo = true curIdx = -1 } continue } if bytes.HasPrefix(line, "func (*") && bytes.Contains(line, ") DecodeFrom(") { start := bytes.Index(line, "(*") end := bytes.IndexByte(line, ')') if start >= 0 && end > start+2 { name := bytes.TrimSpace(line[start+2 : end]) for j := range m.types { if m.types[j].name == name { m.types[j].hasDecodeFrom = true break } } } continue } if curIdx >= 0 { parts := bytes.Fields(line) if len(parts) == 2 { m.types[curIdx].fields = append(m.types[curIdx].fields, mxhField{ name: parts[0], typ: parts[1], }) } } } handles = append(handles, m) return int32(len(handles) - 1) } func copyToOut(s string, outPtr unsafe.Pointer, outCap int32) int32 { n := int32(len(s)) if n > outCap { n = outCap } out := unsafe.Slice((*byte)(outPtr), outCap) copy(out[:n], s) return n } func validHandle(handle int32) *mxhData { if handle < 0 || handle >= int32(len(handles)) { return nil } return handles[handle] } //export moxie_mxh_hash func moxie_mxh_hash(handle int32, outPtr unsafe.Pointer, outCap int32) int32 { m := validHandle(handle) if m == nil { return -1 } return copyToOut(m.hash, outPtr, outCap) } //export moxie_mxh_type_count func moxie_mxh_type_count(handle int32) int32 { m := validHandle(handle) if m == nil { return -1 } return int32(len(m.types)) } //export moxie_mxh_type_name func moxie_mxh_type_name(handle int32, idx int32, outPtr unsafe.Pointer, outCap int32) int32 { m := validHandle(handle) if m == nil || idx < 0 || idx >= int32(len(m.types)) { return -1 } return copyToOut(m.types[idx].name, outPtr, outCap) } //export moxie_mxh_type_field_count func moxie_mxh_type_field_count(handle int32, idx int32) int32 { m := validHandle(handle) if m == nil || idx < 0 || idx >= int32(len(m.types)) { return -1 } return int32(len(m.types[idx].fields)) } //export moxie_mxh_type_field_name func moxie_mxh_type_field_name(handle int32, tidx int32, fidx int32, outPtr unsafe.Pointer, outCap int32) int32 { m := validHandle(handle) if m == nil || tidx < 0 || tidx >= int32(len(m.types)) { return -1 } t := m.types[tidx] if fidx < 0 || fidx >= int32(len(t.fields)) { return -1 } return copyToOut(t.fields[fidx].name, outPtr, outCap) } //export moxie_mxh_type_field_type func moxie_mxh_type_field_type(handle int32, tidx int32, fidx int32, outPtr unsafe.Pointer, outCap int32) int32 { m := validHandle(handle) if m == nil || tidx < 0 || tidx >= int32(len(m.types)) { return -1 } t := m.types[tidx] if fidx < 0 || fidx >= int32(len(t.fields)) { return -1 } return copyToOut(t.fields[fidx].typ, outPtr, outCap) } //export moxie_mxh_type_has_encode func moxie_mxh_type_has_encode(handle int32, idx int32) int32 { m := validHandle(handle) if m == nil || idx < 0 || idx >= int32(len(m.types)) { return -1 } if m.types[idx].hasEncodeTo { return 1 } return 0 } //export moxie_mxh_type_has_decode func moxie_mxh_type_has_decode(handle int32, idx int32) int32 { m := validHandle(handle) if m == nil || idx < 0 || idx >= int32(len(m.types)) { return -1 } if m.types[idx].hasDecodeFrom { return 1 } return 0 } //export moxie_mxh_free func moxie_mxh_free(handle int32) { if handle >= 0 && handle < int32(len(handles)) { handles[handle] = nil } } func main() {}