-
Notifications
You must be signed in to change notification settings - Fork 1
/
rpcgen.py
134 lines (121 loc) · 4.43 KB
/
rpcgen.py
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from dataclasses import dataclass
from os import makedirs
from typing import Literal, Tuple
@dataclass
class t:
string = 'string'
int = 'int'
uint = 'uint'
void = 'void'
fallible_void = 'falliblevoid'
event = 'event'
iohandle = 'handle'
offset = 'ulong'
size = 'ulong'
buffer = 'buffer'
def fallible(t: str) -> Tuple[Literal['fallible'], str]:
return ['fallible', t]
rpc_services = {
'logger': {
'LogLine': [[t.string], t.event],
},
'svcdiscovery': {
'Find': [[t.string], t.int],
'Declare': [[t.int, t.string], t.void],
},
'ioprovider': {
'Read': [[t.iohandle, t.offset, t.size], t.fallible(t.buffer)],
'Write': [[t.iohandle, t.offset, t.size], t.fallible(t.buffer)],
'Close': [[t.iohandle], t.event],
},
'filesystem': {
'OpenFile': [[t.string, t.uint], t.fallible(t.iohandle)],
'OpenDir': [[t.string], t.fallible(t.iohandle)],
'MakeDir': [[t.string], t.fallible_void],
'RemoveDir': [[t.string], t.fallible_void],
'Unlink': [[t.string], t.fallible_void],
'GetStatbuf': [[t.string], t.fallible(t.buffer)],
},
}
funcid = 1
for k, v in rpc_services.items():
code = [
'// Autogenerated by rpcgen.py. Do not edit!',
'module xtrix_rpc.{};'.format(k),
'import libxtrix.events;',
'import libxk.bytebuffer;',
'import libxtrix.rpcutil;',
'struct {}_client {{'.format(k),
'\tulong pid;'
]
nam2id = {}
for fnid, (args, ret) in v.items():
for arg in args:
if arg == t.event:
print('ERROR: argument to {}/{} cannot be an event, only return types can be!'.format(k, fnid))
nam2id[fnid] = funcid
funcid += 1
for fnid, (args, ret) in v.items():
if ret == t.event:
dret = 'void'
elif ret == t.void:
dret = 'Signal'
else:
dret = 'Future!({})'.format(ret)
code.append('\t{} {}(int _stub = 0)({}) {{'.format(dret, fnid, ', '.join([
'{} a_{}'.format(aty, aid)
for aid, aty
in enumerate(args)
])))
code.append('\t\tByteBuffer buf;')
code.append('\t\trpcutil_prepare(buf, {});'.format(nam2id[fnid]))
for aid, aty in enumerate(args):
code.append('\t\trpcutil_encode_{}(buf, a_{});'.format(aty, aid))
if ret == t.event:
code.append('\t\trpcutil_submit_ev(this.pid, buf);')
elif ret == t.void:
code.append('\t\treturn rpcutil_submit_sig(this.pid, buf);')
else:
code.append('\t\tFuture!(ubyte[]) buffer_future = rpcutil_submit(this.pid, buf);')
code.append('\t\treturn buffer_future.then((ref ubyte[] newbuf) {{ ulong o = 0; return rpcutil_decode_{}(newbuf, o); }});'.format(ret))
code.append('\t}')
code.append('}')
code.append('struct {}_server {{'.format(k))
code.append('\tthis() @disable;')
for fnid, (args, ret) in v.items():
if ret == t.event:
dret = 'void'
elif ret == t.void:
dret = 'Signal'
else:
dret = 'Future!({})'.format(ret)
dlty = '{} delegate({})'.format(dret, ', '.join(args))
code.append('\tstatic void on{}(int _stub = 0)({} handler) {{'.format(fnid, dlty))
code.append('\t\trpcutil_handle({}, (pid, rid, buf) {{'.format(nam2id[fnid]))
code.append('\t\t\tulong off = 0;')
for aid, aty in enumerate(args):
code.append('\t\t\t{} a_{} = rpcutil_decode_{}(buf, off);'.format(aty, aid, aty, aid))
# code.append('\t\t\t')
if ret == t.event:
code.append('\t\t\thandler({});'.format(', '.join([
'a_{}'.format(i)
for i in range(len(args))
])))
elif ret == t.void:
code.append('\t\t\trpcutil_sigrespond(pid, rid, handler({}));'.format(', '.join([
'a_{}'.format(i)
for i in range(len(args))
])))
else:
code.append('\t\t\trpcutil_respond_{}(pid, rid, rpcutil_as_future(handler({})));'.format(
ret, ', '.join([
'a_{}'.format(i)
for i in range(len(args))
]
)))
code.append('\t\t});')
code.append('\t}')
code.append('}')
makedirs('build/rsc/xtrix_rpc', exist_ok=True)
with open("build/rsc/xtrix_rpc/{}.d".format(k), 'w') as file:
file.write('\n'.join(code))