From 82dfcc8cc53b50e7c738a9a2f71b9e0f501b7a42 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 3 Jun 2025 16:02:50 +0200 Subject: [PATCH 1/4] mod: decluttering decoder.h examples: rpc_lite_server binding lambdas and static class methods --- examples/rpc_lite_server/rpc_lite_server.ino | 16 +++- src/decoder.h | 86 +---------------- src/rpclite_utils.h | 99 +++++++++++++++++++- 3 files changed, 113 insertions(+), 88 deletions(-) diff --git a/examples/rpc_lite_server/rpc_lite_server.ino b/examples/rpc_lite_server/rpc_lite_server.ino index 81da0e1..665ead4 100644 --- a/examples/rpc_lite_server/rpc_lite_server.ino +++ b/examples/rpc_lite_server/rpc_lite_server.ino @@ -1,6 +1,6 @@ #include -SerialTransport transport(&Serial1); +SerialTransport transport(&Serial2); RPCServer server(transport); int add(int a, int b){ @@ -15,8 +15,18 @@ MsgPack::str_t loopback(MsgPack::str_t message){ return message; } +class multiplier { +public: + + multiplier(){} + static int mult(int a, int b){ + return a*b; + } +}; + + void setup() { - Serial1.begin(115200); + Serial2.begin(115200); transport.begin(); pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600); @@ -24,6 +34,8 @@ void setup() { server.bind("add", add); server.bind("greet", greet); + server.bind("another_greeting", [] {return MsgPack::str_t ("This is a lambda greeting");}); + server.bind("object_multi", &multiplier::mult); } diff --git a/src/decoder.h b/src/decoder.h index 51ea45f..97052bc 100644 --- a/src/decoder.h +++ b/src/decoder.h @@ -4,6 +4,7 @@ #include "MsgPack.h" #include "transport.h" #include "dispatcher.h" +#include "rpclite_utils.h" #define NO_MSG -1 @@ -293,91 +294,6 @@ class RpcDecoder { return 0; } - bool unpackObject(MsgPack::Unpacker& unpacker){ - - if (unpacker.isNil()){ - static MsgPack::object::nil_t nil; - return unpacker.deserialize(nil); - } - if (unpacker.isBool()){ - static bool b; - return unpacker.deserialize(b); - } - if (unpacker.isUInt() || unpacker.isInt()){ - static int integer; - return unpacker.deserialize(integer); - } - if (unpacker.isFloat32()){ - static float num32; - return unpacker.deserialize(num32); - } - if (unpacker.isFloat64()){ - static double num64; - return unpacker.deserialize(num64); - } - if (unpacker.isStr()){ - static MsgPack::str_t string; - return unpacker.deserialize(string); - } - if (unpacker.isBin()){ - static MsgPack::bin_t bytes; - return unpacker.deserialize(bytes); - } - if (unpacker.isArray()){ - static size_t arr_sz; - return unpackArray(unpacker, arr_sz); - } - if (unpacker.isMap()){ - static size_t map_sz; - return unpackMap(unpacker, map_sz); - } - if (unpacker.isFixExt() || unpacker.isExt()){ - static MsgPack::object::ext e; - return unpacker.deserialize(e); - } - if (unpacker.isTimestamp()){ - static MsgPack::object::timespec t; - return unpacker.deserialize(t); - } - - return false; - } - - bool unpackArray(MsgPack::Unpacker& unpacker, size_t& size) { - - static MsgPack::arr_size_t sz; - unpacker.deserialize(sz); - - size = 0; - for (size_t i=0; i -#include +#include namespace RpcUtils { namespace detail { + +/////////////////////////////////////// +/// --- deserialization helpers --- /// +/////////////////////////////////////// + +bool unpackObject(MsgPack::Unpacker& unpacker); + +bool unpackArray(MsgPack::Unpacker& unpacker, size_t& size) { + + static MsgPack::arr_size_t sz; + unpacker.deserialize(sz); + + size = 0; + for (size_t i=0; i bytes; + return unpacker.deserialize(bytes); + } + if (unpacker.isArray()){ + static size_t arr_sz; + return unpackArray(unpacker, arr_sz); + } + if (unpacker.isMap()){ + static size_t map_sz; + return unpackMap(unpacker, map_sz); + } + if (unpacker.isFixExt() || unpacker.isExt()){ + static MsgPack::object::ext e; + return unpacker.deserialize(e); + } + if (unpacker.isTimestamp()){ + static MsgPack::object::timespec t; + return unpacker.deserialize(t); + } + + return false; +} + template bool deserialize_single(MsgPack::Unpacker& unpacker, T& value) { if (!unpacker.unpackable(value)) return false; @@ -15,6 +107,11 @@ bool deserialize_single(MsgPack::Unpacker& unpacker, T& value) { return true; } + +///////////////////////////// +/// --- tuple helpers --- /// +///////////////////////////// + template typename std::enable_if::type deserialize_tuple(MsgPack::Unpacker&, std::tuple&) { From 4e64c20961aa99ce14ae5deaee74de02f7b6e1c5 Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 3 Jun 2025 16:06:57 +0200 Subject: [PATCH 2/4] server example revert Serial2 to Serial1 --- examples/rpc_lite_server/rpc_lite_server.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/rpc_lite_server/rpc_lite_server.ino b/examples/rpc_lite_server/rpc_lite_server.ino index 665ead4..3bd2f79 100644 --- a/examples/rpc_lite_server/rpc_lite_server.ino +++ b/examples/rpc_lite_server/rpc_lite_server.ino @@ -1,6 +1,6 @@ #include -SerialTransport transport(&Serial2); +SerialTransport transport(&Serial1); RPCServer server(transport); int add(int a, int b){ @@ -26,7 +26,7 @@ public: void setup() { - Serial2.begin(115200); + Serial1.begin(115200); transport.begin(); pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600); From ea01c3440b5b31b404fa4a354bdec61ee59784cb Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 3 Jun 2025 16:36:09 +0200 Subject: [PATCH 3/4] refactor: mock transport moved in the examples. rm DEBUG --- .../decoder_example}/DummyTransport.h | 0 examples/decoder_example/decoder_example.ino | 2 +- examples/decoder_tests/DummyTransport.h | 56 +++++++++++++++++++ examples/decoder_tests/decoder_tests.ino | 1 + src/Arduino_RPClite.h | 2 - 5 files changed, 58 insertions(+), 3 deletions(-) rename {src => examples/decoder_example}/DummyTransport.h (100%) create mode 100644 examples/decoder_tests/DummyTransport.h diff --git a/src/DummyTransport.h b/examples/decoder_example/DummyTransport.h similarity index 100% rename from src/DummyTransport.h rename to examples/decoder_example/DummyTransport.h diff --git a/examples/decoder_example/decoder_example.ino b/examples/decoder_example/decoder_example.ino index 9a12f6c..794314b 100644 --- a/examples/decoder_example/decoder_example.ino +++ b/examples/decoder_example/decoder_example.ino @@ -1,5 +1,5 @@ -#define DEBUG #include +#include "DummyTransport.h" void blink_before(){ digitalWrite(LED_BUILTIN, HIGH); diff --git a/examples/decoder_tests/DummyTransport.h b/examples/decoder_tests/DummyTransport.h new file mode 100644 index 0000000..dc3b3b7 --- /dev/null +++ b/examples/decoder_tests/DummyTransport.h @@ -0,0 +1,56 @@ +// +// Created by lucio on 4/8/25. +// + +#ifndef DUMMY_TRANSPORT_H +#define DUMMY_TRANSPORT_H +#include "transport.h" + +class DummyTransport: public ITransport { + + const uint8_t* _dummy_buf; + size_t _dummy_buf_size = 0; + size_t r_size = 0; + + public: + + DummyTransport(const uint8_t* buf, size_t size): _dummy_buf(buf), _dummy_buf_size(size){} + + void begin(){} + + bool available() override { + return _dummy_buf_size > 0; + } + + size_t write(const uint8_t* data, size_t size) override { + // Mock write + (void)data; + return size; + } + + size_t read(uint8_t* buffer, size_t size) override { + + size_t i; + for (i = 0; i < size; i++){ + if ((r_size + i) == _dummy_buf_size) break; + buffer[i] = _dummy_buf[r_size + i]; + delay(1); + } + + r_size = r_size + i; + return i; + + } + + size_t read_byte(uint8_t& r) override { + uint8_t b[1]; + if (read(b, 1) != 1){ + return 0; + }; + r = b[0]; + return 1; + } + +}; + +#endif //SERIALTRANSPORT_H \ No newline at end of file diff --git a/examples/decoder_tests/decoder_tests.ino b/examples/decoder_tests/decoder_tests.ino index ede3afb..9838829 100644 --- a/examples/decoder_tests/decoder_tests.ino +++ b/examples/decoder_tests/decoder_tests.ino @@ -1,4 +1,5 @@ #include +#include "DummyTransport.h" // Shorthand MsgPack::Packer packer; diff --git a/src/Arduino_RPClite.h b/src/Arduino_RPClite.h index 9a45c23..61b7d85 100644 --- a/src/Arduino_RPClite.h +++ b/src/Arduino_RPClite.h @@ -8,7 +8,6 @@ #include "Arduino.h" //#define HANDLE_RPC_ERRORS -#define DEBUG #include "transport.h" #include "client.h" #include "server.h" @@ -17,7 +16,6 @@ #include "decoder.h" #include "decoder_manager.h" -#include "DummyTransport.h" #include "SerialTransport.h" #endif //ARDUINO_RPCLITE_H From b8747f9ec1c14d36a12fec0e092d63b714c41a6f Mon Sep 17 00:00:00 2001 From: Lucio Rossi Date: Tue, 3 Jun 2025 17:08:23 +0200 Subject: [PATCH 4/4] fix: nested, mix-sized container unpacking fails --- src/rpclite_utils.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rpclite_utils.h b/src/rpclite_utils.h index 0e13e65..9f17a44 100644 --- a/src/rpclite_utils.h +++ b/src/rpclite_utils.h @@ -16,8 +16,7 @@ namespace detail { bool unpackObject(MsgPack::Unpacker& unpacker); bool unpackArray(MsgPack::Unpacker& unpacker, size_t& size) { - - static MsgPack::arr_size_t sz; + MsgPack::arr_size_t sz; unpacker.deserialize(sz); size = 0; @@ -34,7 +33,7 @@ bool unpackArray(MsgPack::Unpacker& unpacker, size_t& size) { } bool unpackMap(MsgPack::Unpacker& unpacker, size_t& size) { - static MsgPack::map_size_t sz; + MsgPack::map_size_t sz; unpacker.deserialize(sz); size = 0;