protocol.mx raw
1 package main
2
3 // Protocol: pipe-delimited, newline-terminated messages.
4 // REQ|<seq>|<op>|<arg0>|<arg1>|...
5 // OK|<seq>|<result>
6 // ERR|<seq>|<errmsg>
7
8 func tsItoa(n int32) (s string) {
9 if n == 0 {
10 return "0"
11 }
12 buf := []byte{:0:20}
13 neg := n < 0
14 if neg {
15 n = -n
16 }
17 for n > 0 {
18 push(buf, byte('0'+n%10))
19 n /= 10
20 }
21 if neg {
22 push(buf, '-')
23 }
24 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
25 buf[i], buf[j] = buf[j], buf[i]
26 }
27 return string(buf)
28 }
29
30 func tsAtoi(s string) (n int32) {
31 if len(s) == 0 {
32 return 0
33 }
34 neg := false
35 pos := int32(0)
36 if s[0] == '-' {
37 neg = true
38 pos = 1
39 } else if s[0] == '+' {
40 pos = 1
41 }
42 for pos < int32(len(s)) {
43 c := s[pos]
44 if c < '0' || c > '9' {
45 break
46 }
47 n = n*10 + int32(c-'0')
48 pos++
49 }
50 if neg {
51 n = -n
52 }
53 return n
54 }
55
56 func parseMsg(msg string) (seq int32, op string, args []string) {
57 parts := splitMsg(msg)
58 if len(parts) < 3 {
59 return 0, "", nil
60 }
61 seq = tsAtoi(parts[1])
62 op = parts[2]
63 if len(parts) > 3 {
64 args = parts[3:]
65 }
66 return seq, op, args
67 }
68
69 func formatOK(seq int32, result string) (s string) {
70 return "OK|" | tsItoa(seq) | "|" | result | "\n"
71 }
72
73 func formatERR(seq int32, errmsg string) (s string) {
74 return "ERR|" | tsItoa(seq) | "|" | errmsg | "\n"
75 }
76
77 func parseOK(line string) (result string) {
78 parts := splitMsg(line)
79 if len(parts) >= 3 {
80 return parts[2]
81 }
82 return ""
83 }
84
85 func parseOKMulti(line string) (results []string) {
86 return splitMsg(line)
87 }
88
89 func parseERR(line string) (errmsg string) {
90 parts := splitMsg(line)
91 if len(parts) >= 3 {
92 return parts[2]
93 }
94 return ""
95 }
96
97 func splitMsg(d string) (parts []string) {
98 if len(d) == 0 {
99 return nil
100 }
101 n := int32(1)
102 for i := int32(0); i < int32(len(d)); i++ {
103 if d[i] == '|' {
104 n++
105 }
106 }
107 parts = []string{:0:n}
108 start := int32(0)
109 for i := int32(0); i <= int32(len(d)); i++ {
110 isDelim := false
111 if i < int32(len(d)) {
112 isDelim = d[i] == '|' || d[i] == '\n'
113 }
114 if i == int32(len(d)) || isDelim {
115 push(parts, string(d[start:i]))
116 start = i + 1
117 if i < int32(len(d)) && d[i] == '\n' {
118 break
119 }
120 }
121 }
122 return parts
123 }
124