summaryrefslogtreecommitdiff
path: root/src/cbor/cbor_decoder.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2022-11-22 17:05:02 +1100
committerjacqueline <me@jacqueline.id.au>2022-11-22 17:05:02 +1100
commit9176ef187227ffb56c249c5f321cd1bf50d4cfcc (patch)
treea846c8fc4e5788e97d6fca43c2807c4bf0ae0214 /src/cbor/cbor_decoder.cpp
parent9f8cfaa7a8abd885785830e03d7c417e856b8a22 (diff)
downloadtangara-fw-9176ef187227ffb56c249c5f321cd1bf50d4cfcc.tar.gz
Add cbor wrapper, and chunk streaming util
Diffstat (limited to 'src/cbor/cbor_decoder.cpp')
-rw-r--r--src/cbor/cbor_decoder.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/cbor/cbor_decoder.cpp b/src/cbor/cbor_decoder.cpp
new file mode 100644
index 00000000..eb43e163
--- /dev/null
+++ b/src/cbor/cbor_decoder.cpp
@@ -0,0 +1,158 @@
+#include "cbor_decoder.hpp"
+#include <cstdint>
+#include "esp-idf/components/cbor/tinycbor/src/cbor.h"
+#include "include/cbor_decoder.hpp"
+
+namespace cbor {
+
+static auto ArrayDecoder::Create(uint8_t *buffer, size_t buffer_len) -> cpp::result<std::unique_ptr<ArrayDecoder>, CborError> {
+ auto decoder = std::make_unique<ArrayDecoder>();
+ cbor_parser_init(buffer, buffer_len, &decoder->parser_, &decoder->root_);
+ if (!cbor_value_is_array(&decoder->root_)) {
+ return cpp::fail(CborErrorIllegalType);
+ }
+ CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_);
+ if (err != CborNoError) {
+ return cpp::fail(err);
+ }
+ return std::move(decoder);
+}
+
+
+auto ArrayDecoder::ParseString() -> cpp::result<std::string, CborError> {
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+
+ if (!cbor_value_is_byte_string(&it_)) {
+ error_ = CborErrorIllegalType;
+ return cpp::fail(error_);
+ }
+ uint8_t *buf; size_t len; CborValue new_val;
+ error_ = cbor_value_dup_byte_string(&it_, &buf, &len, &new_val);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ std::string ret(buf, len);
+ free(buf);
+ val_ = new_val;
+ return ret;
+}
+
+auto ArrayDecoder::ParseUnsigned() -> cpp::result<uint32_t, CborError> {
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+
+ if (!cbor_value_is_unsigned_integer(&it_)) {
+ error_ = CborErrorIllegalType;
+ return cpp::fail(error_);
+ }
+ uint64_t ret;
+ error_ = cbor_value_get_uint64(&it_, &ret);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ error_ = cbor_value_advance(&it_);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ return ret;
+}
+
+auto ArrayDecoder::ParseSigned() -> cpp::result<int32_t, CborError> {
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ if (!cbor_value_is_unsigned_integer(&it_)) {
+ error_ = CborErrorIllegalType;
+ return cpp::fail(error_);
+ }
+ uint64_t ret;
+ error_ = cbor_value_get_uint64(&it_, &ret);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ error_ = cbor_value_advance(&it_);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ return ret;
+}
+
+static auto MapDecoder::Create(uint8_t *buffer, size_t buffer_len) -> cpp::result<std::unique_ptr<MapDecoder>, CborError> {
+ auto decoder = std::make_unique<MapDecoder>();
+ cbor_parser_init(buffer, buffer_len, &decoder->parser_, &decoder->root_);
+ if (!cbor_value_is_map(&decoder->root_)) {
+ return cpp::fail(CborErrorIllegalType);
+ }
+ CborError err = cbor_value_enter_container(&decoder->root_, &decoder->it_);
+ if (err != CborNoError) {
+ return cpp::fail(err);
+ }
+ return std::move(decoder);
+}
+
+auto MapDecoder::FindString(const std::string &key) -> std::optional<std::string> {
+ CborValue val;
+ if (error_ != CborNoError) {
+ return {};
+ }
+ if (cbor_value_map_find_value(&it_, key.c_str(), &val) != CborNoError) {
+ return {};
+ }
+ if (!cbor_value_is_byte_string(&val)) {
+ error_ = CborErrorIllegalType;
+ return {};
+ }
+ uint8_t *buf; size_t len;
+ error_ = cbor_value_dup_byte_string(&val, &buf, &len, NULL);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ std::string ret(buf, len);
+ free(buf);
+ return ret;
+}
+
+auto MapDecoder::FindUnsigned(const std::string &key) -> std::optional<uint32_t> {
+ CborValue val;
+ if (error_ != CborNoError) {
+ return {};
+ }
+ if (cbor_value_map_find_value(&it_, key.c_str(), &val) != CborNoError) {
+ return {};
+ }
+ if (!cbor_value_is_unsigned_integer(&val)) {
+ error_ = CborErrorIllegalType;
+ return {};
+ }
+ uint64_t ret;
+ error_ = cbor_value_get_uint64(&val, &ret);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ return ret;
+}
+
+auto MapDecoder::FindSigned(const std::string &key) -> std::optional<int32_t> {
+ CborValue val;
+ if (error_ != CborNoError) {
+ return {};
+ }
+ if (cbor_value_map_find_value(&it_, key.c_str(), &val) != CborNoError) {
+ return {};
+ }
+ if (!cbor_value_is_integer(&val)) {
+ error_ = CborErrorIllegalType;
+ return {};
+ }
+ int32_t ret;
+ error_ = cbor_value_get_int(&val, &ret);
+ if (error_ != CborNoError) {
+ return cpp::fail(error_);
+ }
+ return ret;
+}
+
+} // namespace cbor