api.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. import zmq
  2. from collections import namedtuple
  3. from . import serial, exc, expr
  4. Property = namedtuple("Property", [
  5. "name",
  6. "type",
  7. "subtype",
  8. "defaults",
  9. "ui_name",
  10. "desc",
  11. "is_null_allowed",
  12. "is_expr_allowed",
  13. "array_len",
  14. "min_val",
  15. "max_val",
  16. "enum_items"
  17. ])
  18. class Command:
  19. HELLO = 0
  20. ADD_NODE = 1
  21. REMOVE_NODE = 9
  22. RENAME_NODE = 23
  23. SCAN_DANGLING = 24
  24. LOOKUP_NODE_ID = 12
  25. ADD_PROPERTY = 11
  26. LINK_NODE = 2
  27. UNLINK_NODE = 8
  28. GET_INFO = 19
  29. GET_CHILDREN = 4
  30. GET_PARENTS = 5
  31. GET_PROPERTIES = 3
  32. GET_PROPERTY_VALUE = 6
  33. SET_PROPERTY_VALUE = 7
  34. GET_SIGNALS = 14
  35. REGISTER_SLOT = 15
  36. UNREGISTER_SLOT = 16
  37. LOOKUP_SLOT_ID = 17
  38. GET_SLOTS = 18
  39. GET_METHODS = 20
  40. GET_METHOD = 21
  41. CALL_METHOD = 22
  42. class SceneNodeType:
  43. NULL = 0
  44. ROOT = 1
  45. WINDOW = 2
  46. WINDOW_INPUT = 6
  47. KEYBOARD = 7
  48. MOUSE = 8
  49. RENDER_LAYER = 3
  50. RENDER_OBJECT = 4
  51. RENDER_MESH = 5
  52. RENDER_TEXT = 9
  53. RENDER_TEXTURE = 13
  54. FONTS = 10
  55. FONT = 11
  56. LINE_POSITION = 12
  57. class PropertyType:
  58. NULL = 0
  59. BOOL = 1
  60. UINT32 = 2
  61. FLOAT32 = 3
  62. STR = 4
  63. ENUM = 5
  64. BUFFER = 6
  65. SCENE_NODE_ID = 7
  66. SEXPR = 8
  67. @staticmethod
  68. def to_str(prop_type):
  69. match prop_type:
  70. case PropertyType.NULL:
  71. return "null"
  72. case PropertyType.BOOL:
  73. return "bool"
  74. case PropertyType.UINT32:
  75. return "uint32"
  76. case PropertyType.FLOAT32:
  77. return "float32"
  78. case PropertyType.STR:
  79. return "str"
  80. case PropertyType.ENUM:
  81. return "enum"
  82. case PropertyType.BUFFER:
  83. return "buffer"
  84. case PropertyType.SCENE_NODE_ID:
  85. return "scene_node_id"
  86. case PropertyType.SEXPR:
  87. return "sexpr"
  88. class PropertySubType:
  89. NULL = 0
  90. COLOR = 1
  91. PIXEL = 2
  92. RESOURCE_ID = 3
  93. @staticmethod
  94. def to_str(prop_type):
  95. match prop_type:
  96. case PropertySubType.NULL:
  97. return "null"
  98. case PropertySubType.Color:
  99. return "color"
  100. case PropertySubType.PIXEL:
  101. return "pixel"
  102. case PropertySubType.RESOURCE_ID:
  103. return "resource_id"
  104. class PropertyStatus:
  105. OK = 0
  106. UNSET = 1
  107. NULL = 2
  108. EXPR = 3
  109. class ErrorCode:
  110. INVALID_SCENE_PATH = 1
  111. NODE_NOT_FOUND = 2
  112. CHILD_NODE_NOT_FOUND = 3
  113. PARENT_NODE_NOT_FOUND = 4
  114. PROPERTY_ALREADY_EXISTS = 5
  115. PROPERTY_NOT_FOUND = 6
  116. PROPERTY_WRONG_TYPE = 7
  117. PROPERTY_WRONG_SUB_TYPE = 8
  118. PROPERTY_WRONG_LEN = 9
  119. PROPERTY_WRONG_INDEX = 10
  120. PROPERTY_OUT_OF_RANGE = 11
  121. PROPERTY_NULL_NOT_ALLOWED = 12
  122. PROPERTY_SEXPR_NOT_ALLOWED = 13
  123. PROPERTY_IS_BOUNDED = 14
  124. PROPERTY_WRONG_ENUM_ITEM = 15
  125. SIGNAL_ALREADY_EXISTS = 16
  126. SIGNAL_NOT_FOUND = 17
  127. SLOT_NOT_FOUND = 18
  128. METHOD_ALREADY_EXISTS = 19
  129. METHOD_NOT_FOUND = 20
  130. NODES_ARE_LINKED = 21
  131. NODES_NOT_LINKED = 22
  132. NODE_HAS_PARENTS = 23
  133. NODE_HAS_CHILDREN = 24
  134. NODE_PARENT_NAME_CONFLICT = 25
  135. NODE_CHILD_NAME_CONFLICT = 26
  136. NODE_SIBLING_NAME_CONFLICT = 27
  137. FILE_NOT_FOUND = 28
  138. RESOURCE_NOT_FOUND = 29
  139. PY_EVAL_ERR = 30
  140. SEXPR_EMPTY = 31
  141. SEXPR_GLOBAL_NOT_FOUND = 32
  142. @staticmethod
  143. def to_str(errc):
  144. match errc:
  145. case ErrorCode.INVALID_SCENE_PATH:
  146. return "invalid_scene_path"
  147. case ErrorCode.NODE_NOT_FOUND:
  148. return "node_not_found"
  149. case ErrorCode.CHILD_NODE_NOT_FOUND:
  150. return "child_node_not_found"
  151. case ErrorCode.PARENT_NODE_NOT_FOUND:
  152. return "parent_node_not_found"
  153. case ErrorCode.PROPERTY_ALREADY_EXISTS:
  154. return "property_already_exists"
  155. case ErrorCode.PROPERTY_NOT_FOUND:
  156. return "property_not_found"
  157. case ErrorCode.PROPERTY_WRONG_TYPE:
  158. return "property_wrong_type"
  159. case ErrorCode.PROPERTY_WRONG_LEN:
  160. return "property_wrong_len"
  161. case ErrorCode.PROPERTY_WRONG_INDEX:
  162. return "property_wrong_index"
  163. case ErrorCode.PROPERTY_OUT_OF_RANGE:
  164. return "property_out_of_range"
  165. case ErrorCode.PROPERTY_NULL_NOT_ALLOWED:
  166. return "property_null_not_allowed"
  167. case ErrorCode.PROPERTY_SEXPR_NOT_ALLOWED:
  168. return "property_sexpr_not_allowed"
  169. case ErrorCode.PROPERTY_IS_BOUNDED:
  170. return "property_is_bounded"
  171. case ErrorCode.PROPERTY_WRONG_ENUM_ITEM:
  172. return "property_wrong_enum_item"
  173. case ErrorCode.SIGNAL_ALREADY_EXISTS:
  174. return "signal_already_exists"
  175. case ErrorCode.SIGNAL_NOT_FOUND:
  176. return "signal_not_found"
  177. case ErrorCode.SLOT_NOT_FOUND:
  178. return "slot_not_found"
  179. case ErrorCode.METHOD_ALREADY_EXISTS:
  180. return "method_already_exists"
  181. case ErrorCode.METHOD_NOT_FOUND:
  182. return "method_not_found"
  183. case ErrorCode.NODES_ARE_LINKED:
  184. return "nodes_are_linked"
  185. case ErrorCode.NODES_NOT_LINKED:
  186. return "nodes_not_linked"
  187. case ErrorCode.NODE_HAS_PARENTS:
  188. return "node_has_parents"
  189. case ErrorCode.NODE_HAS_CHILDREN:
  190. return "node_has_children"
  191. case ErrorCode.NODE_PARENT_NAME_CONFLICT:
  192. return "node_parent_name_conflict"
  193. case ErrorCode.NODE_CHILD_NAME_CONFLICT:
  194. return "node_child_name_conflict"
  195. case ErrorCode.NODE_SIBLING_NAME_CONFLICT:
  196. return "node_sibling_name_conflict"
  197. case ErrorCode.FILE_NOT_FOUND:
  198. return "file_not_found"
  199. case ErrorCode.RESOURCE_NOT_FOUND:
  200. return "resource_not_found"
  201. case ErrorCode.PY_EVAL_ERR:
  202. return "py_eval_err"
  203. case ErrorCode.SEXPR_EMPTY:
  204. return "sexpr_empty"
  205. case ErrorCode.SEXPR_GLOBAL_NOT_FOUND:
  206. return "sexpr_global_not_found"
  207. def vertex(x, y, r, g, b, a, u, v):
  208. buf = bytearray()
  209. serial.write_f32(buf, x)
  210. serial.write_f32(buf, y)
  211. serial.write_f32(buf, r)
  212. serial.write_f32(buf, g)
  213. serial.write_f32(buf, b)
  214. serial.write_f32(buf, a)
  215. serial.write_f32(buf, u)
  216. serial.write_f32(buf, v)
  217. return buf
  218. def face(idx1, idx2, idx3):
  219. buf = bytearray()
  220. serial.write_u32(buf, idx1)
  221. serial.write_u32(buf, idx2)
  222. serial.write_u32(buf, idx3)
  223. return buf
  224. class Api:
  225. def __init__(self, addr="[::1]", port=9484):
  226. context = zmq.Context()
  227. self.socket = context.socket(zmq.REQ)
  228. self.socket.setsockopt(zmq.IPV6, True)
  229. self.socket.connect(f"tcp://{addr}:{port}")
  230. def _make_request(self, cmd, payload):
  231. req_cmd = bytearray()
  232. serial.write_u8(req_cmd, cmd)
  233. self.socket.send_multipart([req_cmd, payload])
  234. errc, reply = self.socket.recv_multipart()
  235. errc = int.from_bytes(errc, "little")
  236. cursor = serial.Cursor(reply)
  237. match errc:
  238. case 1:
  239. raise exc.InvalidScenePath
  240. case 2:
  241. raise exc.NodeNotFound
  242. case 3:
  243. raise exc.ChildNodeNotFound
  244. case 4:
  245. raise exc.ParentNodeNotFound
  246. case 5:
  247. raise exc.PropertyAlreadyExists
  248. case 6:
  249. raise exc.PropertyNotFound
  250. case 7:
  251. raise exc.PropertyWrongType
  252. case 8:
  253. raise exc.PropertyWrongSubType
  254. case 9:
  255. raise exc.PropertyWrongLen
  256. case 10:
  257. raise exc.PropertyWrongIndex
  258. case 11:
  259. raise exc.PropertyOutOfRange
  260. case 12:
  261. raise exc.PropertyNullNotAllowed
  262. case 12:
  263. raise exc.PropertySExprNotAllowed
  264. case 14:
  265. raise exc.PropertyIsBounded
  266. case 15:
  267. raise exc.PropertyWrongEnumItem
  268. case 16:
  269. raise exc.SignalAlreadyExists
  270. case 17:
  271. raise exc.SignalNotFound
  272. case 18:
  273. raise exc.SlotNotFound
  274. case 19:
  275. raise exc.MethodAlreadyExists
  276. case 20:
  277. raise exc.MethodNotFound
  278. case 21:
  279. raise exc.NodesAreLinked
  280. case 22:
  281. raise exc.NodesNotLinked
  282. case 23:
  283. raise exc.NodeHasParents
  284. case 24:
  285. raise exc.NodeHasChildren
  286. case 25:
  287. raise exc.NodeParentNameConflict
  288. case 26:
  289. raise exc.NodeChildNameConflict
  290. case 27:
  291. raise exc.NodeSiblingNameConflict
  292. case 28:
  293. raise exc.FileNotFound
  294. case 29:
  295. raise exc.ResourceNotFound
  296. case 30:
  297. raise exc.PyEvalErr
  298. case 31:
  299. raise exc.SExprEmpty
  300. case 32:
  301. raise exc.SExprGlobalNotFound
  302. return cursor
  303. def hello(self):
  304. response = self._make_request(Command.HELLO, bytearray())
  305. return serial.decode_str(response)
  306. def get_info(self, node_id):
  307. req = bytearray()
  308. serial.write_u32(req, node_id)
  309. cur = self._make_request(Command.GET_INFO, req)
  310. name = serial.decode_str(cur)
  311. type = serial.read_u8(cur)
  312. return (name, type)
  313. def get_children(self, node_id):
  314. req = bytearray()
  315. serial.write_u32(req, node_id)
  316. cur = self._make_request(Command.GET_CHILDREN, req)
  317. children_len = serial.decode_varint(cur)
  318. children = []
  319. for _ in range(children_len):
  320. child_name = serial.decode_str(cur)
  321. child_id = serial.read_u32(cur)
  322. child_type = serial.read_u8(cur)
  323. children.append((child_name, child_id, child_type))
  324. return children
  325. def get_parents(self, node_id):
  326. req = bytearray()
  327. serial.write_u32(req, node_id)
  328. cur = self._make_request(Command.GET_PARENTS, req)
  329. parents_len = serial.decode_varint(cur)
  330. parents = []
  331. for _ in range(parents_len):
  332. parent_name = serial.decode_str(cur)
  333. parent_id = serial.read_u32(cur)
  334. parent_type = serial.read_u8(cur)
  335. parents.append((parent_name, parent_id, parent_type))
  336. return parents
  337. def get_properties(self, node_id):
  338. req = bytearray()
  339. serial.write_u32(req, node_id)
  340. cur = self._make_request(Command.GET_PROPERTIES, req)
  341. props_len = serial.decode_varint(cur)
  342. props = []
  343. prop_read_fn = lambda cur: Api.read_prop_val(cur, prop_type)
  344. enum_read_fn = lambda cur: serial.decode_arr(cur, serial.decode_str)
  345. for _ in range(props_len):
  346. prop_name = serial.decode_str(cur)
  347. # We need prop_type below
  348. prop_type = serial.read_u8(cur)
  349. prop = Property(
  350. prop_name,
  351. prop_type,
  352. # subtype
  353. serial.read_u8(cur),
  354. # defaults
  355. serial.decode_arr(cur, prop_read_fn),
  356. # ui_name
  357. serial.decode_str(cur),
  358. # desc
  359. serial.decode_str(cur),
  360. # is_null_allowed
  361. bool(serial.read_u8(cur)),
  362. # is_expr_allowed
  363. bool(serial.read_u8(cur)),
  364. # array_len
  365. serial.read_u32(cur),
  366. # min_val
  367. serial.decode_opt(cur, prop_read_fn),
  368. # max_val
  369. serial.decode_opt(cur, prop_read_fn),
  370. # enum_items
  371. serial.decode_opt(cur, enum_read_fn)
  372. )
  373. props.append(prop)
  374. return props
  375. @staticmethod
  376. def read_prop_val(cur, prop_type):
  377. match prop_type:
  378. case PropertyType.NULL:
  379. return None
  380. case PropertyType.BOOL:
  381. return bool(serial.read_u8(cur))
  382. case PropertyType.UINT32:
  383. return serial.read_u32(cur)
  384. case PropertyType.FLOAT32:
  385. return serial.read_f32(cur)
  386. case PropertyType.STR:
  387. return serial.decode_str(cur)
  388. case PropertyType.ENUM:
  389. return serial.decode_str(cur)
  390. case PropertyType.BUFFER:
  391. pass
  392. case PropertyType.SCENE_NODE_ID:
  393. return serial.read_u32(cur)
  394. case _:
  395. raise Exception("unknown property type returned")
  396. def get_property_value(self, node_id, prop_name):
  397. req = bytearray()
  398. serial.write_u32(req, node_id)
  399. serial.encode_str(req, prop_name)
  400. cur = self._make_request(Command.GET_PROPERTY_VALUE, req)
  401. prop_type = serial.read_u8(cur)
  402. def prop_read_fn(cur):
  403. prop_status = serial.read_u8(cur)
  404. match prop_status:
  405. case PropertyStatus.NULL:
  406. return None
  407. case PropertyStatus.EXPR:
  408. return None
  409. case PropertyStatus.UNSET | PropertyStatus.OK:
  410. return Api.read_prop_val(cur, prop_type)
  411. vals = serial.decode_arr(cur, prop_read_fn)
  412. return vals
  413. def add_node(self, node_name, node_type):
  414. req = bytearray()
  415. serial.encode_str(req, node_name)
  416. serial.write_u8(req, int(node_type))
  417. cur = self._make_request(Command.ADD_NODE, req)
  418. node_id = serial.read_u32(cur)
  419. return node_id
  420. def remove_node(self, node_id):
  421. req = bytearray()
  422. serial.write_u32(req, node_id)
  423. self._make_request(Command.REMOVE_NODE, req)
  424. def rename_node(self, node_id, node_name):
  425. req = bytearray()
  426. serial.write_u32(req, node_id)
  427. serial.encode_str(req, node_name)
  428. self._make_request(Command.RENAME_NODE, req)
  429. def scan_dangling(self):
  430. cur = self._make_request(Command.SCAN_DANGLING, bytearray())
  431. dangling_len = serial.decode_varint(cur)
  432. dangling = []
  433. for _ in range(dangling_len):
  434. node_id = serial.read_u32(cur)
  435. dangling.append(node_id)
  436. return dangling
  437. def lookup_node_id(self, node_path):
  438. req = bytearray()
  439. serial.encode_str(req, node_path)
  440. try:
  441. cur = self._make_request(Command.LOOKUP_NODE_ID, req)
  442. except exc.RequestNodeNotFound:
  443. return None
  444. return serial.read_u32(cur)
  445. def add_property(self, node_id, prop):
  446. req = bytearray()
  447. serial.write_u32(req, node_id)
  448. serial.encode_str(req, prop.name)
  449. serial.write_u8(req, int(prop.type))
  450. serial.write_u8(req, int(prop.subtype))
  451. serial.write_u32(req, int(prop.array_len))
  452. def write_defaults(by):
  453. assert prop.defaults is not None
  454. defaults_len = len(prop.defaults)
  455. serial.encode_varint(req, defaults_len)
  456. for default in prop.defaults:
  457. match prop.type:
  458. case PropertyType.UINT32:
  459. serial.write_u32(req, default)
  460. case PropertyType.FLOAT32:
  461. serial.write_f32(req, default)
  462. case PropertyType.STR:
  463. serial.encode_str(req, default)
  464. case _:
  465. raise exc.PropertyWrongType
  466. serial.encode_opt(req, prop.defaults, write_defaults)
  467. serial.encode_str(req, prop.ui_name)
  468. serial.encode_str(req, prop.desc)
  469. serial.write_u8(req, int(prop.is_null_allowed))
  470. serial.write_u8(req, int(prop.is_expr_allowed))
  471. def write_mxx(v, by):
  472. assert v is not None
  473. match prop.type:
  474. case PropertyType.UINT32:
  475. serial.write_u32(req, v)
  476. case PropertyType.FLOAT32:
  477. serial.write_f32(req, v)
  478. case _:
  479. raise exc.PropertyWrongType
  480. write_min = lambda by: write_mxx(prop.min_val, by)
  481. write_max = lambda by: write_mxx(prop.max_val, by)
  482. serial.encode_opt(req, prop.min_val, write_min)
  483. serial.encode_opt(req, prop.max_val, write_max)
  484. serial.encode_varint(req, len(prop.enum_items))
  485. for enum_item in prop.enum_items:
  486. if prop.type != PropertyType.ENUM:
  487. raise exc.PropertyWrongType
  488. serial.encode_str(req, enum_item)
  489. self._make_request(Command.ADD_PROPERTY, req)
  490. def link_node(self, child_id, parent_id):
  491. req = bytearray()
  492. serial.write_u32(req, child_id)
  493. serial.write_u32(req, parent_id)
  494. self._make_request(Command.LINK_NODE, req)
  495. def unlink_node(self, child_id, parent_id):
  496. req = bytearray()
  497. serial.write_u32(req, child_id)
  498. serial.write_u32(req, parent_id)
  499. self._make_request(Command.UNLINK_NODE, req)
  500. def set_property_bool(self, node_id, prop_name, i, val):
  501. req = bytearray()
  502. serial.write_u32(req, node_id)
  503. serial.encode_str(req, prop_name)
  504. serial.write_u32(req, i)
  505. serial.write_u8(req, PropertyType.BOOL)
  506. serial.write_u8(req, int(val))
  507. self._make_request(Command.SET_PROPERTY_VALUE, req)
  508. def set_property_u32(self, node_id, prop_name, i, val):
  509. req = bytearray()
  510. serial.write_u32(req, node_id)
  511. serial.encode_str(req, prop_name)
  512. serial.write_u32(req, i)
  513. serial.write_u8(req, PropertyType.UINT32)
  514. serial.write_u32(req, val)
  515. self._make_request(Command.SET_PROPERTY_VALUE, req)
  516. def set_property_f32(self, node_id, prop_name, i, val):
  517. req = bytearray()
  518. serial.write_u32(req, node_id)
  519. serial.encode_str(req, prop_name)
  520. serial.write_u32(req, i)
  521. serial.write_u8(req, PropertyType.FLOAT32)
  522. serial.write_f32(req, val)
  523. self._make_request(Command.SET_PROPERTY_VALUE, req)
  524. def set_property_str(self, node_id, prop_name, i, val):
  525. req = bytearray()
  526. serial.write_u32(req, node_id)
  527. serial.encode_str(req, prop_name)
  528. serial.write_u32(req, i)
  529. serial.write_u8(req, PropertyType.STR)
  530. serial.encode_str(req, val)
  531. self._make_request(Command.SET_PROPERTY_VALUE, req)
  532. def set_property_enum(self, node_id, prop_name, i, val):
  533. req = bytearray()
  534. serial.write_u32(req, node_id)
  535. serial.encode_str(req, prop_name)
  536. serial.write_u32(req, i)
  537. serial.write_u8(req, PropertyType.ENUM)
  538. serial.encode_str(req, val)
  539. self._make_request(Command.SET_PROPERTY_VALUE, req)
  540. def set_property_buf(self, node_id, prop_name, i, buf):
  541. req = bytearray()
  542. serial.write_u32(req, node_id)
  543. serial.encode_str(req, prop_name)
  544. serial.write_u32(req, i)
  545. serial.write_u8(req, PropertyType.BUFFER)
  546. serial.encode_buf(req, buf)
  547. self._make_request(Command.SET_PROPERTY_VALUE, req)
  548. def set_property_expr(self, node_id, prop_name, i, code):
  549. req = bytearray()
  550. serial.write_u32(req, node_id)
  551. serial.encode_str(req, prop_name)
  552. serial.write_u32(req, i)
  553. serial.write_u8(req, PropertyType.SEXPR)
  554. serial.encode_varint(req, len(code))
  555. for sexpr in code:
  556. expr.encode_expr(req, sexpr)
  557. self._make_request(Command.SET_PROPERTY_VALUE, req)
  558. def get_signals(self, node_id):
  559. req = bytearray()
  560. serial.write_u32(req, node_id)
  561. cur = self._make_request(Command.GET_SIGNALS, req)
  562. sigs_len = serial.decode_varint(cur)
  563. sigs = []
  564. for _ in range(sigs_len):
  565. sigs.append(serial.decode_str(cur))
  566. return sigs
  567. def register_slot(self, node_id, sig_name, slot_name, user_data):
  568. req = bytearray()
  569. serial.write_u32(req, node_id)
  570. serial.encode_str(req, sig_name)
  571. serial.encode_str(req, slot_name)
  572. serial.encode_varint(req, len(user_data))
  573. req += user_data
  574. cur = self._make_request(Command.REGISTER_SLOT, req)
  575. slot_id = serial.read_u32(cur)
  576. return slot_id
  577. def unregister_slot(self, node_id, sig_name, slot_id):
  578. req = bytearray()
  579. serial.write_u32(req, node_id)
  580. serial.encode_str(req, sig_name)
  581. serial.write_u32(req, slot_id)
  582. self._make_request(Command.UNREGISTER_SLOT, req)
  583. def lookup_slot_id(self, node_id, sig_name, slot_name):
  584. req = bytearray()
  585. serial.write_u32(req, node_id)
  586. serial.encode_str(req, sig_name)
  587. serial.encode_str(req, slot_name)
  588. try:
  589. cur = self._make_request(Command.LOOKUP_SLOT_ID, req)
  590. except exc.RequestSlotNotFound:
  591. return None
  592. return serial.read_u32(cur)
  593. def get_slots(self, node_id, sig_name):
  594. req = bytearray()
  595. serial.write_u32(req, node_id)
  596. serial.encode_str(req, sig_name)
  597. cur = self._make_request(Command.GET_SLOTS, req)
  598. def read_slot(cur):
  599. slot_name = serial.decode_str(cur)
  600. slot_id = serial.read_u32(cur)
  601. return (slot_name, slot_id)
  602. slots = serial.decode_arr(cur, read_slot)
  603. return slots
  604. def get_methods(self, node_id):
  605. req = bytearray()
  606. serial.write_u32(req, node_id)
  607. cur = self._make_request(Command.GET_METHODS, req)
  608. def read_method(cur):
  609. method_name = serial.decode_str(cur)
  610. return method_name
  611. methods = serial.decode_arr(cur, read_method)
  612. return methods
  613. def get_method(self, node_id, method_name):
  614. req = bytearray()
  615. serial.write_u32(req, node_id)
  616. serial.encode_str(req, method_name)
  617. cur = self._make_request(Command.GET_METHOD, req)
  618. def read_arg(cur):
  619. arg_name = serial.decode_str(cur)
  620. arg_desc = serial.decode_str(cur)
  621. arg_type = serial.read_u8(cur)
  622. return (arg_name, arg_desc, arg_type)
  623. args = serial.decode_arr(cur, read_arg)
  624. results = serial.decode_arr(cur, read_arg)
  625. return (args, results)
  626. def call_method(self, node_id, method_name, arg_data):
  627. req = bytearray()
  628. serial.write_u32(req, node_id)
  629. serial.encode_str(req, method_name)
  630. serial.encode_buf(req, arg_data)
  631. cur = self._make_request(Command.CALL_METHOD, req)
  632. errc = serial.read_u8(cur)
  633. result = serial.decode_buf(cur)
  634. return (errc, result)