stinger-ipc 0.0.10__py3-none-any.whl → 0.0.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {stinger_ipc-0.0.10.dist-info → stinger_ipc-0.0.26.dist-info}/METADATA +3 -2
  2. {stinger_ipc-0.0.10.dist-info → stinger_ipc-0.0.26.dist-info}/RECORD +35 -29
  3. stingeripc/asyncapi.py +3 -0
  4. stingeripc/components.py +61 -10
  5. stingeripc/schema/schema.yaml +240 -0
  6. stingeripc/templates/cpp/examples/client_main.cpp.jinja2 +18 -0
  7. stingeripc/templates/cpp/include/broker.hpp.jinja2 +18 -10
  8. stingeripc/templates/cpp/include/client.hpp.jinja2 +80 -11
  9. stingeripc/templates/cpp/include/ibrokerconnection.hpp.jinja2 +24 -4
  10. stingeripc/templates/cpp/include/property_structs.hpp.jinja2 +40 -2
  11. stingeripc/templates/cpp/include/server.hpp.jinja2 +5 -1
  12. stingeripc/templates/cpp/include/structs.hpp.jinja2 +2 -0
  13. stingeripc/templates/cpp/partials/args.jinja2 +11 -0
  14. stingeripc/templates/cpp/partials/deserialize.jinja2 +42 -0
  15. stingeripc/templates/cpp/partials/serialize.jinja2 +18 -0
  16. stingeripc/templates/cpp/src/broker.cpp.jinja2 +46 -24
  17. stingeripc/templates/cpp/src/client.cpp.jinja2 +111 -38
  18. stingeripc/templates/cpp/src/property_structs.cpp.jinja2 +25 -0
  19. stingeripc/templates/cpp/src/server.cpp.jinja2 +17 -25
  20. stingeripc/templates/cpp/src/structs.cpp.jinja2 +13 -0
  21. stingeripc/templates/html/app.js.jinja2 +130 -29
  22. stingeripc/templates/html/index.html.jinja2 +96 -8
  23. stingeripc/templates/html/styles.css.jinja2 +135 -0
  24. stingeripc/templates/markdown/index.md.jinja2 +151 -10
  25. stingeripc/templates/python/server.py.jinja2 +138 -18
  26. stingeripc/templates/rust/client/src/lib.rs.jinja2 +24 -5
  27. stingeripc/templates/rust/server/examples/server.rs.jinja2 +59 -23
  28. stingeripc/templates/rust/server/src/lib.rs.jinja2 +72 -51
  29. stingeripc/tools/cli.py +33 -7
  30. stingeripc/tools/cpp_generator.py +90 -0
  31. stingeripc/tools/rust_generator.py +1 -1
  32. stingeripc/templates/rust/payloads/src/handler.rs.jinja2 +0 -0
  33. {stinger_ipc-0.0.10.dist-info → stinger_ipc-0.0.26.dist-info}/WHEEL +0 -0
  34. {stinger_ipc-0.0.10.dist-info → stinger_ipc-0.0.26.dist-info}/entry_points.txt +0 -0
  35. {stinger_ipc-0.0.10.dist-info → stinger_ipc-0.0.26.dist-info}/licenses/LICENSE +0 -0
  36. {stinger_ipc-0.0.10.dist-info → stinger_ipc-0.0.26.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stinger-ipc
3
- Version: 0.0.10
3
+ Version: 0.0.26
4
4
  Summary: Tools to create code to do IPC over MQTT
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
7
7
  License-File: LICENSE
8
- Requires-Dist: jacobs-jinja-too>=0.2.4
8
+ Requires-Dist: jacobs-jinja-too>=0.2.5
9
+ Requires-Dist: jacobs-json-schema>=0.4.2
9
10
  Requires-Dist: packaging>=25.0
10
11
  Requires-Dist: pydantic>=2.11.7
11
12
  Requires-Dist: pyyaml>=6.0.2
@@ -1,57 +1,63 @@
1
- stinger_ipc-0.0.10.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
1
+ stinger_ipc-0.0.26.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
2
2
  stingeripc/__init__.py,sha256=PTr5WfMfB-GL4vp3-XMU8IwGv3Q5RXQ24H7JuEo3hdk,133
3
3
  stingeripc/args.py,sha256=x3P8GRu9-jyiMl62t0FPqbWY18FbhMVN4eSa2UzUv6c,3960
4
- stingeripc/asyncapi.py,sha256=DJZuz_LiQEJjQGlnfRtgOToWVD55uLw5ZoiZ95-bxZc,23291
5
- stingeripc/components.py,sha256=B08bXGrhVy90i3S67uS1kXDC3jQb_2bQay_LbgzWhQ4,38426
4
+ stingeripc/asyncapi.py,sha256=yyHDIM2Hm8stAPGmcuCostQ7Tk_YzVOqA2jAiqyp7j4,23445
5
+ stingeripc/components.py,sha256=xPVgrnDZhHuG0wAswvT1Lx6gQiWDUIvrEkVgVGiE578,40830
6
6
  stingeripc/connection.py,sha256=DfBG9LKaEuGacmX5NPphDabJqJmO3tVUg8Oa-efCd7w,184
7
7
  stingeripc/exceptions.py,sha256=nX5Xl4KjPTfSRTVZIB9NkgM0g_6auXgr5fTyunCZy5Q,51
8
8
  stingeripc/interface.py,sha256=ypt4T7hTH7ePKLy3JCl1b1ggyH5T38m68Gt0m_5VOBM,1558
9
9
  stingeripc/lang_symb.py,sha256=MOIMj9_mj6_8IADXCJf-EvlZ5d7Y6yR4QWsCONcw-T8,3331
10
10
  stingeripc/topic.py,sha256=mIL6Abf3fcI0yeSGj_o9ulV6xFNIfyfwGZ5joEVXyzE,2404
11
+ stingeripc/schema/schema.yaml,sha256=mck4f3zl0PuLlVJH7wS9JfsMySp_Diup43ytDje6sPk,4772
11
12
  stingeripc/templates/cpp/CMakeLists.txt.jinja2,sha256=jXlF2GOAt1mBsm6JqPZGaRr53NV5oJsfTd6nedeJ-GA,945
12
- stingeripc/templates/cpp/examples/client_main.cpp.jinja2,sha256=llUcuT4_R4SA5Nhpg6pRjs8nMogD5M21n6_aaewTJwE,2630
13
+ stingeripc/templates/cpp/examples/client_main.cpp.jinja2,sha256=Xgn5DfHPCFJ0Pfbcd9PKXiAhG54PLhwr60twEp-0mjY,3625
13
14
  stingeripc/templates/cpp/examples/server_main.cpp.jinja2,sha256=AvkkZX_jbB3xYL7W04ZKna_rE4fL8l1PN8b5pq9WrCU,1523
14
- stingeripc/templates/cpp/include/broker.hpp.jinja2,sha256=5VQ2k3EXavBlXjBfSykjH0YqhwTA_upDcVz_aIptwho,5569
15
- stingeripc/templates/cpp/include/client.hpp.jinja2,sha256=ap5gCYpTicYHRa0a97Ta9X836UxHNwErE0jM5H4Nmjg,2714
15
+ stingeripc/templates/cpp/include/broker.hpp.jinja2,sha256=-huaBDU-YHTbDdKNQ3tYKvtCZlW6mBBqC0rJ44_afkw,5467
16
+ stingeripc/templates/cpp/include/client.hpp.jinja2,sha256=ksng3hCp3dusEVz5CfUskgDJthnK3d_8HY4N0dwngRM,6155
16
17
  stingeripc/templates/cpp/include/enums.hpp.jinja2,sha256=psTnV1KXr72RfL4ufdtX8BO0Ub_CJm9Uj5h8UUM_-uI,598
17
- stingeripc/templates/cpp/include/ibrokerconnection.hpp.jinja2,sha256=KH73Jk6FqZ4MovN2bKSzgjKN-tufm3AxGsFRkT9USc4,1829
18
- stingeripc/templates/cpp/include/property_structs.hpp.jinja2,sha256=ndEUE-1A5l0aMFvd8n1R_3_eCMYLh1FosEFMh2LKbao,263
18
+ stingeripc/templates/cpp/include/ibrokerconnection.hpp.jinja2,sha256=yKPTaHHcs6yFpcI5hYMHCWBzZCKGXl_vz3IAm9n8LU4,2154
19
+ stingeripc/templates/cpp/include/property_structs.hpp.jinja2,sha256=rqknyWgG9P7q8oYIqNnFofyJhxyJ839SkaWa1rxwnfg,1793
19
20
  stingeripc/templates/cpp/include/return_types.hpp.jinja2,sha256=qFBkvNG0m4XT7sCVCjuE0cDoROp5Fq4XXiWUt6DwEho,528
20
- stingeripc/templates/cpp/include/server.hpp.jinja2,sha256=LSLf-Og2R1atstOSOJFuiOzBCEqFfXorJbC1IT1TZNY,2033
21
- stingeripc/templates/cpp/include/structs.hpp.jinja2,sha256=DJAAq07DWJmYAEI9An5yxD2YHbA0Vwv11xR5MgcQdmM,507
22
- stingeripc/templates/cpp/src/broker.cpp.jinja2,sha256=32bfKFJIzHe8w4JKZKjJ-wv8vVrYtOULyRK8f2lF1ow,9345
23
- stingeripc/templates/cpp/src/client.cpp.jinja2,sha256=lfIbb-Usnru44-5EmrAGzjFiLqkoiSt-9VYkIrugXSI,9010
24
- stingeripc/templates/cpp/src/server.cpp.jinja2,sha256=hs27uqLCwYR_1cvhwZwGiXTpEnsoBiGlMJE0pbY5cPg,7765
25
- stingeripc/templates/html/app.js.jinja2,sha256=07USEiNgd1euaahPTz3tfcV-aFKEBX83NAVgYVbvr98,4110
26
- stingeripc/templates/html/index.html.jinja2,sha256=egY_0riMki6czNQLTldOMlRdapFKNMouDfwMIcnDtuo,2155
27
- stingeripc/templates/html/styles.css.jinja2,sha256=C0-ZZk4SIzG9dv9x9MrfhHrtkHBj7jRBFIQ98BFlrcg,3323
28
- stingeripc/templates/markdown/index.md.jinja2,sha256=yB1Jpawc1VdBAzmnCI0ikdvVlcjZXf-2xRs159XSnHg,6432
21
+ stingeripc/templates/cpp/include/server.hpp.jinja2,sha256=Pg4LTkq2nS9W1naH6OpqH3TJwhIO47QaW9jFw9jLH5U,2004
22
+ stingeripc/templates/cpp/include/structs.hpp.jinja2,sha256=Fzm2cUSCwSdAcGyzq258YPZaYxmjfZVyVWwXlrLc-js,639
23
+ stingeripc/templates/cpp/partials/args.jinja2,sha256=jJYp_290Q21schBItazlf8bd60vbt42kjmW-VwgFATY,336
24
+ stingeripc/templates/cpp/partials/deserialize.jinja2,sha256=VwmsnpdHEQAXG7hD_MrmaiVjV6HazwoIXsjeoMfSSNY,1492
25
+ stingeripc/templates/cpp/partials/serialize.jinja2,sha256=iT1pNwT1m9ECb068HGn4U94CVVGBqgGpDPocpK0VuIA,826
26
+ stingeripc/templates/cpp/src/broker.cpp.jinja2,sha256=bBSSLjnJXpHHWhghf-SljJ825nsrQaTOBoOIzoXLbp4,10368
27
+ stingeripc/templates/cpp/src/client.cpp.jinja2,sha256=BQujzcyN9XnZZ-92U-psggkFNayj5NL6LZxsJeqQCdM,12368
28
+ stingeripc/templates/cpp/src/property_structs.cpp.jinja2,sha256=e7K3tGhZZ9iekEYOJvcPmhWCAonOTVMKwCQI39tfyZ4,939
29
+ stingeripc/templates/cpp/src/server.cpp.jinja2,sha256=c9XeBzfC2uIxpkpRGPmKHZV11tpSWmRX19ZGkMDO9lo,7001
30
+ stingeripc/templates/cpp/src/structs.cpp.jinja2,sha256=w4DSPqWf7r01lhuwwCbyoVwmUr5W1GqC2G8x_G3O_Gk,493
31
+ stingeripc/templates/html/app.js.jinja2,sha256=hbwXzV2JaSu8r-riDMp1eyw-xbG5_EjhH3gpblpvboI,8352
32
+ stingeripc/templates/html/index.html.jinja2,sha256=uu3bCfQyPbcrJToPVq9W0zCrfmLeFeKPfHgv5upW2Vw,6004
33
+ stingeripc/templates/html/styles.css.jinja2,sha256=kPasL4hXp8F9y7FtPgchDCl5qoZgfPsDIvkZPyE_Mog,6706
34
+ stingeripc/templates/markdown/index.md.jinja2,sha256=Fbr6qvstccE4nFN8KIMrCRs7caWS2YU6eEJT5cEB8CY,11976
29
35
  stingeripc/templates/python/__init__.py.jinja2,sha256=jdZ07ogzJLOgzqqkHjj2_8hld9uBDnvB1DXPXnWkt98,22
30
36
  stingeripc/templates/python/client.py.jinja2,sha256=lUlnh-Z2ulDaomx-bR7RAgovmZ4QYLjck0c_885x8DY,16461
31
37
  stingeripc/templates/python/connection.py.jinja2,sha256=mTiiC_p4AEwIGH9mvyzYDdu_AKxpI_548LpapL5CM-4,7238
32
38
  stingeripc/templates/python/interface_types.py.jinja2,sha256=BcCD0uCzDn1TAn1IvWhHiOsai6MczIBu12Xg0snTHk8,1711
33
39
  stingeripc/templates/python/method_codes.py.jinja2,sha256=74i8iKk4Fu9_nE2SYTRrRK2G4mogfJx88ihbmjyfYVQ,1089
34
40
  stingeripc/templates/python/pyproject.toml.jinja2,sha256=R-rgSv6RTdgPINvhCwJ180Vzjy9-WkqtLbLgnCov3CI,195
35
- stingeripc/templates/python/server.py.jinja2,sha256=pxjzLPE7k3DG6zE-zXyK_I16ZF8k-xgbdh_182Fx_E8,11217
41
+ stingeripc/templates/python/server.py.jinja2,sha256=oK5fy2YfkJXfpzM46zLann9sATRUzP_qJxuol5GGDWI,18253
36
42
  stingeripc/templates/rust/Cargo.toml.jinja2,sha256=teIu5y2AeqSkk0eUPT8CemvzmhRoblCUP5jdmonLfY4,70
37
43
  stingeripc/templates/rust/client/Cargo.toml.jinja2,sha256=oymbdtF3apgD4nVxt-fa9__hSZaUFsvjA0AxJarPMGw,858
38
44
  stingeripc/templates/rust/client/examples/client.rs.jinja2,sha256=pMLR-xyEJrK4289XUbFEB18HKe3kaRJDoeFBQ89SLU4,2075
39
- stingeripc/templates/rust/client/src/lib.rs.jinja2,sha256=7GGy_IBH-DBHIZUCvvBq1xbTTVVMczvx5W-i0qO_fvw,15451
45
+ stingeripc/templates/rust/client/src/lib.rs.jinja2,sha256=S8aFZJ9EmErCXAFCY2MuQcnBK_y6_Brh-TlaRVs5sow,16950
40
46
  stingeripc/templates/rust/payloads/Cargo.toml.jinja2,sha256=t6WQ5BCBvjagCW8AgK4VYSNjW2OZCX30KQTXk27SGwI,739
41
47
  stingeripc/templates/rust/payloads/examples/pub_and_recv.rs.jinja2,sha256=cIbunwEwYGbkRO1lzi2nGNX2dGdFhAJ2ZZqFhphY7CY,1461
42
- stingeripc/templates/rust/payloads/src/handler.rs.jinja2,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
48
  stingeripc/templates/rust/payloads/src/lib.rs.jinja2,sha256=3vBn2OGm_j7BoyHRHLcH1e0hKRBiqtbgHsz04rTaVMM,86
44
49
  stingeripc/templates/rust/payloads/src/payloads.rs.jinja2,sha256=1PUSzmHLMBYsVaCR8gOMdHWK8dmODmLM3WSu9iysN-c,4380
45
50
  stingeripc/templates/rust/server/Cargo.toml.jinja2,sha256=t2MIpoe34RYOtxvpS6ma7W0A9sLlMQBYblpALU805TQ,573
46
- stingeripc/templates/rust/server/examples/server.rs.jinja2,sha256=NVNR_kamR3t4FSpfYGfao0S9DpK1zXTQcOZR1WDPAaI,3624
47
- stingeripc/templates/rust/server/src/lib.rs.jinja2,sha256=OE9WxOUmKLc1iii8iXKn5BAwMpP9HXrIYcGdmZnQG7U,14973
51
+ stingeripc/templates/rust/server/examples/server.rs.jinja2,sha256=L8Cgs1Wb1HFLyMqF0EARUtrgqoxXly6u4kaSElaNrHo,4851
52
+ stingeripc/templates/rust/server/src/lib.rs.jinja2,sha256=rhackDGeDndEXoNXoldsc-jr7I-nP2uYKTZSnWXOaIU,15675
48
53
  stingeripc/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- stingeripc/tools/cli.py,sha256=oLfVQx4EqRgZ2AH9Xl7X6neXle-aJE55bSXTEvH7RDE,2303
54
+ stingeripc/tools/cli.py,sha256=RqeL6FcoeUCvle86jmox-4A25SL4Br2CSZXPKbaJwlY,3372
55
+ stingeripc/tools/cpp_generator.py,sha256=jYIRVjykI4corEI65CsA7q42psFxfkgskasYcSXSbqY,3111
50
56
  stingeripc/tools/markdown_generator.py,sha256=HVEWcMjAfVnuWY29kxfAW1mvSxQSF-rdYFA2kWdLOn0,1174
51
57
  stingeripc/tools/python_generator.py,sha256=GJwGI6DntkJPJjHN4xSeTD60KgY32gI43IvIByxWSsw,1845
52
- stingeripc/tools/rust_generator.py,sha256=9E7SMDM-iHE3O26QI3ieAHIInlrLepWMAFRnflKk3KI,2235
53
- stinger_ipc-0.0.10.dist-info/METADATA,sha256=IWuujmhLBXd10UkK5gE5TMYfPHdPY1JTzev_X75npgs,6038
54
- stinger_ipc-0.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
55
- stinger_ipc-0.0.10.dist-info/entry_points.txt,sha256=bh8k8mvtAog4MKTd82ALSHqQkuD069VrZ-vNlde6XjE,204
56
- stinger_ipc-0.0.10.dist-info/top_level.txt,sha256=mSNwAf83_1qiTP_vu7XEPBrZu-fDusT1FFyQZzCrRcU,11
57
- stinger_ipc-0.0.10.dist-info/RECORD,,
58
+ stingeripc/tools/rust_generator.py,sha256=Im0EdNifxkGDnZy2JCuvKzmn1h2suk6EJ_xtpGZazGk,2240
59
+ stinger_ipc-0.0.26.dist-info/METADATA,sha256=dIRomA-GKMIZRvcna1tVp-6QoanVoZ4wfRUT6rbu2Yk,6079
60
+ stinger_ipc-0.0.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
61
+ stinger_ipc-0.0.26.dist-info/entry_points.txt,sha256=bh8k8mvtAog4MKTd82ALSHqQkuD069VrZ-vNlde6XjE,204
62
+ stinger_ipc-0.0.26.dist-info/top_level.txt,sha256=mSNwAf83_1qiTP_vu7XEPBrZu-fDusT1FFyQZzCrRcU,11
63
+ stinger_ipc-0.0.26.dist-info/RECORD,,
stingeripc/asyncapi.py CHANGED
@@ -571,6 +571,9 @@ class StingerToAsyncApi:
571
571
  add_arg(arg_spec)
572
572
  resp_msg_schema.add_value_dependency(arg_spec.name, "result", 0)
573
573
  elif method_spec.return_value is not None:
574
+ assert isinstance(
575
+ method_spec.return_value, Arg
576
+ ), "Method return value must be a primitive or enum"
574
577
  add_arg(method_spec.return_value)
575
578
  resp_msg_schema.add_value_dependency(
576
579
  method_spec.return_value_name, "result", 0
stingeripc/components.py CHANGED
@@ -79,6 +79,10 @@ class Arg:
79
79
  def rust_local_type(self) -> str:
80
80
  return self.rust_type
81
81
 
82
+ @property
83
+ def cpp_type(self) -> str:
84
+ return stringmanip.upper_camel_case(self.name)
85
+
82
86
  @classmethod
83
87
  def new_arg_from_stinger(
84
88
  cls, arg_spec: YamlArg, stinger_spec: StingerSpec | None = None
@@ -107,32 +111,40 @@ class Arg:
107
111
  if arg_spec["type"] == "enum":
108
112
  if "enumName" not in arg_spec:
109
113
  raise InvalidStingerStructure(f"Enum args need a 'enumName'")
114
+ if not isinstance(arg_spec["enumName"], str):
115
+ raise InvalidStingerStructure("'enumName' in arg structure must be a string")
110
116
  if arg_spec["enumName"] not in stinger_spec.enums:
111
117
  raise InvalidStingerStructure(
112
118
  f"Enum arg '{arg_spec['enumName']}' was not found in the list of stinger spec enums"
113
119
  )
114
- arg = ArgEnum(
120
+ enum_arg = ArgEnum(
115
121
  arg_spec["name"], stinger_spec.get_interface_enum(arg_spec["enumName"])
116
122
  )
117
123
  if opt := arg_spec.get("optional", False):
118
- arg.optional = opt
119
- arg.try_set_description_from_spec(arg_spec)
120
- return arg
124
+ if not isinstance(opt, bool):
125
+ raise InvalidStingerStructure("'optional' in arg structure must be a boolean")
126
+ enum_arg.optional = opt
127
+ enum_arg.try_set_description_from_spec(arg_spec)
128
+ return enum_arg
121
129
 
122
130
  if arg_spec["type"] == "struct":
123
131
  if "structName" not in arg_spec:
124
132
  raise InvalidStingerStructure("Struct args need a 'structName'")
133
+ if not isinstance(arg_spec["structName"], str):
134
+ raise InvalidStingerStructure("'structName' in arg structure must be a string")
125
135
  if arg_spec["structName"] not in stinger_spec.structs:
126
136
  raise InvalidStingerStructure(
127
137
  f"Struct arg '{arg_spec["structName"]}' was not found in the list of stinger spec structs"
128
138
  )
129
- arg = ArgStruct(
139
+ st_arg = ArgStruct(
130
140
  arg_spec["name"], stinger_spec.structs[arg_spec["structName"]]
131
141
  )
132
142
  if opt := arg_spec.get("optional", False):
133
- arg.optional = opt
134
- arg.try_set_description_from_spec(arg_spec)
135
- return arg
143
+ if not isinstance(opt, bool):
144
+ raise InvalidStingerStructure("'optional' in arg structure must be a boolean")
145
+ st_arg.optional = opt
146
+ st_arg.try_set_description_from_spec(arg_spec)
147
+ return st_arg
136
148
  raise RuntimeError(f"unknown arg type: {arg_spec['type']}")
137
149
 
138
150
  @abstractmethod
@@ -240,6 +252,8 @@ class ArgPrimitive(Arg):
240
252
  @property
241
253
  def cpp_temp_type(self) -> str:
242
254
  if self._arg_type == ArgPrimitiveType.STRING:
255
+ if self.optional:
256
+ return "boost::optional<std::string>"
243
257
  return "std::string"
244
258
  else:
245
259
  return self.cpp_type
@@ -288,6 +302,10 @@ class ArgPrimitive(Arg):
288
302
  raise InvalidStingerStructure("No 'type' in arg structure")
289
303
  if "name" not in arg_spec:
290
304
  raise InvalidStingerStructure("No 'name' in arg structure")
305
+ if not isinstance(arg_spec["type"], str):
306
+ raise InvalidStingerStructure("'type' in arg structure must be a string")
307
+ if not isinstance(arg_spec["name"], str):
308
+ raise InvalidStingerStructure("'name' in arg structure must be a string")
291
309
 
292
310
  arg_primitive_type = ArgPrimitiveType.from_string(arg_spec["type"])
293
311
  arg: ArgPrimitive = cls(name=arg_spec["name"], arg_type=arg_primitive_type)
@@ -333,6 +351,10 @@ class ArgStruct(Arg):
333
351
  def markdown_type(self) -> str:
334
352
  return f"[Struct {self._interface_struct.class_name}](#enum-{self._interface_struct.class_name})"
335
353
 
354
+ @property
355
+ def cpp_rapidjson_type(self) -> str:
356
+ return "Object"
357
+
336
358
  def get_random_example_value(self, lang="python", seed: int = 2) -> str | None:
337
359
  example_list: dict[str, str] = {
338
360
  a.name: str(a.get_random_example_value(lang, seed=seed))
@@ -688,6 +710,8 @@ class Property(InterfaceComponent):
688
710
  prop_obj.add_arg(new_arg)
689
711
 
690
712
  if r_o := prop_spec.get("readOnly", False):
713
+ if not isinstance(r_o, bool):
714
+ raise InvalidStingerStructure("'readOnly' in property structure must be a boolean")
691
715
  prop_obj._read_only = r_o
692
716
 
693
717
  prop_obj.try_set_documentation_from_spec(prop_spec)
@@ -749,6 +773,11 @@ class InterfaceEnum:
749
773
  @property
750
774
  def values(self):
751
775
  return self._values
776
+
777
+ def value_description(self, index: int) -> str | None:
778
+ if index < 0 or index >= len(self._value_descriptions):
779
+ return None
780
+ return self._value_descriptions[index]
752
781
 
753
782
  @classmethod
754
783
  def new_enum_from_stinger(cls, name, enum_spec: YamlIfaceEnum) -> InterfaceEnum:
@@ -756,7 +785,12 @@ class InterfaceEnum:
756
785
  for enum_obj in enum_spec.get("values", []):
757
786
  assert isinstance(enum_obj, dict), f"Enum values must be a dicts."
758
787
  if "name" in enum_obj and isinstance(enum_obj["name"], str):
759
- ie.add_value(enum_obj["name"], enum_obj.get("description", None))
788
+ value_description = enum_obj.get("description", None)
789
+ if value_description is not None and not isinstance(value_description, str):
790
+ raise InvalidStingerStructure(
791
+ f"InterfaceEnum '{name}' item descriptions must be strings."
792
+ )
793
+ ie.add_value(enum_obj["name"], description=value_description)
760
794
  else:
761
795
  raise InvalidStingerStructure(
762
796
  f"InterfaceEnum '{name}' items must have string names."
@@ -834,9 +868,14 @@ class InterfaceStruct:
834
868
  ) -> InterfaceStruct:
835
869
  istruct = cls(name)
836
870
  for memb in spec.get("members", []):
871
+ if not isinstance(memb, dict):
872
+ raise InvalidStingerStructure("Struct members must be dicts")
837
873
  arg = Arg.new_arg_from_stinger(memb, stinger_spec=stinger_spec)
838
874
  istruct.add_member(arg)
839
- istruct._description = spec.get("description", None)
875
+ description = spec.get("description", None)
876
+ if description is not None and not isinstance(description, str):
877
+ raise InvalidStingerStructure("Struct description must be a string")
878
+ istruct._description = description
840
879
  return istruct
841
880
 
842
881
  def __str__(self) -> str:
@@ -948,6 +987,18 @@ class StingerSpec:
948
987
  }
949
988
  return (self._topic_creator.interface_info_topic(), info)
950
989
 
990
+ @property
991
+ def summary(self) -> str:
992
+ return self._summary or ""
993
+
994
+ @property
995
+ def title(self) -> str:
996
+ return self._title or self._name or ""
997
+
998
+ @property
999
+ def documentation(self) -> str:
1000
+ return self._documentation or ""
1001
+
951
1002
  def add_broker(self, broker: Broker):
952
1003
  assert broker is not None
953
1004
  self._brokers[broker.name] = broker
@@ -0,0 +1,240 @@
1
+ $id: "https://stingeripc.peargrove.com/stingeripc.schema.yaml"
2
+ $schema: "http://json-schema.org/draft-07/schema#"
3
+ description: |
4
+ This schema is used to validate StingerIPC stinger files.
5
+ type: object
6
+
7
+ properties:
8
+
9
+ stingeripc:
10
+ type: object
11
+ properties:
12
+ version:
13
+ type: string
14
+ const: "0.0.7"
15
+ required:
16
+ - version
17
+
18
+ interface:
19
+ type: object
20
+ parameters:
21
+ name:
22
+ type: string
23
+ pattern: "[a-zA-Z0-9_]+"
24
+ maxLength: 32
25
+ description: "A short token that will be used to create class names, folder names, filenames, etc."
26
+ title:
27
+ type: string
28
+ maxLength: 64
29
+ description: "A few words that are the title for the API. Used at the top of documentation, etc. The interface name is used if not provided."
30
+ summary:
31
+ type: string
32
+ description: "A one sentence description of the service."
33
+ maxLength: 128
34
+ version:
35
+ type: string
36
+ maxLength: 32
37
+ documentation:
38
+ $ref: "#/$defs/documentation"
39
+ required:
40
+ - name
41
+ - version
42
+
43
+ brokers:
44
+ type: object
45
+ additionalProperties:
46
+ type: object
47
+ properties:
48
+ host:
49
+ type: string
50
+ port:
51
+ type: integer
52
+ protocol:
53
+ type: string
54
+ enum:
55
+ - tcp
56
+ - websockets
57
+ default: tcp
58
+ secure:
59
+ type: boolean
60
+ default: false
61
+ description:
62
+ type: string
63
+
64
+ dependentRequired:
65
+ host: ["port"]
66
+
67
+ enums:
68
+ type: object
69
+ additionalProperties:
70
+ type: object
71
+ properties:
72
+ values:
73
+ type: array
74
+ uniqueItems: true
75
+ items:
76
+ type: object
77
+ properties:
78
+ name:
79
+ type: string
80
+ required:
81
+ - name
82
+ documentation:
83
+ $ref: "#/$defs/documentation"
84
+ required:
85
+ - values
86
+
87
+ structures:
88
+ type: object
89
+ additionalProperties:
90
+ type: object
91
+ properties:
92
+ members:
93
+ $ref: "#/$defs/payload"
94
+ documentation:
95
+ $ref: "#/$defs/documentation"
96
+ required:
97
+ - members
98
+
99
+ signals:
100
+ type: object
101
+ additionalProperties:
102
+ $ref: "#/$defs/signal"
103
+
104
+ properties:
105
+ type: object
106
+ additionalProperties:
107
+ $ref: "#/$defs/property"
108
+
109
+ methods:
110
+ type: object
111
+ additionalProperties:
112
+ $ref: "#/$defs/method"
113
+
114
+ required:
115
+ - stingeripc
116
+ - interface
117
+
118
+ $defs:
119
+
120
+ documentation:
121
+ type: string
122
+
123
+ payload:
124
+ type: array
125
+ uniqueItems: true
126
+ items:
127
+ $ref: "#/$defs/arg"
128
+
129
+ genericArg:
130
+ type: object
131
+ required:
132
+ - "type"
133
+ - "name"
134
+ properties:
135
+ name:
136
+ type: string
137
+ optional:
138
+ type: boolean
139
+ default: false
140
+ description:
141
+ type: string
142
+ schema:
143
+ type: object
144
+ description: A JSON schema which further constrains the value.
145
+
146
+ primitiveArg:
147
+ properties:
148
+ type:
149
+ type: string
150
+ enum:
151
+ - float
152
+ - string
153
+ - integer
154
+ - boolean
155
+ - date
156
+ - time
157
+ - datetime
158
+ - duration
159
+ - binary
160
+
161
+ enumArg:
162
+ properties:
163
+ type:
164
+ type: string
165
+ const: "enum"
166
+ enumName:
167
+ type: string
168
+ required:
169
+ - enumName
170
+
171
+ structArg:
172
+ properties:
173
+ type:
174
+ type: string
175
+ const: "struct"
176
+ structName:
177
+ type: string
178
+ required:
179
+ - structName
180
+
181
+ listArg:
182
+ properties:
183
+ type:
184
+ type: string
185
+ const: "list"
186
+ itemType:
187
+ oneOf:
188
+ - $ref: "#/$defs/primitiveArg"
189
+ - $ref: "#/$defs/enumArg"
190
+ - $ref: "#/$defs/structArg"
191
+ required:
192
+ - itemType
193
+
194
+ arg:
195
+ oneOf:
196
+ - allOf:
197
+ - $ref: "#/$defs/genericArg"
198
+ - $ref: "#/$defs/primitiveArg"
199
+ - allOf:
200
+ - $ref: "#/$defs/genericArg"
201
+ - $ref: "#/$defs/enumArg"
202
+ - allOf:
203
+ - $ref: "#/$defs/genericArg"
204
+ - $ref: "#/$defs/structArg"
205
+ - allOf:
206
+ - $ref: "#/$defs/genericArg"
207
+ - $ref: "#/$defs/listArg"
208
+
209
+ signal:
210
+ type: object
211
+ properties:
212
+ documentation:
213
+ $ref: "#/$defs/documentation"
214
+ payload:
215
+ $ref: "#/$defs/payload"
216
+
217
+ property:
218
+ type: object
219
+ properties:
220
+ documentation:
221
+ $ref: "#/$defs/documentation"
222
+ values:
223
+ $ref: "#/$defs/payload"
224
+ readOnly:
225
+ type: boolean
226
+ default: false
227
+ required:
228
+ - values
229
+
230
+ method:
231
+ type: object
232
+ properties:
233
+ documentation:
234
+ $ref: "#/$defs/documentation"
235
+ arguments:
236
+ $ref: "#/$defs/payload"
237
+ returnValues:
238
+ $ref: "#/$defs/payload"
239
+ required:
240
+ - arguments
@@ -1,3 +1,4 @@
1
+ {% import 'partials/args.jinja2' as ar %}
1
2
 
2
3
  #include <iostream>
3
4
  #include <boost/chrono/chrono.hpp>
@@ -16,6 +17,23 @@ int main(int argc, char** argv) {
16
17
  });
17
18
  {%-endfor%}
18
19
 
20
+ {%- for prop_name, prop in stinger.properties.items() %}
21
+ client.register{{prop_name | UpperCamelCase}}PropertyCallback([]({{ar.methodParams(prop.arg_list)}}) {
22
+ std::cout << "Received update for {{prop_name}} property: " << {# #}
23
+ {%-for arg in prop.arg_list-%}
24
+ "{{arg.name}}=" << {%if arg.optional%} "None"{%else%}
25
+ {%-if arg.arg_type.name.lower() == 'enum'%}
26
+ {{arg.enum.name | camelCase }}Strings[static_cast<int>({{arg.name}})]
27
+ {%elif arg.arg_type.name.lower() == 'struct'-%}
28
+ "[{{arg.cpp_type}} object]"
29
+ {%-else%}{{arg.name}}{%endif%}
30
+ {%-endif%} <<
31
+ {%-if not loop.last %} " | " << {%endif%}
32
+ {%-endfor-%}
33
+ std::endl;
34
+ });
35
+ {%endfor%}
36
+
19
37
  {%-for method_name, method in stinger.methods.items() %}
20
38
  std::cout << "Calling {{method_name}}" << std::endl;
21
39
  auto {{method_name|camelCase}}ResultFuture = client.{{method_name | camelCase}}({%for arg in method.arg_list%}{{arg.get_random_example_value('c++')}}{%if not loop.last%}, {%endif%}{%endfor%});
@@ -51,21 +51,24 @@ public:
51
51
  const std::string& payload,
52
52
  unsigned qos,
53
53
  bool retain,
54
- boost::optional<std::string> optCorrelationId,
55
- boost::optional<std::string> optResponseTopic,
56
- boost::optional<MethodResultCode> optResultCode);
54
+ const MqttProperties& properties);
57
55
 
58
56
  /*! Subscribe to a topic.
59
57
  * \param topic the subscription topic.
60
58
  * \param qos an MQTT quality of service value between 0 and 2 inclusive.
59
+ * \return the MQTT subscription ID.
61
60
  */
62
- virtual void Subscribe(const std::string& topic, int qos);
61
+ virtual int Subscribe(const std::string& topic, int qos);
63
62
 
64
63
  /*! Add a function that is called on the receipt of a message.
65
64
  * Many callbacks can be added, and each will be called in the order in which the callbacks were added.
66
65
  * \param cb the callback function.
67
66
  */
68
- virtual void AddMessageCallback(const std::function<void(const std::string&, const std::string&, const boost::optional<std::string>, const boost::optional<std::string>, const boost::optional<MethodResultCode>)>& cb);
67
+ virtual void AddMessageCallback(const std::function<void(
68
+ const std::string&,
69
+ const std::string&,
70
+ const MqttProperties&
71
+ )>& cb);
69
72
 
70
73
  /*! Determines if a topic string matches a subscription topic.
71
74
  * \param topic a topic to match against a subscription.
@@ -99,20 +102,25 @@ private:
99
102
 
100
103
  struct MqttSubscription
101
104
  {
102
- MqttSubscription(const std::string& topic, int qos) : _topic(topic), _qos(qos) {}
105
+ MqttSubscription(const std::string& topic, int qos, int subscriptionId) : topic(topic), qos(qos), subscriptionId(subscriptionId) {}
103
106
  ~MqttSubscription() = default;
104
- std::string _topic;
105
- int _qos;
106
- int subscription_id;
107
+ std::string topic;
108
+ int qos;
109
+ int subscriptionId;
107
110
  };
108
111
 
109
112
  mosquitto *_mosq;
110
113
  std::string _host;
111
114
  int _port;
112
115
  std::string _clientId;
116
+ int _nextSubscriptionId = 1;
113
117
  std::queue<MqttSubscription> _subscriptions;
114
118
  boost::mutex _mutex;
115
- std::vector<std::function<void(const std::string&, const std::string&, const boost::optional<std::string>, const boost::optional<std::string>, const boost::optional<MethodResultCode>)>> _messageCallbacks;
119
+ std::vector<std::function<void(
120
+ const std::string&,
121
+ const std::string&,
122
+ const MqttProperties&
123
+ )>> _messageCallbacks;
116
124
  std::queue<MqttMessage> _msgQueue;
117
125
  std::map<int, std::shared_ptr<boost::promise<bool>>> _sendMessages;
118
126
  };