diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index 2f6289e..da9e4fe 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -30,9 +30,7 @@ jobs: LIBRARIES: | # Install the NetworkConfigurator library from the repository - source-path: ./ - - name: ArxContainer - - name: ArxTypeTraits - - name: DebugLog + - name: MsgPack SKETCH_PATHS: | - examples/decoder_tests - examples/dispatcher_example diff --git a/examples/decoder_example/DummyTransport.h b/examples/decoder_example/DummyTransport.h deleted file mode 100644 index dc3b3b7..0000000 --- a/examples/decoder_example/DummyTransport.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// 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_example/decoder_example.ino b/examples/decoder_example/decoder_example.ino deleted file mode 100644 index 794314b..0000000 --- a/examples/decoder_example/decoder_example.ino +++ /dev/null @@ -1,142 +0,0 @@ -#include -#include "DummyTransport.h" - -void blink_before(){ - digitalWrite(LED_BUILTIN, HIGH); - delay(100); - digitalWrite(LED_BUILTIN, LOW); - delay(100); - digitalWrite(LED_BUILTIN, HIGH); - delay(100); - digitalWrite(LED_BUILTIN, LOW); - delay(100); - digitalWrite(LED_BUILTIN, HIGH); - delay(100); - digitalWrite(LED_BUILTIN, LOW); - delay(100); -} - -MsgPack::Packer packer; -MsgPack::Unpacker unpacker; - -void print_buf() { - Serial.print("buf size: "); - Serial.print(packer.size()); - Serial.print(" - "); - - for (size_t i=0; i decoder(dummy_transport); - - while (!decoder.packet_incoming()){ - Serial.println("Packet not ready"); - decoder.advance(); - decoder.parse_packet(); - delay(100); - } - - if (decoder.packet_incoming()){ - Serial.print("packet incoming. type: "); - Serial.println(decoder.packet_type()); - } - - // NOTIFICATION - blink_before(); - packer.clear(); - packer.serialize(notify_sz, 2, "method", par_sz, 1.0, 2.0); - print_buf(); - - DummyTransport dummy_transport2(packer.data(), packer.size()); - RpcDecoder<> decoder2(dummy_transport2); - - while (!decoder2.packet_incoming()){ - Serial.println("Packet not ready"); - decoder2.advance(); - decoder2.parse_packet(); - delay(100); - } - - if (decoder2.packet_incoming()){ - Serial.print("packet incoming. type: "); - Serial.println(decoder2.packet_type()); - } - - // RESPONSE - blink_before(); - packer.clear(); - MsgPack::object::nil_t nil; - MsgPack::arr_size_t ret_sz(2); - packer.serialize(resp_sz, 1, 1, nil, ret_sz, 3.0, 2); - print_buf(); - - DummyTransport dummy_transport3(packer.data(), packer.size()); - RpcDecoder<> decoder3(dummy_transport3); - - while (!decoder3.packet_incoming()){ - Serial.println("Packet not ready"); - decoder3.advance(); - decoder3.parse_packet(); - delay(100); - } - - if (decoder3.packet_incoming()){ - Serial.print("packet incoming. type: "); - Serial.println(decoder3.packet_type()); - } - - // MIXED INCOMING RESPONSE AND REQUEST - Serial.println("-- Discard TEST --"); - blink_before(); - packer.clear(); - packer.serialize(resp_sz, 1, 1, nil, ret_sz, 3.0, 2); - Serial.print("1st packet size: "); - Serial.println(packer.size()); - packer.serialize(req_sz, 0, 1, "method", par_sz, 1.0, 2.0); - Serial.print("full size: "); - Serial.println(packer.size()); - print_buf(); - - DummyTransport dummy_transport4(packer.data(), packer.size()); - RpcDecoder<> decoder4(dummy_transport4); - - while (!decoder4.packet_incoming()){ - Serial.println("Packet not ready"); - decoder4.advance(); - decoder4.parse_packet(); - delay(100); - } - - while (decoder4.packet_incoming()){ - size_t removed = decoder4.discard_packet(); - Serial.print("Removed bytes: "); - Serial.println(removed); - decoder4.advance(); - decoder4.parse_packet(); - } - - Serial.println("-- END Discard TEST --"); - -} \ No newline at end of file diff --git a/examples/decoder_tests/decoder_tests.ino b/examples/decoder_tests/decoder_tests.ino index 9838829..3b6af6f 100644 --- a/examples/decoder_tests/decoder_tests.ino +++ b/examples/decoder_tests/decoder_tests.ino @@ -25,8 +25,7 @@ void runDecoderTest(const char* label) { while (!decoder.packet_incoming()) { Serial.println("Packet not ready"); - decoder.advance(); - decoder.parse_packet(); + decoder.decode(); delay(50); } @@ -34,8 +33,7 @@ void runDecoderTest(const char* label) { size_t removed = decoder.discard_packet(); Serial.print("Removed bytes: "); Serial.println(removed); - decoder.advance(); - decoder.parse_packet(); + decoder.decode(); } Serial.println("-- Done --\n"); diff --git a/examples/simple_client/simple_client.ino b/examples/simple_client/simple_client.ino deleted file mode 100644 index b1dd27b..0000000 --- a/examples/simple_client/simple_client.ino +++ /dev/null @@ -1,72 +0,0 @@ -#include - -SerialTransport transport(&Serial1); -RPCClient client(transport); - -void setup() { - Serial1.begin(115200); - transport.begin(); - pinMode(LED_BUILTIN, OUTPUT); - Serial.begin(9600); - while(!Serial); -} - -void blink_before(){ - digitalWrite(LED_BUILTIN, HIGH); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - delay(200); - digitalWrite(LED_BUILTIN, HIGH); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - delay(200); - digitalWrite(LED_BUILTIN, HIGH); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - delay(200); -} - -void loop() { - - blink_before(); - - int result; - bool ok = client.call("add", result, 15, 7); - - if (ok) { - Serial.print("Result: "); - Serial.println(result); - } - - // ok = client.call("divi", result, 2.0, 0.0); - // if (!ok) { - // Serial.println("Testing Server-side exception OK"); - // } - - // int rand_int; - // ok = client.call("get_rand", rand_int); - - // if (ok) { - // Serial.print("Random int from server: "); - // Serial.println(rand_int); - // } - - // client.notify("blink"); - // Serial.println("Sent a blink notification"); - - // int duration_ms = 100; - // client.notify("blink", duration_ms); - // Serial.println("Sent a 100ms blink notification"); - - // MsgPack::object::nil_t out; - // ok = client.call("blink", out); - // Serial.print("Sent a blink RPC -> "); - - // if (ok) { - // Serial.println("Server returns without issues"); - // } else { - // Serial.println("Server could not handle a notification as a call"); - // } - - delay(2000); -} \ No newline at end of file diff --git a/examples/unpacker_test/unpacker_test.ino b/examples/unpacker_test/unpacker_test.ino deleted file mode 100644 index 78b7a4b..0000000 --- a/examples/unpacker_test/unpacker_test.ino +++ /dev/null @@ -1,45 +0,0 @@ -#include - -void blink_before(){ - digitalWrite(LED_BUILTIN, HIGH); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - delay(200); - digitalWrite(LED_BUILTIN, HIGH); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - delay(200); - digitalWrite(LED_BUILTIN, HIGH); - delay(200); - digitalWrite(LED_BUILTIN, LOW); - delay(200); -} - -MsgPack::Packer packer; -MsgPack::Unpacker unpacker; - -void setup() { - Serial.begin(9600); -} - -void loop() { - - size_t expected_index_size = 5; - blink_before(); - MsgPack::arr_size_t req_sz(4); - MsgPack::arr_size_t par_sz(2); - packer.clear(); - packer.serialize(req_sz, 0, 1, "method", par_sz, 1.0, 2.0); - - Serial.print("packet size: "); - Serial.println(packer.size()); - - for (size_t i=1; i< packer.size(); i++){ - unpacker.clear(); - if (unpacker.feed(packer.data(), i) && unpacker.size() >= expected_index_size){ - Serial.println("problem "); - Serial.println(i); - } - } - -} \ No newline at end of file diff --git a/library.json b/library.json index b2a0cc7..cd9a34e 100644 --- a/library.json +++ b/library.json @@ -17,8 +17,6 @@ "platforms": "*", "dependencies": { - "hideakitai/ArxContainer": ">=0.6.0", - "hideakitai/ArxTypeTraits": "*", - "hideakitai/DebugLog": ">=0.8.1" + "hideakitai/MsgPack": ">=0.4.2" } } diff --git a/library.properties b/library.properties index 28a61c9..54cfdde 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=allows to create a client/server architecture using MessagePack as the category=Communication url=https://www.arduino.cc/ architectures=* -depends=ArxContainer (>=0.6.0), ArxTypeTraits, DebugLog (>=0.8.1) +depends=MsgPack (>=0.4.2) diff --git a/src/MsgPack.h b/src/MsgPack.h deleted file mode 100644 index 8499f3a..0000000 --- a/src/MsgPack.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#ifndef HT_SERIAL_MSGPACK_H -#define HT_SERIAL_MSGPACK_H - -#include -#ifdef MSGPACK_DEBUGLOG_ENABLE -#include -#else -#include -#endif - -#include "MsgPack/Types.h" -#include "MsgPack/Packer.h" -#include "MsgPack/Unpacker.h" -#include "MsgPack/Utility.h" - -namespace MsgPack = arduino::msgpack; - -#include - -#endif // ARDUINOMSGPACK_H diff --git a/src/MsgPack/Packer.h b/src/MsgPack/Packer.h deleted file mode 100644 index c585e09..0000000 --- a/src/MsgPack/Packer.h +++ /dev/null @@ -1,1032 +0,0 @@ -#pragma once -#ifndef HT_SERIAL_MSGPACK_PACKER_H -#define HT_SERIAL_MSGPACK_PACKER_H - -#include -#include -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else // Do not have libstdc++11 -// containers are disabled -#endif - -#ifdef TEENSYDUINO -#include "util/TeensyDirtySTLErrorSolution/TeensyDirtySTLErrorSolution.h" -#endif // TEENSYDUINO - -#include "Types.h" -#include "Unpacker.h" -#include - -namespace arduino { -namespace msgpack { - - class Packer { - bin_t buffer; - size_t n_indices {0}; - - public: - void reserve_buffer(const size_t size) { - buffer.reserve(size); - } - - template - auto serialize(const First& first, Rest&&... rest) -> typename std::enable_if< - !std::is_pointer::value || std::is_same::value -#ifdef ARDUINO - || std::is_same::value -#endif - >::type { - pack(first); - serialize(std::forward(rest)...); - } - - void serialize() {} - - template - void serialize(const arr_size_t& arr_size, Args&&... args) { - packArraySize(arr_size.size()); - serialize(std::forward(args)...); - } - - template - void serialize(const map_size_t& map_size, Args&&... args) { - packMapSize(map_size.size()); - serialize(std::forward(args)...); - } - -#ifdef ARDUINOJSON_VERSION - - //! Note: ArduinoJson cannot handle Arduino's String class correctly. - //! So the external buffer size is required. - void serialize_arduinojson(const JsonDocument& doc, const size_t num_max_string_type = 32) { - const size_t size = measureMsgPack(doc); - uint8_t* data = new uint8_t[size + num_max_string_type]; - serializeMsgPack(doc, data, size + num_max_string_type); - packRawBytes(data, size); - // TODO: smarter way to calcurate size of indices? - Unpacker unpacker; - unpacker.feed(data, size); - n_indices += unpacker.size(); - delete[] data; - } - - template - void serialize(const StaticJsonDocument& doc, const size_t num_max_string_type = 32) { - serialize_arduinojson(doc, num_max_string_type); - } - void serialize(const DynamicJsonDocument& doc, const size_t num_max_string_type = 32) { - serialize_arduinojson(doc, num_max_string_type); - } - -#endif // ARDUINOJSON_VERSION - - template - void to_array(Args&&... args) { - serialize(arr_size_t(sizeof...(args)), std::forward(args)...); - } - - template - void to_map(Args&&... args) { - size_t size = sizeof...(args); - if ((size % 2) == 0) - serialize(map_size_t(size / 2), std::forward(args)...); - else - LOG_ERROR(F("serialize arg size must be even for map:"), size); - } - - const bin_t& packet() const { - return buffer; - } - const uint8_t* data() const { - return buffer.data(); - } - size_t size() const { - return buffer.size(); - } - size_t indices() const { - return n_indices; - } - void clear() { - buffer.clear(); - n_indices = 0; - } - - ///////////////////////////////////////////////// - // ---------- msgpack type adaptors ---------- // - ///////////////////////////////////////////////// - - // adaptation of types to msgpack - // https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor - - // ---------- NIL format family ---------- - // - N/A - - template - auto pack(const T& n) -> typename std::enable_if< - std::is_same::value || std::is_same::value>::type { - (void)n; - packNil(); - } - - // ---------- BOOL format family ---------- - // - bool - - template - auto pack(const T& b) -> typename std::enable_if::value>::type { - packBool(b); - } - - // ---------- INT format family ---------- - // - char (signed/unsigned) - // - ints (signed/unsigned) - - template - auto pack(const T& value) -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value>::type { - packInteger(value); - } - - // ---------- FLOAT format family ---------- - // - float - // - double - - template - auto pack(const T& value) -> - typename std::enable_if::value && std::is_floating_point::value>::type { - packFloat(value); - } - - // ---------- STRING format family ---------- - // - char* - // - char[] - // - std::string - - void pack(const str_t& str) { - packString(str, getStringSize(str)); - } - void pack(const char* str) { - packString(str, getStringSize(str)); - } - void pack(const char* str, const size_t size) { - packString(str, size); - } -#ifdef ARDUINO - void pack(const __FlashStringHelper* str) { - packString(str, getStringSize(str)); - } -#endif - - // ---------- BIN format family ---------- - // - unsigned char* - // - unsigned char[] - // - std::vector - // - std::vector - // - std::array - // - std::array - - void pack(const uint8_t* bin, const size_t size) { - packBinary(bin, size); - } - - void pack(const bin_t& bin) { - packBinary((const uint8_t*)bin.data(), bin.size()); - } - - void pack(const bin_t& bin) { - packBinary(bin.data(), bin.size()); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - void pack(const std::array& bin) { - packBinary((const uint8_t*)bin.data(), bin.size()); - } - - template - void pack(const std::array& bin) { - packBinary(bin.data(), bin.size()); - } - -#endif // have libstdc++11 - - // ---------- ARRAY format family ---------- - // - T[] - // - std::vector - // - std::array - // - std::deque - // - std::pair - // - std::tuple - // - std::list - // - std::forward_list - // - std::set - // - std::multiset - // - std::unordered_set * - // - std::unordered_multiset * - // * : not supported in arduino - - template - auto pack(const T* arr, const size_t size) -> - typename std::enable_if::value && !std::is_same::value>::type { - packArraySize(size); - for (size_t i = 0; i < size; ++i) pack(arr[i]); - } - - template - auto pack(const arr_t& arr) -> - typename std::enable_if::value && !std::is_same::value>::type { - packArrayContainer(arr); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto pack(const std::array& arr) -> - typename std::enable_if::value && !std::is_same::value>::type { - packArrayContainer(arr); - } - - template - void pack(const std::deque& arr) { - packArrayContainer(arr); - } - - template - void pack(const std::pair& arr) { - packArraySize(2); - pack(arr.first); - pack(arr.second); - } - -#endif // have libstdc++11 - - template - auto pack(const std::tuple& t) -> typename std::enable_if < I::type { - if (I == 0) packArraySize(sizeof...(Ts)); - pack(std::get(t)); - pack(t); - } - - template - auto pack(const std::tuple&) -> typename std::enable_if::type {} - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - void pack(const std::list& arr) { - packArrayContainer(arr); - } - - template - void pack(const std::forward_list& arr) { - auto size = std::distance(arr.begin(), arr.end()); - packArraySize(size); - for (const auto& a : arr) pack(a); - } - - template - void pack(const std::set& arr) { - packArrayContainer(arr); - } - - template - void pack(const std::multiset& arr) { - packArrayContainer(arr); - } - - template - void pack(const std::unordered_set& arr) { - packArrayContainer(arr); - } - - template - void pack(const std::unordered_multiset& arr) { - packArrayContainer(arr); - } - -#endif // have libstdc++11 - - // ---------- MAP format family ---------- - // - std::map - // - std::multimap - // - std::unordered_map * - // - std::unordered_multimap * - // * : not supported in arduino - - template - void pack(const map_t& mp) { - packMapContainer(mp); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - void pack(const std::multimap& mp) { - packMapContainer(mp); - } - - template - void pack(const std::unordered_map& mp) { - packMapContainer(mp); - } - - template - void pack(const std::unordered_multimap& mp) { - packMapContainer(mp); - } - -#endif // have libstdc++11 - - // ---------- EXT format family ---------- - - void pack(const object::ext& e) { - packExt(e); - } - - // ---------- TIMESTAMP format family ---------- - - void pack(const object::timespec& t) { - packTimestamp(t); - } - - // ---------- CUSTOM format ---------- - - template - auto pack(const C& c) -> typename std::enable_if::value>::type { - c.to_msgpack(*this); - } - - // ---------- Array/Map Size format ---------- - - void pack(const arr_size_t& t) { - packArraySize(t.size()); - } - - void pack(const map_size_t& t) { - packMapSize(t.size()); - } - - ///////////////////////////////////////////////////// - // ---------- msgpack types abstraction ---------- // - /////////////////////////////////////////............ - - // ---------- INT format family ---------- - - template - auto packInteger(const T& value) -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value>::type { - if (value >= 0) { - if ((uint64_t)value < (uint64_t)BitMask::UINT7) - packUInt7(value); - else if ((uint64_t)value <= (uint64_t)std::numeric_limits::max()) - packUInt8(value); - else if ((uint64_t)value <= (uint64_t)std::numeric_limits::max()) - packUInt16(value); - else if ((uint64_t)value <= (uint64_t)std::numeric_limits::max()) - packUInt32(value); - else - packUInt64(value); - } else { - if ((int64_t)value > -(int64_t)BitMask::INT5) - packInt5(value); - else if ((int64_t)value >= (int64_t)std::numeric_limits::min()) - packInt8(value); - else if ((int64_t)value >= (int64_t)std::numeric_limits::min()) - packInt16(value); - else if ((int64_t)value >= (int64_t)std::numeric_limits::min()) - packInt32(value); - else - packInt64(value); - } - } - - // ---------- FLOAT format family ---------- - - template - auto packFloat(const T& value) -> - typename std::enable_if::value && std::is_floating_point::value>::type { - if (sizeof(T) == sizeof(float)) - packFloat32(value); - else - packFloat64(value); - } - - // ---------- STR format family ---------- - - template - void packString(const T& str) { - packString(str, getStringSize(str)); - } - - template - void packString(const T& str, const size_t len) { - if (len <= (size_t)BitMask::STR5) - packString5(str, len); - else if (len <= std::numeric_limits::max()) - packString8(str, len); - else if (len <= std::numeric_limits::max()) - packString16(str, len); - else if (len <= std::numeric_limits::max()) - packString32(str, len); - } - - // ---------- BIN format family ---------- - - void packBinary(const uint8_t* bin, const size_t size) { - if (size <= std::numeric_limits::max()) - packBinary8(bin, (uint8_t)size); - else if (size <= std::numeric_limits::max()) - packBinary16(bin, (uint16_t)size); - else if (size <= std::numeric_limits::max()) - packBinary32(bin, (uint32_t)size); - } - - // ---------- ARRAY format family ---------- - - void packArraySize(const size_t size) { - if (size < (1 << 4)) - packArraySize4((uint8_t)size); - else if (size <= std::numeric_limits::max()) - packArraySize16((uint16_t)size); - else if (size <= std::numeric_limits::max()) - packArraySize32((uint32_t)size); - } - - // ---------- MAP format family ---------- - - void packMapSize(const size_t size) { - if (size < (1 << 4)) - packMapSize4((uint8_t)size); - else if (size <= std::numeric_limits::max()) - packMapSize16((uint16_t)size); - else if (size <= std::numeric_limits::max()) - packMapSize32((uint32_t)size); - } - - // ---------- EXT format family ---------- - - template - auto packFixExt(const int8_t type, const T value) -> - typename std::enable_if::value>::type { - size_t size = sizeof(T); - if (size == sizeof(uint8_t)) - packFixExt1(type, value); - else if (size == sizeof(uint16_t)) - packFixExt2(type, value); - else if (size == sizeof(uint32_t)) - packFixExt4(type, value); - else if (size == sizeof(uint64_t)) - packFixExt8(type, value); - } - - void packFixExt(const int8_t type, const uint64_t value_h, const uint64_t value_l) { - packFixExt16(type, value_h, value_l); - } - - void packFixExt(const int8_t type, const uint8_t* ptr, const uint8_t size) { - if (size == 0) return; - if (size == sizeof(uint8_t)) - packFixExt1(type, (uint8_t) * (ptr)); - else if (size == sizeof(uint16_t)) - packFixExt2(type, ptr); - else if (size <= sizeof(uint32_t)) - packFixExt4(type, ptr); - else if (size <= sizeof(uint64_t)) - packFixExt8(type, ptr); - else if (size <= sizeof(uint64_t) * 2) - packFixExt16(type, ptr); - } - - void packFixExt(const int8_t type, const uint16_t* ptr, const uint8_t size) { - packFixExt(type, (const uint8_t*)ptr, size); - } - - void packFixExt(const int8_t type, const uint32_t* ptr, const uint8_t size) { - packFixExt(type, (const uint8_t*)ptr, size); - } - - void packFixExt(const int8_t type, const uint64_t* ptr, const uint8_t size) { - packFixExt(type, (const uint8_t*)ptr, size); - } - - template - auto packExt(const int8_t type, const T* ptr, const U size) -> - typename std::enable_if::value && std::is_integral::value>::type { - if (size <= sizeof(uint64_t) * 2) - packFixExt(type, ptr, size); - else { - if (size <= std::numeric_limits::max()) - packExtSize8(type, size); - else if (size <= std::numeric_limits::max()) - packExtSize16(type, size); - else if (size <= std::numeric_limits::max()) - packExtSize32(type, size); - packRawBytes((const uint8_t*)ptr, size); - } - } - - void packExt(const object::ext& e) { - packExt(e.type(), e.data(), e.size()); - } - - // ---------- TIMESTAMP format family ---------- - - void packTimestamp(const object::timespec& time) { - if ((time.tv_sec >> 34) == 0) { - uint64_t data64 = ((uint64_t)time.tv_nsec << 34) | time.tv_sec; - if ((data64 & 0xffffffff00000000L) == 0) - packTimestamp32((uint32_t)data64); - else - packTimestamp64(data64); - } else - packTimestamp96(time.tv_sec, time.tv_nsec); - } - - ///////////////////////////////////////// - // ---------- msgpack types ---------- // - ///////////////////////////////////////// - - // MessagePack Specification - // https://github.com/msgpack/msgpack/blob/master/spec.md - - // ---------- NIL format family ---------- - - void packNil() { - packRawByte(Type::NIL); - ++n_indices; - } - - void packNil(const object::nil_t& n) { - (void)n; - packRawByte(Type::NIL); - ++n_indices; - } - - // ---------- BOOL format family ---------- - - void packBool(const bool b) { - packRawByte((uint8_t)Type::BOOL | ((uint8_t)b & (uint8_t)BitMask::BOOL)); - ++n_indices; - } - - // ---------- INT format family ---------- - - void packUInt7(const uint8_t value) { - packRawByte((uint8_t)Type::UINT7 | (value & (uint8_t)BitMask::UINT7)); - ++n_indices; - } - - void packUInt8(const uint8_t value) { - packRawByte(Type::UINT8); - packRawByte(value); - ++n_indices; - } - - void packUInt16(const uint16_t value) { - packRawByte(Type::UINT16); - packRawReversed(value); - ++n_indices; - } - - void packUInt32(const uint32_t value) { - packRawByte(Type::UINT32); - packRawReversed(value); - ++n_indices; - } - - void packUInt64(const uint64_t value) { - packRawByte(Type::UINT64); - packRawReversed(value); - ++n_indices; - } - - void packInt5(const int8_t value) { - packRawByte((uint8_t)Type::INT5 | ((uint8_t)value & (uint8_t)BitMask::INT5)); - ++n_indices; - } - - void packInt8(const int8_t value) { - packRawByte(Type::INT8); - packRawByte(value); - ++n_indices; - } - - void packInt16(const int16_t value) { - packRawByte(Type::INT16); - packRawReversed(value); - ++n_indices; - } - - void packInt32(const int32_t value) { - packRawByte(Type::INT32); - packRawReversed(value); - ++n_indices; - } - - void packInt64(const int64_t value) { - packRawByte(Type::INT64); - packRawReversed(value); - ++n_indices; - } - - // ---------- FLOAT format family ---------- - - void packFloat32(const float value) { - packRawByte(Type::FLOAT32); - packRawReversed(value); - ++n_indices; - } - - void packFloat64(const double value) { -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - packRawByte(Type::FLOAT64); - packRawReversed(value); - ++n_indices; -#else - packFloat32((const float)value); // Uno, etc. does not support double -#endif // have libstdc++11 - } - - // ---------- STR format family ---------- - - void packString5(const str_t& str) { - packString5(str, getStringSize(str)); - } - void packString5(const str_t& str, const size_t len) { - packString5(str.c_str(), len); - } - void packString5(const char* value) { - packString5(value, getStringSize(value)); - } - void packString5(const char* value, const size_t len) { - packRawByte((uint8_t)Type::STR5 | ((uint8_t)len & (uint8_t)BitMask::STR5)); - packRawBytes(value, len); - ++n_indices; - } - - void packString8(const str_t& str) { - packString8(str, getStringSize(str)); - } - void packString8(const str_t& str, const size_t len) { - packString8(str.c_str(), len); - } - void packString8(const char* value) { - packString8(value, getStringSize(value)); - } - void packString8(const char* value, const size_t len) { - packRawByte(Type::STR8); - packRawByte((uint8_t)len); - packRawBytes(value, len); - ++n_indices; - } - - void packString16(const str_t& str) { - packString16(str, getStringSize(str)); - } - void packString16(const str_t& str, const size_t len) { - packString16(str.c_str(), len); - } - void packString16(const char* value) { - packString16(value, getStringSize(value)); - } - void packString16(const char* value, const size_t len) { - packRawByte(Type::STR16); - packRawReversed((uint16_t)len); - packRawBytes(value, len); - ++n_indices; - } - - void packString32(const str_t& str) { - packString32(str, getStringSize(str)); - } - void packString32(const str_t& str, const size_t len) { - packString32(str.c_str(), len); - } - void packString32(const char* value) { - packString32(value, getStringSize(value)); - } - void packString32(const char* value, const size_t len) { - packRawByte(Type::STR32); - packRawReversed((uint32_t)len); - packRawBytes(value, len); - ++n_indices; - } - -#ifdef ARDUINO - - void packString5(const __FlashStringHelper* str) { - packString5(str, getStringSize(str)); - } - void packString5(const __FlashStringHelper* str, const size_t len) { - packRawByte((uint8_t)Type::STR5 | ((uint8_t)len & (uint8_t)BitMask::STR5)); - packFlashString(str); - ++n_indices; - } - - void packString8(const __FlashStringHelper* str) { - packString8(str, getStringSize(str)); - } - void packString8(const __FlashStringHelper* str, const size_t len) { - packRawByte(Type::STR8); - packRawByte((uint8_t)len); - packFlashString(str); - ++n_indices; - } - - void packString16(const __FlashStringHelper* str) { - packString16(str, getStringSize(str)); - } - void packString16(const __FlashStringHelper* str, const size_t len) { - packRawByte(Type::STR16); - packRawReversed((uint16_t)len); - packFlashString(str); - ++n_indices; - } - - void packString32(const __FlashStringHelper* str) { - packString32(str, getStringSize(str)); - } - void packString32(const __FlashStringHelper* str, const size_t len) { - packRawByte(Type::STR32); - packRawReversed((uint32_t)len); - packFlashString(str); - ++n_indices; - } - -#endif - - // ---------- BIN format family ---------- - - void packBinary8(const uint8_t* value, const uint8_t size) { - packRawByte(Type::BIN8); - packRawByte(size); - packRawBytes(value, size); - ++n_indices; - } - - void packBinary16(const uint8_t* value, const uint16_t size) { - packRawByte(Type::BIN16); - packRawReversed(size); - packRawBytes(value, size); - ++n_indices; - } - - void packBinary32(const uint8_t* value, const uint32_t size) { - packRawByte(Type::BIN32); - packRawReversed(size); - packRawBytes(value, size); - ++n_indices; - } - - // ---------- ARRAY format family ---------- - - void packArraySize4(const uint8_t value) { - packRawByte((uint8_t)Type::ARRAY4 | (value & (uint8_t)BitMask::ARRAY4)); - ++n_indices; - } - - void packArraySize16(const uint16_t value) { - packRawByte(Type::ARRAY16); - packRawReversed(value); - ++n_indices; - } - - void packArraySize32(const uint32_t value) { - packRawByte(Type::ARRAY32); - packRawReversed(value); - ++n_indices; - } - - // ---------- MAP format family ---------- - - void packMapSize4(const uint8_t value) { - packRawByte((uint8_t)Type::MAP4 | (value & (uint8_t)BitMask::MAP4)); - ++n_indices; - } - - void packMapSize16(const uint16_t value) { - packRawByte(Type::MAP16); - packRawReversed(value); - ++n_indices; - } - - void packMapSize32(const uint32_t value) { - packRawByte(Type::MAP32); - packRawReversed(value); - ++n_indices; - } - - // ---------- EXT format family ---------- - - void packFixExt1(const int8_t type, const uint8_t value) { - packRawByte(Type::FIXEXT1); - packRawByte((uint8_t)type); - packRawByte(value); - ++n_indices; - } - - void packFixExt2(const int8_t type, const uint16_t value) { - packRawByte(Type::FIXEXT2); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)&value, sizeof(value)); - ++n_indices; - } - - void packFixExt2(const int8_t type, const uint8_t* ptr) { - packRawByte(Type::FIXEXT2); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)ptr, 2); - ++n_indices; - } - - void packFixExt2(const int8_t type, const uint16_t* ptr) { - packFixExt2(type, (const uint8_t*)ptr); - } - - void packFixExt4(const int8_t type, const uint32_t value) { - packRawByte(Type::FIXEXT4); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)&value, sizeof(value)); - ++n_indices; - } - - void packFixExt4(const int8_t type, const uint8_t* ptr) { - packRawByte(Type::FIXEXT4); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)ptr, 4); - ++n_indices; - } - - void packFixExt4(const int8_t type, const uint32_t* ptr) { - packFixExt4(type, (const uint8_t*)ptr); - } - - void packFixExt8(const int8_t type, const uint64_t value) { - packRawByte(Type::FIXEXT8); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)&value, sizeof(value)); - ++n_indices; - } - - void packFixExt8(const int8_t type, const uint8_t* ptr) { - packRawByte(Type::FIXEXT8); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)ptr, 8); - ++n_indices; - } - - void packFixExt8(const int8_t type, const uint64_t* ptr) { - packFixExt8(type, (const uint8_t*)ptr); - } - - void packFixExt16(const int8_t type, const uint64_t value_h, const uint64_t value_l) { - packRawByte(Type::FIXEXT16); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)&value_h, sizeof(value_h)); - packRawBytes((const uint8_t*)&value_l, sizeof(value_l)); - ++n_indices; - } - - void packFixExt16(const int8_t type, const uint8_t* ptr) { - packRawByte(Type::FIXEXT16); - packRawByte((uint8_t)type); - packRawBytes((const uint8_t*)ptr, 16); - ++n_indices; - } - - void packFixExt16(const int8_t type, const uint64_t* ptr) { - packFixExt16(type, (const uint8_t*)ptr); - } - - void packExtSize8(const int8_t type, const uint8_t size) { - packRawByte(Type::EXT8); - packRawByte(size); - packRawByte((uint8_t)type); - ++n_indices; - } - - void packExtSize16(const int8_t type, const uint16_t size) { - packRawByte(Type::EXT16); - packRawReversed(size); - packRawByte((uint8_t)type); - ++n_indices; - } - - void packExtSize32(const int8_t type, const uint32_t size) { - packRawByte(Type::EXT32); - packRawReversed(size); - packRawByte((uint8_t)type); - ++n_indices; - } - - // ---------- TIMESTAMP format family ---------- - - void packTimestamp32(const uint32_t unix_time_sec) { - packRawByte(Type::FIXEXT4); - packRawByte((uint8_t)-1); - packRawReversed(unix_time_sec); - ++n_indices; - } - - void packTimestamp64(const uint64_t unix_time) { - packRawByte(Type::FIXEXT8); - packRawByte((uint8_t)-1); - packRawReversed(unix_time); - ++n_indices; - } - - void packTimestamp64(const uint64_t unix_time_sec, const uint32_t unix_time_nsec) { - uint64_t utime = ((unix_time_nsec & 0x00000003FFFFFFFF) << 34) | (uint64_t)(unix_time_sec & 0x3FFFFFFFF); - packTimestamp64(utime); - } - - void packTimestamp96(const int64_t unix_time_sec, const uint32_t unix_time_nsec) { - packExtSize8(-1, 12); - packRawReversed(unix_time_nsec); - packRawReversed(unix_time_sec); - ++n_indices; - } - - private: - void packRawByte(const uint8_t value) { - buffer.emplace_back(value); - } - - void packRawByte(const Type& type) { - buffer.emplace_back((uint8_t)type); - } - - void packRawBytes(const uint8_t* value, const size_t size) { - for (size_t i = 0; i < size; ++i) buffer.emplace_back(value[i]); - } - - void packRawBytes(const char* value, const size_t size) { - for (size_t i = 0; i < size; ++i) buffer.emplace_back(value[i]); - } - - template - void packRawReversed(const DataType& value) { - const auto size = sizeof(DataType); - for (size_t i = 0; i < size; ++i) { - buffer.emplace_back(((uint8_t*)&value)[size - 1 - i]); - } - } - - template - void packArrayContainer(const A& arr) { - packArraySize(arr.size()); - for (const auto& a : arr) pack(a); - } - - template - void packMapContainer(const M& mp) { - packMapSize(mp.size()); - for (const auto& m : mp) { - pack(m.first); - pack(m.second); - } - } - - size_t getStringSize(const str_t& str) const { - return str.length(); - } - - size_t getStringSize(const char* str) const { - return strlen(str); - } - -#ifdef ARDUINO - - size_t getStringSize(const __FlashStringHelper* str) const { - return strlen_P((const char*)str); - } - - void packFlashString(const __FlashStringHelper* str) { - char* p = (char*)str; - while (1) { - uint8_t c = pgm_read_byte(p++); - if (c == 0) break; - packRawByte(c); - } - } - -#endif - }; - -} // namespace msgpack -} // namespace arduino - -#endif // HT_SERIAL_MSGPACK_PACKER_H diff --git a/src/MsgPack/Types.h b/src/MsgPack/Types.h deleted file mode 100644 index 837c54c..0000000 --- a/src/MsgPack/Types.h +++ /dev/null @@ -1,289 +0,0 @@ -#pragma once -#ifndef HT_SERIAL_MSGPACK_TYPES_H -#define HT_SERIAL_MSGPACK_TYPES_H - -#include -#ifdef ARDUINO -#include -#else -#include -#endif - -#ifdef INT5 -// avoid conflict with interrrupt macro on e.g. Arduino Mega. This -// should not break code that rely on this constant, by keeping the -// value available as a C++-level constant. This first allocates a -// temporary constant, to capture the value before undeffing, and -// then defines the actual INT5 constant. Finally, INT5 is redefined -// as itself to make sure #ifdef INT5 still works. -static constexpr uint8_t INT5_TEMP_VALUE = INT5; -#undef INT5 -static constexpr uint8_t INT5 = INT5_TEMP_VALUE; -#define INT5 INT5 -#endif - -#include -#include - -namespace arduino { -namespace msgpack { - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - using idx_t = std::vector; - template - using arr_t = std::vector; - template - using fix_arr_t = std::array; - template - using map_t = std::map; - template - using bin_t = std::vector< - typename std::enable_if::value || std::is_same::value, T>::type, - std::allocator >; - -#else // Do not have libstdc++11 - -#ifndef MSGPACK_MAX_PACKET_BYTE_SIZE -#define MSGPACK_MAX_PACKET_BYTE_SIZE 128 -#endif // MSGPACK_MAX_PACKET_BYTE_SIZE -#ifndef MSGPACK_MAX_ARRAY_SIZE -#define MSGPACK_MAX_ARRAY_SIZE 8 -#endif // MSGPACK_MAX_ARRAY_SIZE -#ifndef MSGPACK_MAX_MAP_SIZE -#define MSGPACK_MAX_MAP_SIZE 8 -#endif // MSGPACK_MAX_MAP_SIZE -#ifndef MSGPACK_MAX_OBJECT_SIZE -#define MSGPACK_MAX_OBJECT_SIZE 32 -#endif // MSGPACK_MAX_OBJECT_SIZE - - using idx_t = arx::stdx::vector; - template - using arr_t = arx::stdx::vector; - template - using fix_arr_t = arx::stdx::array; - template - using map_t = arx::stdx::map; - template - using bin_t = arx::stdx::vector::value || std::is_same::value, T>::type, N>; - -#endif // Do not have libstdc++11 - -#ifdef ARDUINO - using str_t = String; -#else - using str_t = std::string; -#ifndef F - inline const char* F(const char* c) { - return c; - } -#endif -#endif - - namespace type { - class ArraySize { - size_t sz; - - public: - explicit ArraySize(const size_t size = 0) : sz(size) {} - size_t size() const { - return sz; - } - void size(const size_t s) { - sz = s; - } - }; - class MapSize { - size_t sz; - - public: - explicit MapSize(const size_t size = 0) : sz(size) {} - size_t size() const { - return sz; - } - void size(const size_t s) { - sz = s; - } - }; - } // namespace type - - using arr_size_t = type::ArraySize; - using map_size_t = type::MapSize; - - namespace object { - struct nil_t { - bool is_nil {false}; - nil_t& operator=(const nil_t& rhs) { - this->is_nil = rhs.is_nil; - return *this; - } - nil_t& operator=(const bool b) { - this->is_nil = b; - return *this; - } - bool operator()() const { - return this->is_nil; - } - bool operator==(const nil_t& x) { - return (*this)() == x(); - } - bool operator!=(const nil_t& x) { - return !(*this == x); - } - }; - - class ext { - bin_t m_data; - - public: - ext() : m_data() {} - ext(int8_t t, const uint8_t* p, uint32_t s) { - m_data.reserve(static_cast(s) + 1); - m_data.push_back(static_cast(t)); - m_data.insert(m_data.end(), p, p + s); - } - ext(int8_t t, uint32_t s) { - m_data.resize(static_cast(s) + 1); - m_data[0] = static_cast(t); - } - int8_t type() const { - return static_cast(m_data[0]); - } - const uint8_t* data() const { - return &(m_data[0]) + 1; - } - uint8_t* data() { - return &(m_data[0]) + 1; - } - uint32_t size() const { - return static_cast(m_data.size()) - 1; - } - bool operator==(const ext& x) const { - return m_data == x.m_data; - } - bool operator!=(const ext& x) const { - return !(*this == x); - } - }; - - struct timespec { - int64_t tv_sec; // seconds - uint32_t tv_nsec; // nanoseconds - - bool operator==(const timespec& x) const { - return (tv_sec == x.tv_sec) && (tv_nsec == x.tv_nsec); - } - bool operator!=(const timespec& x) const { - return !(*this == x); - } - bool operator<(const timespec& x) const { - if (tv_sec < x.tv_sec) - return true; - else if (tv_sec > x.tv_sec) - return false; - else - return tv_nsec < x.tv_nsec; - } - bool operator>(const timespec& x) const { - return (*this != x) && (*this < x); - } - }; - - } // namespace object - - enum class Type : uint8_t { - NA = 0xC1, // never used - NIL = 0xC0, - BOOL = 0xC2, - UINT7 = 0x00, // same as POSITIVE_FIXINT - UINT8 = 0xCC, - UINT16 = 0xCD, - UINT32 = 0xCE, - UINT64 = 0xCF, - INT5 = 0xE0, // same as NEGATIVE_FIXINT - INT8 = 0xD0, - INT16 = 0xD1, - INT32 = 0xD2, - INT64 = 0xD3, - FLOAT32 = 0xCA, - FLOAT64 = 0xCB, - STR5 = 0xA0, // same as FIXSTR - STR8 = 0xD9, - STR16 = 0xDA, - STR32 = 0xDB, - BIN8 = 0xC4, - BIN16 = 0xC5, - BIN32 = 0xC6, - ARRAY4 = 0x90, // same as FIXARRAY - ARRAY16 = 0xDC, - ARRAY32 = 0xDD, - MAP4 = 0x80, // same as FIXMAP - MAP16 = 0xDE, - MAP32 = 0xDF, - FIXEXT1 = 0xD4, - FIXEXT2 = 0xD5, - FIXEXT4 = 0xD6, - FIXEXT8 = 0xD7, - FIXEXT16 = 0xD8, - EXT8 = 0xC7, - EXT16 = 0xC8, - EXT32 = 0xC9, - TIMESTAMP32 = 0xD6, - TIMESTAMP64 = 0xD7, - TIMESTAMP96 = 0xC7, - - POSITIVE_FIXINT = 0x00, - NEGATIVE_FIXINT = 0xE0, - FIXSTR = 0xA0, - FIXARRAY = 0x90, - FIXMAP = 0x80, - }; - - enum class BitMask : uint8_t { - BOOL = 0x01, - POSITIVE_FIXINT = 0x7F, - UINT7 = 0x7F, // same as POSITIVE_FIXINT - NEGATIVE_FIXINT = 0x1F, - INT5 = 0x1F, // same as NEGATIVE_FIXINT - FIXSTR = 0x1F, - STR5 = 0x1F, // same as FIXSTR - FIXARRAY = 0x0F, - ARRAY4 = 0x0F, // same as FIXARRAY - FIXMAP = 0x0F, - MAP4 = 0x0F, // same as FIXMAP - }; - - template - using has_to_msgpack_impl = typename std::enable_if< - std::is_same::value>::type; - template - using has_to_msgpack = arx::is_detected; - - template - using has_from_msgpack_impl = typename std::enable_if< - std::is_same::value>::type; - template - using has_from_msgpack = arx::is_detected; - -} // namespace msgpack -} // namespace arduino - -#define MSGPACK_DEFINE(...) \ - void to_msgpack(MsgPack::Packer& packer) const { \ - packer.to_array(__VA_ARGS__); \ - } \ - void from_msgpack(MsgPack::Unpacker& unpacker) { \ - unpacker.from_array(__VA_ARGS__); \ - } - -#define MSGPACK_DEFINE_MAP(...) \ - void to_msgpack(MsgPack::Packer& packer) const { \ - packer.to_map(__VA_ARGS__); \ - } \ - void from_msgpack(MsgPack::Unpacker& unpacker) { \ - unpacker.from_map(__VA_ARGS__); \ - } - -#define MSGPACK_BASE(base) (*const_cast(static_cast(this))) - -#endif // HT_SERIAL_MSGPACK_TYPES_H diff --git a/src/MsgPack/Unpacker.h b/src/MsgPack/Unpacker.h deleted file mode 100644 index 512601e..0000000 --- a/src/MsgPack/Unpacker.h +++ /dev/null @@ -1,2006 +0,0 @@ -#pragma once -#ifndef HT_SERIAL_MSGPACK_UNPACKER_H -#define HT_SERIAL_MSGPACK_UNPACKER_H - -#include -#include -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#else // Do not have libstdc++11 -// containers are disabled -#endif -#ifdef TEENSYDUINO -#include "util/TeensyDirtySTLErrorSolution/TeensyDirtySTLErrorSolution.h" -#endif // TEENSYDUINO - -#include "Types.h" -#include - -namespace arduino { -namespace msgpack { - - class Unpacker { - uint8_t* raw_data {nullptr}; - idx_t indices; - size_t curr_index {0}; - bool b_size_matched {false}; - bool b_decode_success {false}; - -#define MSGPACK_DECODABLE_CHECK(T) \ - if (curr_index >= indices.size()) { \ - LOG_ERROR(F("no more decodable objects")); \ - b_decode_success = false; \ - return T(); \ - } else { \ - b_decode_success = true; \ - } - - public: - void reserve_indices(const size_t size) { - indices.reserve(size); - } - - bool feed(const uint8_t* data, const size_t size) { - raw_data = (uint8_t*)data; - for (size_t i = 0; i < size; i += getElementSize(indices.size() - 1)) indices.emplace_back(i); - const size_t decoded_size = indices.back() + getElementSize(indices.size() - 1); - b_size_matched = (size == decoded_size); - if (!b_size_matched) LOG_ERROR(F("decoded binary size"), decoded_size, F("not matched to"), size); - return b_size_matched; - } - - template - bool deserialize(First& first, Rest&&... rest) { - if (!b_size_matched || indices.empty()) { - LOG_WARN(F("correct binary data was not supplied yet")); - b_decode_success = false; - return b_decode_success; - } - if (curr_index >= indices.size()) { - LOG_ERROR(F("too many args: obj index overflow")); - b_decode_success = false; - return b_decode_success; - } - if (!unpack(first)) { - return b_decode_success; - } - - return deserialize(std::forward(rest)...); - } - - bool deserialize() { - if (curr_index > indices.size()) { - LOG_ERROR("index overflow:", curr_index, "must be <=", indices.size()); - b_decode_success = false; - } - - // do nothing if curr_index is <= indices.size() - // - curr_index == indices.size() - // - to be decoded after this deserialize() - - return b_decode_success; - } - -#ifdef ARDUINOJSON_VERSION - - private: - bool deserialize_arduinojson(JsonDocument& doc) { - auto err = deserializeMsgPack(doc, raw_data); - if (err) { - LOG_ERROR("deserializeJson() faled: ", err.c_str()); - b_decode_success = false; - } else { - b_decode_success = true; - } - return b_decode_success; - } - - public: - template - bool deserialize(StaticJsonDocument& doc) { - return deserialize_arduinojson(doc); - } - bool deserialize(DynamicJsonDocument& doc) { - return deserialize_arduinojson(doc); - } - -#endif // ARDUINOJSON_VERSION - - template - bool from_array(Args&&... args) { - static arr_size_t sz; - return deserialize(sz, std::forward(args)...); - } - - template - bool from_map(Args&&... args) { - if ((sizeof...(args) % 2) == 0) { - static map_size_t sz; - return deserialize(sz, std::forward(args)...); - } else { - LOG_ERROR(F("arg size must be even for map:"), sizeof...(args)); - b_decode_success = false; - return b_decode_success; - } - } - - template - void to_tuple(std::tuple& t) { - to_tuple(std::make_index_sequence(), t); - } - template - void to_tuple(std::index_sequence&&, std::tuple& t) { - size_t i {0}; - idx_t {(unpack(std::get(t)), i++)...}; - } - void to_tuple() { - // nothing to do - } - - bool decode_ready() const { - return b_size_matched; - } - bool decoded() const { - return b_decode_success; - } - size_t size() const { - return indices.size(); - } - void index(const size_t i) { - curr_index = i; - } - size_t index() const { - return curr_index; - } - void clear() { - indices.clear(); - index(0); - b_size_matched = false; - b_decode_success = false; - raw_data = nullptr; - } - - ///////////////////////////////////////////////// - // ---------- msgpack type adaptors ---------- // - ///////////////////////////////////////////////// - - // adaptation of types to msgpack - // https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor - - // ---------- NIL format family ---------- - // - N/A - - template - auto unpack(T& value) -> typename std::enable_if::value, bool>::type { - value = unpackNil(); - return b_decode_success; - } - - // ---------- BOOL format family ---------- - // - bool - - template - auto unpack(T& value) -> typename std::enable_if::value, bool>::type { - value = unpackBool(); - return b_decode_success; - } - - // ---------- INT format family ---------- - // - char (signed/unsigned) - // - ints (signed/unsigned) - - template - auto unpack(T& value) -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value && !std::is_signed::value, - bool>::type { - value = unpackUInt(); - return b_decode_success; - } - - template - auto unpack(T& value) -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value && std::is_signed::value, - bool>::type { - value = unpackInt(); - return b_decode_success; - } - - // ---------- FLOAT format family ---------- - // - float - // - double - - template - auto unpack(T& value) -> - typename std::enable_if::value && std::is_floating_point::value, bool>::type { - value = unpackFloat(); - return b_decode_success; - } - - // ---------- STRING format family ---------- - // - char* - // - char[] - // - std::string - - bool unpack(str_t& str) { - str = unpackString(); - return b_decode_success; - } - - // ---------- BIN format family ---------- - // - unsigned char* - // - unsigned char[] - // - std::vector - // - std::vector - // - std::array - // - std::array - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpack(bin_t& bin) -> - typename std::enable_if::value || std::is_same::value, bool>::type { - bin = unpackBinary(); - return b_decode_success; - } - -#else - - template - auto unpack(arx::stdx::vector& bin) // bin_t - -> typename std::enable_if::value || std::is_same::value, bool>::type { - bin = unpackBinary(); - return b_decode_success; - } - -#endif // Do not have libstdc++11 - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpack(std::array& bin) -> - typename std::enable_if::value || std::is_same::value, bool>::type { - bin = unpackBinary(); - return b_decode_success; - } - -#endif // Do not have libstdc++11 - - // ---------- ARRAY format family ---------- - // - T[] - // - std::vector - // - std::array - // - std::deque - // - std::pair - // - std::tuple - // - std::list - // - std::forward_list - // - std::set - // - std::multiset - // - std::unordered_set * - // - std::unordered_multiset * - // * : not supported in arduino - - template - auto unpack(arr_t& arr) -> - typename std::enable_if::value && !std::is_same::value, bool>::type { - unpackArrayContainerArray(arr); - arr.shrink_to_fit(); - return b_decode_success; - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpack(std::array& arr) -> - typename std::enable_if::value && !std::is_same::value, bool>::type { - const size_t size = unpackArraySize(); - if (N == size) - for (auto& a : arr) unpack(a); - else { - LOG_ERROR(F("array size mismatch:"), size, F("must be"), N); - b_decode_success = false; - } - return b_decode_success; - } - - template - bool unpack(std::deque& arr) { - unpackArrayContainerArray(arr); - arr.shrink_to_fit(); - return b_decode_success; - } - - template - bool unpack(std::pair& arr) { - const size_t size = unpackArraySize(); - if (size == 2) { - unpack(arr.first); - unpack(arr.second); - } else { - LOG_ERROR(F("array size mismatch:"), size, F("must be"), 2); - b_decode_success = false; - } - return b_decode_success; - } - - template - bool unpack(std::tuple& t) { - const size_t size = unpackArraySize(); - if (sizeof...(Args) == size) { - to_tuple(t); - } else { - LOG_ERROR(F("array size mismatch:"), size, F("must be"), sizeof...(Args)); - b_decode_success = false; - } - return b_decode_success; - } - - template - bool unpack(std::list& arr) { - unpackArrayContainerArray(arr); - return b_decode_success; - } - - template - bool unpack(std::forward_list& arr) { - const size_t arr_size = std::distance(arr.begin(), arr.end()); - const size_t size = unpackArraySize(); - if (size == 0) { - LOG_ERROR(F("array size mismatch:"), size, F("must be"), arr_size); - b_decode_success = false; - } else if (arr_size == size) - for (auto& a : arr) unpack(a); - else { - arr.clear(); - for (size_t a = 0; a < size; ++a) { - T t; - unpack(t); - arr.emplace_after(std::next(arr.before_begin(), a), t); - } - } - return b_decode_success; - } - - template - bool unpack(std::set& arr) { - unpackArrayContainerSet(arr); - return b_decode_success; - } - - template - bool unpack(std::multiset& arr) { - unpackArrayContainerSet(arr); - return b_decode_success; - } - - template - bool unpack(std::unordered_set& arr) { - unpackArrayContainerSet(arr); - return b_decode_success; - } - - template - bool unpack(std::unordered_multiset& arr) { - unpackArrayContainerSet(arr); - return b_decode_success; - } - -#endif // Do not have libstdc++11 - - // ---------- MAP format family ---------- - // - std::map - // - std::multimap - // - std::unordered_map * - // - std::unordered_multimap * - // * : not supported in arduino - - template - bool unpack(map_t& mp) { - unpackMapContainer(mp); - return b_decode_success; - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - bool unpack(std::multimap& mp) { - unpackMapContainer(mp); - return b_decode_success; - } - - template - bool unpack(std::unordered_map& mp) { - unpackMapContainer(mp); - return b_decode_success; - } - - template - bool unpack(std::unordered_multimap& mp) { - unpackMapContainer(mp); - return b_decode_success; - } - -#endif // Do not have libstdc++11 - - // ---------- EXT format family ---------- - - bool unpack(object::ext& e) { - e = unpackExt(); - return b_decode_success; - } - - // ---------- TIMESTAMP format family ---------- - - bool unpack(object::timespec& t) { - t = unpackTimestamp(); - return b_decode_success; - } - - // ---------- CUSTOM format ---------- - - template - auto unpack(C& c) -> typename std::enable_if::value, bool>::type { - c.from_msgpack(*this); - return b_decode_success; - } - - // ---------- Array/Map Size format ---------- - - bool unpack(arr_size_t& t) { - t = arr_size_t(unpackArraySize()); - return b_decode_success; - } - - bool unpack(map_size_t& t) { - t = map_size_t(unpackMapSize()); - return b_decode_success; - } - - ///////////////////////////////////////////////////// - // ---------- msgpack types abstraction ---------- // - /////////////////////////////////////////............ - - // ---------- INT format family ---------- - - template - auto unpackUInt() -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value && !std::is_signed::value, - T>::type { - MSGPACK_DECODABLE_CHECK(T); - switch (getType()) { - case Type::UINT7: - return (T)unpackUInt7(); - case Type::UINT8: - return (T)unpackUInt8(); - case Type::UINT16: - return (T)unpackUInt16(); - case Type::UINT32: - return (T)unpackUInt32(); - case Type::UINT64: - return (T)unpackUInt64(); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - template - auto unpackInt() -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value && std::is_signed::value, - T>::type { - MSGPACK_DECODABLE_CHECK(T); - switch (getType()) { - case Type::INT5: - return (T)unpackInt5(); - case Type::INT8: - return (T)unpackInt8(); - case Type::INT16: - return (T)unpackInt16(); - case Type::INT32: - return (T)unpackInt32(); - case Type::INT64: - return (T)unpackInt64(); - case Type::UINT7: - return (T)unpackUInt7(); - case Type::UINT8: - return uint_to_int(unpackUInt8()); - case Type::UINT16: - return uint_to_int(unpackUInt16()); - case Type::UINT32: - return uint_to_int(unpackUInt32()); - case Type::UINT64: - return uint_to_int(unpackUInt64()); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - // ---------- FLOAT format family ---------- - - template - auto unpackFloat() -> - typename std::enable_if::value && std::is_floating_point::value, T>::type { - MSGPACK_DECODABLE_CHECK(T); - switch (getType()) { - case Type::UINT7: - return (T)unpackUInt7(); - case Type::UINT8: - return (T)unpackUInt8(); - case Type::UINT16: - return (T)unpackUInt16(); - case Type::UINT32: - return (T)unpackUInt32(); - case Type::UINT64: - return (T)unpackUInt64(); - case Type::INT5: - return (T)unpackInt5(); - case Type::INT8: - return (T)unpackInt8(); - case Type::INT16: - return (T)unpackInt16(); - case Type::INT32: - return (T)unpackInt32(); - case Type::INT64: - return (T)unpackInt64(); - case Type::FLOAT32: - return (T)unpackFloat32(); - case Type::FLOAT64: - return (T)unpackFloat64(); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - // ---------- STR format family ---------- - - str_t unpackString() { - MSGPACK_DECODABLE_CHECK(str_t); - switch (getType()) { - case Type::STR5: - return unpackStringUnchecked5(); - case Type::STR8: - return unpackStringUnchecked8(); - case Type::STR16: - return unpackStringUnchecked16(); - case Type::STR32: - return unpackStringUnchecked32(); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - // ---------- BIN format family ---------- - - template - auto unpackBinary() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - MSGPACK_DECODABLE_CHECK(bin_t); - switch (getType()) { - case Type::BIN8: - return unpackBinaryUnchecked8(); - case Type::BIN16: - return unpackBinaryUnchecked16(); - case Type::BIN32: - return unpackBinaryUnchecked32(); - default: - LOG_ERROR("type error"); - return type_error>(); - } - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpackBinary() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - using t = std::array; - MSGPACK_DECODABLE_CHECK(t); - switch (getType()) { - case Type::BIN8: - return unpackBinaryUnchecked8(); - case Type::BIN16: - return unpackBinaryUnchecked16(); - case Type::BIN32: - return unpackBinaryUnchecked32(); - default: - LOG_ERROR("type error"); - return type_error>(); - } - } - -#endif // Do not have libstdc++11 - - // ---------- ARRAY format family ---------- - - size_t unpackArraySize() { - MSGPACK_DECODABLE_CHECK(size_t); - switch (getType()) { - case Type::ARRAY4: - return unpackArraySizeUnchecked4(); - case Type::ARRAY16: - return unpackArraySizeUnchecked16(); - case Type::ARRAY32: - return unpackArraySizeUnchecked32(); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - // ---------- MAP format family ---------- - - size_t unpackMapSize() { - MSGPACK_DECODABLE_CHECK(size_t); - switch (getType()) { - case Type::MAP4: - return unpackMapSizeUnchecked4(); - case Type::MAP16: - return unpackMapSizeUnchecked16(); - case Type::MAP32: - return unpackMapSizeUnchecked32(); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - // ---------- EXT format family ---------- - - object::ext unpackExt() { - MSGPACK_DECODABLE_CHECK(object::ext); - switch (getType()) { - case Type::FIXEXT1: - return unpackFixExtUnchecked1(); - case Type::FIXEXT2: - return unpackFixExtUnchecked2(); - case Type::FIXEXT4: - return unpackFixExtUnchecked4(); - case Type::FIXEXT8: - return unpackFixExtUnchecked8(); - case Type::FIXEXT16: - return unpackFixExtUnchecked16(); - case Type::EXT8: - return unpackExtUnchecked8(); - case Type::EXT16: - return unpackExtUnchecked16(); - case Type::EXT32: - return unpackExtUnchecked32(); - default: - LOG_ERROR("type error"); - return type_error(); - } - } - - // ---------- TIMESTAMP format family ---------- - - object::timespec unpackTimestamp() { - // because only timestamp has mutiple condition to satisfy, - // used isTimestampXX() instead of switch + type tag - MSGPACK_DECODABLE_CHECK(object::timespec); - if (isTimestamp32()) - return unpackTimestampUnchecked32(); - else if (isTimestamp64()) - return unpackTimestampUnchecked64(); - else if (isTimestamp96()) - return unpackTimestampUnchecked96(); - else { - LOG_ERROR("type error"); - return type_error(); - } - } - - ////////////////////////////////////////////////////// - // ---------- msgpack types with checker ---------- // - ////////////////////////////////////////////////////// - - // ---------- NIL format family ---------- - - bool unpackNil() { - MSGPACK_DECODABLE_CHECK(bool); - if (isNil()) - return unpackNilUnchecked(); - else - return type_error(Type::NIL); - } - - // ---------- BOOL format family ---------- - - bool unpackBool() { - MSGPACK_DECODABLE_CHECK(bool); - if (isBool()) - return unpackBoolUnchecked(); - else - return type_error(Type::BOOL); - } - - // ---------- INT format family ---------- - - uint8_t unpackUInt7() { - MSGPACK_DECODABLE_CHECK(uint8_t); - if (isUInt7()) - return unpackUIntUnchecked7(); - else - return type_error(Type::UINT7); - } - - uint8_t unpackUInt8() { - MSGPACK_DECODABLE_CHECK(uint8_t); - if (isUInt8()) - return unpackUIntUnchecked8(); - else - return type_error(Type::UINT8); - } - - uint16_t unpackUInt16() { - MSGPACK_DECODABLE_CHECK(uint16_t); - if (isUInt16()) - return unpackUIntUnchecked16(); - else - return type_error(Type::UINT16); - } - - uint32_t unpackUInt32() { - MSGPACK_DECODABLE_CHECK(uint32_t); - if (isUInt32()) - return unpackUIntUnchecked32(); - else - return type_error(Type::UINT32); - } - - uint64_t unpackUInt64() { - MSGPACK_DECODABLE_CHECK(uint64_t); - if (isUInt64()) - return unpackUIntUnchecked64(); - else - return type_error(Type::UINT64); - } - - int8_t unpackInt5() { - MSGPACK_DECODABLE_CHECK(int8_t); - if (isInt5()) - return unpackIntUnchecked5(); - else - return type_error(Type::INT5); - } - - int8_t unpackInt8() { - MSGPACK_DECODABLE_CHECK(int8_t); - if (isInt8()) - return unpackIntUnchecked8(); - else - return type_error(Type::INT8); - } - - int16_t unpackInt16() { - MSGPACK_DECODABLE_CHECK(int16_t); - if (isInt16()) - return unpackIntUnchecked16(); - else - return type_error(Type::INT16); - } - - int32_t unpackInt32() { - MSGPACK_DECODABLE_CHECK(int32_t); - if (isInt32()) - return unpackIntUnchecked32(); - else - return type_error(Type::INT32); - } - - int64_t unpackInt64() { - MSGPACK_DECODABLE_CHECK(int64_t); - if (isInt64()) - return unpackIntUnchecked64(); - else - return type_error(Type::INT64); - } - - // ---------- FLOAT format family ---------- - - float unpackFloat32() { - MSGPACK_DECODABLE_CHECK(float); - if (isFloat32()) - return unpackFloatUnchecked32(); - else - return type_error(Type::FLOAT32); - } - - double unpackFloat64() { - MSGPACK_DECODABLE_CHECK(double); -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - if (isFloat64()) - return unpackFloatUnchecked64(); - else - return type_error(Type::FLOAT64); -#else - if (isFloat32() || isFloat64()) - return unpackFloat32(); // AVR does not support double - else - return type_error(Type::FLOAT64); -#endif - } - - // ---------- STR format family ---------- - - str_t unpackString5() { - MSGPACK_DECODABLE_CHECK(str_t); - if (isStr5()) - return unpackStringUnchecked5(); - else - return type_error(Type::STR5); - } - - str_t unpackString8() { - MSGPACK_DECODABLE_CHECK(str_t); - if (isStr8()) - return unpackStringUnchecked8(); - else - return type_error(Type::STR8); - } - - str_t unpackString16() { - str_t str(""); - MSGPACK_DECODABLE_CHECK(str_t); - if (isStr16()) - return unpackStringUnchecked16(); - else - return type_error(Type::STR16); - } - - str_t unpackString32() { - MSGPACK_DECODABLE_CHECK(str_t); - if (isStr32()) - return unpackStringUnchecked32(); - else - return type_error(Type::STR32); - } - - // ---------- BIN format family ---------- - - template - auto unpackBinary8() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - MSGPACK_DECODABLE_CHECK(bin_t); - if (isBin8()) - return unpackBinaryUnchecked8(); - else - return type_error>(Type::BIN8); - } - - template - auto unpackBinary16() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - MSGPACK_DECODABLE_CHECK(bin_t); - if (isBin16()) - return unpackBinaryUnchecked16(); - else - return type_error>(Type::BIN16); - } - - template - auto unpackBinary32() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - MSGPACK_DECODABLE_CHECK(bin_t); - if (isBin32()) - return unpackBinaryUnchecked32(); - else - return type_error>(Type::BIN32); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpackBinary8() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - using t = std::array; - MSGPACK_DECODABLE_CHECK(t); - if (isBin8()) - return unpackBinaryUnchecked8(); - else - return type_error>(Type::BIN8); - } - - template - auto unpackBinary16() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - using t = std::array; - MSGPACK_DECODABLE_CHECK(t); - if (isBin16()) - return unpackBinaryUnchecked16(); - else - return type_error>(Type::BIN16); - } - - template - auto unpackBinary32() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - using t = std::array; - MSGPACK_DECODABLE_CHECK(t); - if (isBin32()) - return unpackBinaryUnchecked32(); - else - return type_error>(Type::BIN32); - } - -#endif // Do not have libstdc++11 - - // ---------- ARRAY format family ---------- - - size_t unpackArraySize4() { - MSGPACK_DECODABLE_CHECK(size_t); - if (isArray4()) - return unpackArraySizeUnchecked4(); - else - return type_error(Type::ARRAY4); - } - - size_t unpackArraySize16() { - MSGPACK_DECODABLE_CHECK(size_t); - if (isArray16()) - return unpackArraySizeUnchecked16(); - else - return type_error(Type::ARRAY16); - } - - size_t unpackArraySize32() { - MSGPACK_DECODABLE_CHECK(size_t); - if (isArray32()) - return unpackArraySizeUnchecked32(); - else - return type_error(Type::ARRAY32); - } - - // ---------- MAP format family ---------- - - size_t unpackMapSize4() { - MSGPACK_DECODABLE_CHECK(size_t); - if (isMap4()) - return unpackMapSizeUnchecked4(); - else - return type_error(Type::MAP4); - } - - size_t unpackMapSize16() { - MSGPACK_DECODABLE_CHECK(size_t); - if (isMap16()) - return unpackMapSizeUnchecked16(); - else - return type_error(Type::MAP16); - } - - size_t unpackMapSize32() { - MSGPACK_DECODABLE_CHECK(size_t); - if (isMap32()) - return unpackMapSizeUnchecked32(); - else - return type_error(Type::MAP32); - } - - // ---------- EXT format family ---------- - - object::ext unpackFixExt1() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isFixExt1()) - return unpackFixExtUnchecked1(); - else - return type_error(Type::FIXEXT1); - } - - object::ext unpackFixExt2() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isFixExt2()) - return unpackFixExtUnchecked2(); - else - return type_error(Type::FIXEXT2); - } - - object::ext unpackFixExt4() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isFixExt4()) - return unpackFixExtUnchecked4(); - else - return type_error(Type::FIXEXT4); - } - - object::ext unpackFixExt8() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isFixExt8()) - return unpackFixExtUnchecked8(); - else - return type_error(Type::FIXEXT8); - } - - object::ext unpackFixExt16() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isFixExt16()) - return unpackFixExtUnchecked16(); - else - return type_error(Type::FIXEXT16); - } - - object::ext unpackExt8() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isExt8()) - return unpackExtUnchecked8(); - else - return type_error(Type::EXT8); - } - - object::ext unpackExt16() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isExt16()) - return unpackExtUnchecked16(); - else - return type_error(Type::EXT16); - } - - object::ext unpackExt32() { - MSGPACK_DECODABLE_CHECK(object::ext); - if (isExt32()) - return unpackExtUnchecked32(); - else - return type_error(Type::EXT32); - } - - // ---------- TIMESTAMP format family ---------- - - object::timespec unpackTimestamp32() { - MSGPACK_DECODABLE_CHECK(object::timespec); - if (isTimestamp32()) - return unpackTimestampUnchecked32(); - else - return type_error(Type::TIMESTAMP32); - } - - object::timespec unpackTimestamp64() { - MSGPACK_DECODABLE_CHECK(object::timespec); - if (isTimestamp64()) - return unpackTimestampUnchecked64(); - else - return type_error(Type::TIMESTAMP64); - } - - object::timespec unpackTimestamp96() { - MSGPACK_DECODABLE_CHECK(object::timespec); - if (isTimestamp96()) - return unpackTimestampUnchecked96(); - else - return type_error(Type::TIMESTAMP96); - } - - ///////////////////////////////////////////////////////// - // ---------- msgpack types without checker ---------- // - ///////////////////////////////////////////////////////// - - // ---------- NIL format family ---------- - - bool unpackNilUnchecked() { - ++curr_index; - return true; - } - - // ---------- BOOL format family ---------- - - bool unpackBoolUnchecked() { - return (bool)(getRawBytes(curr_index++, 0) & (uint8_t)BitMask::BOOL); - } - - // ---------- INT format family ---------- - - uint8_t unpackUIntUnchecked7() { - return (uint8_t)(getRawBytes(curr_index++, 0) & (uint8_t)BitMask::UINT7); - } - - uint8_t unpackUIntUnchecked8() { - return getRawBytes(curr_index++, 1); - } - - uint16_t unpackUIntUnchecked16() { - return getRawBytes(curr_index++, 1); - } - - uint32_t unpackUIntUnchecked32() { - return getRawBytes(curr_index++, 1); - } - - uint64_t unpackUIntUnchecked64() { - return getRawBytes(curr_index++, 1); - } - - int8_t unpackIntUnchecked5() { - return (int8_t)getRawBytes(curr_index++, 0); - } - - int8_t unpackIntUnchecked8() { - return getRawBytes(curr_index++, 1); - } - - int16_t unpackIntUnchecked16() { - return getRawBytes(curr_index++, 1); - } - - int32_t unpackIntUnchecked32() { - return getRawBytes(curr_index++, 1); - } - - int64_t unpackIntUnchecked64() { - return getRawBytes(curr_index++, 1); - } - - // ---------- FLOAT format family ---------- - - float unpackFloatUnchecked32() { - return getRawBytes(curr_index++, 1); - } - - double unpackFloatUnchecked64() { -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - return getRawBytes(curr_index++, 1); -#else - return unpackFloatUnchecked32(); // AVR does not support double -#endif - } - - // ---------- STR format family ---------- - - str_t unpackStringUnchecked5() { - str_t str; - uint8_t size = getRawBytes(curr_index, 0) & (uint8_t)BitMask::STR5; - for (uint8_t c = 0; c < size; ++c) str += getRawBytes(curr_index, c + 1); - ++curr_index; - return str; - } - - str_t unpackStringUnchecked8() { - str_t str; - uint8_t size = getRawBytes(curr_index, 1); - for (uint8_t c = 0; c < size; ++c) str += getRawBytes(curr_index, c + 1 + sizeof(uint8_t)); - ++curr_index; - return str; - } - - str_t unpackStringUnchecked16() { - str_t str; - uint16_t size = getRawBytes(curr_index, 1); - for (uint16_t c = 0; c < size; ++c) str += getRawBytes(curr_index, c + 1 + sizeof(uint16_t)); - ++curr_index; - return str; - } - - str_t unpackStringUnchecked32() { - str_t str; - uint32_t size = getRawBytes(curr_index, 1); - for (uint32_t c = 0; c < size; ++c) str += getRawBytes(curr_index, c + 1 + sizeof(uint32_t)); - ++curr_index; - return str; - } - - // ---------- BIN format family ---------- - - template - auto unpackBinaryUnchecked8() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - bin_t data; - uint8_t size = getRawBytes(curr_index, 1); - for (uint8_t v = 0; v < size; ++v) data.emplace_back(getRawBytes(curr_index, v + 1 + sizeof(uint8_t))); - ++curr_index; - return data; - } - - template - auto unpackBinaryUnchecked16() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - bin_t data; - uint16_t size = getRawBytes(curr_index, 1); - for (uint16_t v = 0; v < size; ++v) - data.emplace_back(getRawBytes(curr_index, v + 1 + sizeof(uint16_t))); - ++curr_index; - return data; - } - - template - auto unpackBinaryUnchecked32() -> - typename std::enable_if::value || std::is_same::value, bin_t>::type { - bin_t data; - uint32_t size = getRawBytes(curr_index, 1); - for (uint32_t v = 0; v < size; ++v) - data.emplace_back(getRawBytes(curr_index, v + 1 + sizeof(uint32_t))); - ++curr_index; - return data; - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpackBinaryUnchecked8() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - std::array data; - uint8_t size = getRawBytes(curr_index, 1); - for (uint8_t v = 0; v < size; ++v) data[v] = getRawBytes(curr_index, v + 1 + sizeof(uint8_t)); - ++curr_index; - return data; - } - - template - auto unpackBinaryUnchecked16() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - std::array data; - uint16_t size = getRawBytes(curr_index, 1); - for (uint16_t v = 0; v < size; ++v) data[v] = getRawBytes(curr_index, v + 1 + sizeof(uint16_t)); - ++curr_index; - return data; - } - - template - auto unpackBinaryUnchecked32() -> typename std:: - enable_if::value || std::is_same::value, std::array>::type { - std::array data; - uint32_t size = getRawBytes(curr_index, 1); - for (uint32_t v = 0; v < size; ++v) data[v] = getRawBytes(curr_index, v + 1 + sizeof(uint32_t)); - ++curr_index; - return data; - } - -#endif // Do not have libstdc++11 - - // ---------- ARRAY format family ---------- - - size_t unpackArraySizeUnchecked4() { - return (size_t)((getRawBytes(curr_index++, 0) & (uint8_t)BitMask::ARRAY4)); - } - - size_t unpackArraySizeUnchecked16() { - return (size_t)getRawBytes(curr_index++, 1); - } - - size_t unpackArraySizeUnchecked32() { - return (size_t)getRawBytes(curr_index++, 1); - } - - // ---------- MAP format family ---------- - - size_t unpackMapSizeUnchecked4() { - return (size_t)((getRawBytes(curr_index++, 0) & (uint8_t)BitMask::MAP4)); - } - - size_t unpackMapSizeUnchecked16() { - return (size_t)getRawBytes(curr_index++, 1); - } - - size_t unpackMapSizeUnchecked32() { - return (size_t)getRawBytes(curr_index++, 1); - } - - // ---------- EXT format family ---------- - - object::ext unpackFixExtUnchecked1() { - int8_t ext_type = getRawBytes(curr_index, 1); - uint8_t* ptr = getRawBytePtr(curr_index++, 2); - return object::ext(ext_type, ptr, 1); - } - - object::ext unpackFixExtUnchecked2() { - int8_t ext_type = getRawBytes(curr_index, 1); - uint8_t* ptr = getRawBytePtr(curr_index++, 2); - return object::ext(ext_type, ptr, 2); - } - - object::ext unpackFixExtUnchecked4() { - int8_t ext_type = getRawBytes(curr_index, 1); - uint8_t* ptr = getRawBytePtr(curr_index++, 2); - return object::ext(ext_type, ptr, 4); - } - - object::ext unpackFixExtUnchecked8() { - int8_t ext_type = getRawBytes(curr_index, 1); - uint8_t* ptr = getRawBytePtr(curr_index++, 2); - return object::ext(ext_type, ptr, 8); - } - - object::ext unpackFixExtUnchecked16() { - int8_t ext_type = getRawBytes(curr_index, 1); - uint8_t* ptr = getRawBytePtr(curr_index++, 2); - return object::ext(ext_type, ptr, 16); - } - - object::ext unpackExtUnchecked8() { - uint8_t size = getRawBytes(curr_index, 1); - int8_t ext_type = getRawBytes(curr_index, 2); - uint8_t* ptr = getRawBytePtr(curr_index++, 3); - return object::ext(ext_type, ptr, size); - } - - object::ext unpackExtUnchecked16() { - uint16_t size = getRawBytes(curr_index, 1); - int8_t ext_type = getRawBytes(curr_index, 3); - uint8_t* ptr = getRawBytePtr(curr_index++, 4); - return object::ext(ext_type, ptr, size); - } - - object::ext unpackExtUnchecked32() { - uint32_t size = getRawBytes(curr_index, 1); - int8_t ext_type = getRawBytes(curr_index, 5); - uint8_t* ptr = getRawBytePtr(curr_index++, 6); - return object::ext(ext_type, ptr, size); - } - - // ---------- TIMESTAMP format family ---------- - - object::timespec unpackTimestampUnchecked32() { - object::timespec ts; - ts.tv_nsec = 0; - ts.tv_sec = getRawBytes(curr_index++, 2); - return ts; - } - - object::timespec unpackTimestampUnchecked64() { - object::timespec ts; - uint64_t data64 = getRawBytes(curr_index++, 2); - ts.tv_nsec = data64 >> 34; - ts.tv_sec = data64 & 0x00000003ffffffffL; - return ts; - } - - object::timespec unpackTimestampUnchecked96() { - object::timespec ts; - ts.tv_nsec = getRawBytes(curr_index, 3); - ts.tv_sec = getRawBytes(curr_index++, 7); - return ts; - } - - ///////////////////////////////////////// - // ---------- type checkers ---------- // - ///////////////////////////////////////// - - // ---------- NIL format family ---------- - // - N/A - - template - auto unpackable(const T& value) const -> - typename std::enable_if::value, bool>::type { - (void)value; - return isNil(); - } - - // ---------- BOOL format family ---------- - // - bool - - template - auto unpackable(const T& value) const -> typename std::enable_if::value, bool>::type { - (void)value; - return isBool(); - } - - // ---------- INT format family ---------- - // - char (signed/unsigned) - // - ints (signed/unsigned) - - template - auto unpackable(const T&) const -> typename std::enable_if< - std::is_arithmetic::value && !std::is_floating_point::value && !std::is_same::value - && !std::is_same::type, char*>::value && !std::is_signed::value, - bool>::type { - if (isUInt7()) - return sizeof(T) >= sizeof(uint8_t); - else if (isUInt8()) - return sizeof(T) >= sizeof(uint8_t); - else if (isUInt16()) - return sizeof(T) >= sizeof(uint16_t); - else if (isUInt32()) - return sizeof(T) >= sizeof(uint32_t); - else if (isUInt64()) - return sizeof(T) >= sizeof(uint64_t); - else - return false; - } - - template - auto unpackable(const T&) const -> typename std::enable_if< - std::is_arithmetic::value && !std::is_floating_point::value && !std::is_same::value - && !std::is_same::type, char*>::value && std::is_signed::value, - bool>::type { - if (isInt5()) - return sizeof(T) >= sizeof(int8_t); - else if (isInt8()) - return sizeof(T) >= sizeof(int8_t); - else if (isInt16()) - return sizeof(T) >= sizeof(int16_t); - else if (isInt32()) - return sizeof(T) >= sizeof(int32_t); - else if (isInt64()) - return sizeof(T) >= sizeof(int64_t); - else if (isUInt7()) - return sizeof(T) >= sizeof(int8_t); - else if (isUInt8()) - return sizeof(T) >= sizeof(int8_t); - else if (isUInt16()) - return sizeof(T) >= sizeof(int16_t); - else if (isUInt32()) - return sizeof(T) >= sizeof(int32_t); - else if (isUInt64()) - return sizeof(T) >= sizeof(int64_t); - else - return false; - } - - // ---------- FLOAT format family ---------- - // - float - // - double - - template - auto unpackable(const T&) const -> - typename std::enable_if::value && std::is_floating_point::value, bool>::type { - switch (getType()) { - case Type::UINT7: - case Type::UINT8: - case Type::UINT16: - case Type::UINT32: - case Type::UINT64: - case Type::INT5: - case Type::INT8: - case Type::INT16: - case Type::INT32: - case Type::INT64: - case Type::FLOAT32: - case Type::FLOAT64: - return true; - default: - return false; - } - } - - // ---------- STRING format family ---------- - // - char* - // - char[] - // - std::string - - bool unpackable(const str_t& str) const { - (void)str; - return isStr(); - } - - // ---------- BIN format family ---------- - // - unsigned char* - // - unsigned char[] - // - std::vector - // - std::vector - // - std::array - // - std::array - - template - auto unpackable(const bin_t& bin) const -> - typename std::enable_if::value || std::is_same::value, bool>::type { - (void)bin; - return isBin(); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpackable(const std::array& bin) const -> - typename std::enable_if::value || std::is_same::value, bool>::type { - (void)bin; - return isBin(); - } - -#endif // Do not have libstdc++11 - - // ---------- ARRAY format family ---------- - // - T[] - // - std::vector - // - std::array - // - std::deque - // - std::pair - // - std::tuple - // - std::list - // - std::forward_list - // - std::set - // - std::unordered_set - // - std::multiset - // - std::unordered_multiset - - template - auto unpackable(const arr_t& arr) const -> - typename std::enable_if::value && !std::is_same::value, bool>::type { - (void)arr; - return isArray(); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - auto unpackable(const std::array& arr) const -> - typename std::enable_if::value && !std::is_same::value, bool>::type { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::deque& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::pair& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::tuple& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::list& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::forward_list& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::set& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::unordered_set& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(const std::multiset& arr) const { - (void)arr; - return isArray(); - } - - template - bool unpackable(std::unordered_multiset& arr) const { - (void)arr; - return isArray(); - } - -#endif // Do not have libstdc++11 - - // ---------- MAP format family ---------- - // - std::map - // - std::multimap - // - std::unordered_map * - // - std::unordered_multimap * - // * : not supported in arduino - - template - bool unpackable(const map_t& mp) const { - (void)mp; - return isMap(); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - - template - bool unpackable(const std::multimap& mp) const { - (void)mp; - return isMap(); - } - - template - bool unpackable(const std::unordered_map& mp) const { - (void)mp; - return isMap(); - } - - template - bool unpackable(const std::unordered_multimap& mp) const { - (void)mp; - return isMap(); - } - -#endif // Do not have libstdc++11 - - // ---------- EXT format family ---------- - - bool unpackable(const object::ext& e) const { - (void)e; - return isFixExt() || isExt(); - } - - // ---------- TIMESTAMP format family ---------- - - bool unpackable(const object::timespec& t) const { - (void)t; - return isTimestamp(); - } - - ///////////////////////////////////////////////// - // ---------- msgpack type checkers ---------- // - ///////////////////////////////////////////////// - - bool isNil() const { - return getType() == Type::NIL; - } - bool isBool() const { - return getType() == Type::BOOL; - } - bool isUInt7() const { - return getType() == Type::UINT7; - } - bool isUInt8() const { - return getType() == Type::UINT8; - } - bool isUInt16() const { - return getType() == Type::UINT16; - } - bool isUInt32() const { - return getType() == Type::UINT32; - } - bool isUInt64() const { - return getType() == Type::UINT64; - } - bool isUInt() const { - return isUInt7() || isUInt8() || isUInt16() || isUInt32() || isUInt64(); - } - bool isInt5() const { - return getType() == Type::INT5; - } - bool isInt8() const { - return getType() == Type::INT8; - } - bool isInt16() const { - return getType() == Type::INT16; - } - bool isInt32() const { - return getType() == Type::INT32; - } - bool isInt64() const { - return getType() == Type::INT64; - } - bool isInt() const { - return isInt5() || isInt8() || isInt16() || isInt32() || isInt64(); - } - bool isFloat32() const { - return getType() == Type::FLOAT32; - } - bool isFloat64() const { - return getType() == Type::FLOAT64; - } - bool isStr5() const { - return getType() == Type::STR5; - } - bool isStr8() const { - return getType() == Type::STR8; - } - bool isStr16() const { - return getType() == Type::STR16; - } - bool isStr32() const { - return getType() == Type::STR32; - } - bool isStr() const { - return isStr5() || isStr8() || isStr16() || isStr32(); - } - bool isBin8() const { - return getType() == Type::BIN8; - } - bool isBin16() const { - return getType() == Type::BIN16; - } - bool isBin32() const { - return getType() == Type::BIN32; - } - bool isBin() const { - return isBin8() || isBin16() || isBin32(); - } - bool isArray4() const { - return getType() == Type::ARRAY4; - } - bool isArray16() const { - return getType() == Type::ARRAY16; - } - bool isArray32() const { - return getType() == Type::ARRAY32; - } - bool isArray() const { - return isArray4() || isArray16() || isArray32(); - } - bool isMap4() const { - return getType() == Type::MAP4; - } - bool isMap16() const { - return getType() == Type::MAP16; - } - bool isMap32() const { - return getType() == Type::MAP32; - } - bool isMap() const { - return isMap4() || isMap16() || isMap32(); - } - bool isFixExt1() const { - return getType() == Type::FIXEXT1; - } - bool isFixExt2() const { - return getType() == Type::FIXEXT2; - } - bool isFixExt4() const { - return getType() == Type::FIXEXT4; - } - bool isFixExt8() const { - return getType() == Type::FIXEXT8; - } - bool isFixExt16() const { - return getType() == Type::FIXEXT16; - } - bool isFixExt() const { - return isFixExt1() || isFixExt2() || isFixExt4() || isFixExt8() || isFixExt16(); - } - bool isExt8() const { - return getType() == Type::EXT8; - } - bool isExt16() const { - return getType() == Type::EXT16; - } - bool isExt32() const { - return getType() == Type::EXT32; - } - bool isExt() const { - return isExt8() || isExt16() || isExt32(); - } - bool isTimestamp32() const { - return (getType() == Type::TIMESTAMP32) && (getRawBytes(curr_index, 1) == -1); - } - bool isTimestamp64() const { - return (getType() == Type::TIMESTAMP64) && (getRawBytes(curr_index, 1) == -1); - } - bool isTimestamp96() const { - return (getType() == Type::TIMESTAMP96) && (getRawBytes(curr_index, 2) == -1) - && (getRawBytes(curr_index, 1) == 12); - } - bool isTimestamp() const { - return isTimestamp32() || isTimestamp64() || isTimestamp96(); - } - - Type getType() const { - return getType(curr_index); - } - - private: - template - DataType getRawBytes(const size_t idx, const size_t offset) const { - if (idx >= indices.size()) { - LOG_ERROR(F("index overrun: idx"), idx, F("must be <"), indices.size()); - return DataType(); - } - DataType data; - const auto size = sizeof(DataType); - for (uint8_t b = 0; b < size; ++b) { - uint8_t distance = size - 1 - b; - auto index = indices[idx] + offset + distance; - ((uint8_t*)&data)[b] = raw_data[index]; - } - return data; - } - - uint8_t* getRawBytePtr(const size_t idx, const size_t offset) const { - if (idx >= indices.size()) { - LOG_ERROR(F("index overrun: idx"), idx, F("must be <"), indices.size()); - return nullptr; - } - auto index = indices[idx] + offset; - return raw_data + index; - } - - Type getType(const size_t idx) const { - if (idx >= indices.size()) { - LOG_ERROR(F("index overrun: idx"), idx, F("must be <"), indices.size()); - return Type::NA; - } - - uint8_t raw = getRawBytes(idx, 0); - if (raw < (uint8_t)Type::MAP4) - return Type::UINT7; - else if (raw < (uint8_t)Type::ARRAY4) - return Type::MAP4; - else if (raw < (uint8_t)Type::STR5) - return Type::ARRAY4; - else if (raw < (uint8_t)Type::NIL) - return Type::STR5; - else if (raw == (uint8_t)Type::NIL) - return Type::NIL; - else if (raw == (uint8_t)Type::NA) - return Type::NA; - else if (raw < (uint8_t)Type::BIN8) - return Type::BOOL; - else if (raw < (uint8_t)Type::INT5) - return (Type)raw; - else - return Type::INT5; - } - - size_t getElementSize(size_t i) const { - Type type = getType(i); - switch (type) { - // size of ARRAY & MAP is size of OBJECTs - // so the size from header to first object is returned - case Type::NIL: - case Type::BOOL: - case Type::UINT7: - case Type::INT5: - case Type::ARRAY4: - case Type::MAP4: - return 1; - case Type::UINT8: - case Type::INT8: - return 2; - case Type::UINT16: - case Type::INT16: - case Type::ARRAY16: - case Type::MAP16: - case Type::FIXEXT1: - return 3; - case Type::FIXEXT2: - return 4; - case Type::UINT32: - case Type::INT32: - case Type::FLOAT32: - case Type::ARRAY32: - case Type::MAP32: - return 5; - case Type::FIXEXT4: // includes case Type::TIMESTAMP32: - return 6; - case Type::UINT64: - case Type::INT64: - case Type::FLOAT64: - return 9; - case Type::FIXEXT8: // includes case Type::TIMESTAMP64: - return 10; - case Type::FIXEXT16: - return 18; - case Type::STR5: - return (getRawBytes(i, 0) & (uint8_t)BitMask::STR5) + 1; - case Type::STR8: - case Type::BIN8: - return getRawBytes(i, 1) + sizeof(uint8_t) + 1; - case Type::STR16: - case Type::BIN16: - return (size_t)getRawBytes(i, 1) + sizeof(uint16_t) + 1; - case Type::STR32: - case Type::BIN32: - return (size_t)getRawBytes(i, 1) + sizeof(uint32_t) + 1; - case Type::EXT8: // includes case Type::TIMESTAMP96: - return (size_t)getRawBytes(i, 1) + sizeof(uint8_t) + 1 + 1; - case Type::EXT16: - return (size_t)getRawBytes(i, 1) + sizeof(uint16_t) + 1 + 1; - case Type::EXT32: - return (size_t)getRawBytes(i, 1) + sizeof(uint32_t) + 1 + 1; - default: - LOG_ERROR(F("undefined type:"), (int)type); - return 0; - } - } - - template - T type_error(const Type type = Type::NA) { - if (type == Type::NA) - LOG_ERROR(F("unknown type in index"), curr_index, F(": type byte"), (int)getType()); - else - LOG_ERROR( - F("unpack type mimatch in index"), - curr_index, - F(": type byte"), - (int)getType(), - F("must be"), - (int)type); - b_decode_success = false; - ++curr_index; - return T(); - } - - template - auto uint_to_int(const U value) -> typename std::enable_if< - std::is_arithmetic::value && std::is_integral::value && !std::is_same::value - && !std::is_same::type, char*>::value && std::is_signed::value, - T>::type { - if ((sizeof(T) > sizeof(V)) || (value <= (U)std::numeric_limits::max())) - return (T)value; - else - return T(); - } - -#if ARX_HAVE_LIBSTDCPLUSPLUS >= 201103L // Have libstdc++11 - template