parent
222c810b07
commit
c36208016e
@ -1,7 +1,7 @@ |
||||
idf_component_register( |
||||
SRCS "audio_decoder.cpp" "audio_task.cpp" "chunk.cpp" "fatfs_audio_input.cpp" |
||||
"stream_info.cpp" |
||||
"stream_info.cpp" "stream_message.cpp" |
||||
INCLUDE_DIRS "include" |
||||
REQUIRES "codecs" "drivers" "cbor_wrapper" "result" "tasks") |
||||
REQUIRES "codecs" "drivers" "cbor" "result" "tasks") |
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) |
||||
|
@ -1,11 +1,60 @@ |
||||
#pragma once |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include <functional> |
||||
#include <optional> |
||||
|
||||
#include "cbor.h" |
||||
#include "result.hpp" |
||||
|
||||
namespace audio { |
||||
|
||||
extern const int kEncoderFlags; |
||||
extern const int kDecoderFlags; |
||||
|
||||
enum MessageType { |
||||
TYPE_UNKNOWN, |
||||
TYPE_CHUNK_HEADER, |
||||
TYPE_STREAM_INFO, |
||||
}; |
||||
|
||||
template <typename Writer> |
||||
auto WriteMessage(MessageType type, |
||||
Writer&& writer, |
||||
uint8_t* buffer, |
||||
size_t length) -> cpp::result<size_t, CborError> { |
||||
CborEncoder root; |
||||
CborEncoder container; |
||||
|
||||
cbor_encoder_init(&root, buffer, length, kEncoderFlags); |
||||
cbor_encoder_create_array(&root, &container, 2); |
||||
cbor_encode_uint(&container, type); |
||||
|
||||
std::optional<CborError> inner_err = std::invoke(writer, container); |
||||
if (inner_err) { |
||||
return cpp::fail(inner_err.value()); |
||||
} |
||||
|
||||
cbor_encoder_close_container(&root, &container); |
||||
return cbor_encoder_get_buffer_size(&root, buffer); |
||||
} |
||||
|
||||
template <typename Result, typename Reader> |
||||
auto ReadMessage(Reader&& reader, uint8_t* buffer, size_t length) |
||||
-> cpp::result<Result, CborError> { |
||||
CborParser parser; |
||||
CborValue root; |
||||
CborValue container; |
||||
|
||||
cbor_parser_init(buffer, length, kDecoderFlags, &parser, &root); |
||||
cbor_value_enter_container(&root, &container); |
||||
// Skip the type header
|
||||
cbor_value_advance_fixed(&container); |
||||
|
||||
return std::invoke(reader, container); |
||||
} |
||||
|
||||
auto ReadMessageType(uint8_t* buffer, size_t length) -> MessageType; |
||||
|
||||
} // namespace audio
|
||||
|
@ -0,0 +1,26 @@ |
||||
#include "stream_message.hpp" |
||||
|
||||
#include <cstdint> |
||||
|
||||
#include "cbor.h" |
||||
|
||||
namespace audio { |
||||
|
||||
const int kEncoderFlags = 0; |
||||
const int kDecoderFlags = 0; |
||||
|
||||
auto ReadMessageType(uint8_t* buffer, size_t length) -> MessageType { |
||||
CborParser parser; |
||||
CborValue root; |
||||
CborValue container; |
||||
|
||||
cbor_parser_init(buffer, length, kDecoderFlags, &parser, &root); |
||||
cbor_value_enter_container(&root, &container); |
||||
|
||||
uint64_t header = 0; |
||||
cbor_value_get_uint64(&container, &header); |
||||
|
||||
return static_cast<MessageType>(header); |
||||
} |
||||
|
||||
} // namespace audio
|
@ -1,6 +0,0 @@ |
||||
idf_component_register( |
||||
SRCS "cbor_decoder.cpp" "cbor_encoder.cpp" |
||||
INCLUDE_DIRS "include" |
||||
REQUIRES "cbor" "result") |
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS}) |
@ -1,112 +0,0 @@ |
||||
#include "cbor_decoder.hpp" |
||||
|
||||
#include <cstdint> |
||||
#include <string> |
||||
|
||||
#include "cbor.h" |
||||
#include "result.hpp" |
||||
|
||||
static const int kDecoderFlags = 0; |
||||
|
||||
namespace cbor { |
||||
|
||||
auto parse_stdstring(const CborValue* val, std::string* out) -> CborError { |
||||
char* buf; |
||||
size_t len; |
||||
CborError err = cbor_value_dup_text_string(val, &buf, &len, NULL); |
||||
if (err != CborNoError) { |
||||
return err; |
||||
} |
||||
*out = std::string(buf, len); |
||||
free(buf); |
||||
return err; |
||||
} |
||||
|
||||
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, kDecoderFlags, &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::Create(CborValue& root) |
||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError> { |
||||
auto decoder = std::make_unique<ArrayDecoder>(); |
||||
decoder->root_ = 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); |
||||
} |
||||
|
||||
template <> |
||||
auto ArrayDecoder::NextValue() -> cpp::result<int64_t, CborError> { |
||||
return NextValue(&cbor_value_is_integer, &cbor_value_get_int); |
||||
} |
||||
template <> |
||||
auto ArrayDecoder::NextValue() -> cpp::result<uint64_t, CborError> { |
||||
return NextValue(&cbor_value_is_unsigned_integer, &cbor_value_get_uint64); |
||||
} |
||||
template <> |
||||
auto ArrayDecoder::NextValue() -> cpp::result<std::string, CborError> { |
||||
return NextValue(&cbor_value_is_byte_string, &parse_stdstring); |
||||
} |
||||
|
||||
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, kDecoderFlags, &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::Create(CborValue& root) |
||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError> { |
||||
auto decoder = std::make_unique<MapDecoder>(); |
||||
decoder->root_ = 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); |
||||
} |
||||
|
||||
template <> |
||||
auto MapDecoder::FindValue(const std::string& key) -> std::optional<int64_t> { |
||||
return FindValue(key, &cbor_value_is_integer, &cbor_value_get_int); |
||||
} |
||||
template <> |
||||
auto MapDecoder::FindValue(const std::string& key) -> std::optional<uint64_t> { |
||||
return FindValue(key, &cbor_value_is_unsigned_integer, |
||||
&cbor_value_get_uint64); |
||||
} |
||||
template <> |
||||
auto MapDecoder::FindValue(const std::string& key) |
||||
-> std::optional<std::string> { |
||||
return FindValue(key, &cbor_value_is_byte_string, &parse_stdstring); |
||||
} |
||||
|
||||
} // namespace cbor
|
@ -1,63 +0,0 @@ |
||||
#include "cbor_encoder.hpp" |
||||
|
||||
#include <cstdint> |
||||
#include <string> |
||||
|
||||
#include "cbor.h" |
||||
#include "cbor_decoder.hpp" |
||||
#include "result.hpp" |
||||
|
||||
namespace cbor { |
||||
|
||||
static const int kEncoderFlags = 0; |
||||
|
||||
Encoder::Encoder(ContainerType type, |
||||
uint32_t container_len, |
||||
uint8_t* buffer, |
||||
size_t buffer_len) { |
||||
cbor_encoder_init(&root_encoder_, buffer, buffer_len, kEncoderFlags); |
||||
switch (type) { |
||||
case CONTAINER_ARRAY: |
||||
error_ = cbor_encoder_create_array(&root_encoder_, &container_encoder_, |
||||
container_len); |
||||
break; |
||||
case CONTAINER_MAP: |
||||
error_ = cbor_encoder_create_map(&root_encoder_, &container_encoder_, |
||||
container_len); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
auto Encoder::WriteValue(const std::string& val) -> void { |
||||
if (error_ != CborNoError) { |
||||
return; |
||||
} |
||||
error_ = |
||||
cbor_encode_text_string(&container_encoder_, val.c_str(), val.size()); |
||||
} |
||||
|
||||
auto Encoder::WriteValue(uint32_t val) -> void { |
||||
if (error_ != CborNoError) { |
||||
return; |
||||
} |
||||
error_ = cbor_encode_uint(&container_encoder_, val); |
||||
} |
||||
|
||||
auto Encoder::WriteValue(int32_t val) -> void { |
||||
if (error_ != CborNoError) { |
||||
return; |
||||
} |
||||
error_ = cbor_encode_int(&container_encoder_, val); |
||||
} |
||||
|
||||
auto Encoder::Finish() -> cpp::result<size_t, CborError> { |
||||
if (error_ == CborNoError) { |
||||
error_ = cbor_encoder_close_container(&root_encoder_, &container_encoder_); |
||||
} |
||||
if (error_ != CborNoError) { |
||||
return cpp::fail(error_); |
||||
} |
||||
return cbor_encoder_get_buffer_size(&root_encoder_, buffer_); |
||||
} |
||||
|
||||
} // namespace cbor
|
@ -1,113 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include <cstdint> |
||||
#include <string> |
||||
|
||||
#include "cbor.h" |
||||
#include "result.hpp" |
||||
|
||||
namespace cbor { |
||||
|
||||
class ArrayDecoder { |
||||
public: |
||||
static auto Create(uint8_t* buffer, size_t buffer_len) |
||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError>; |
||||
|
||||
static auto Create(CborValue& root) |
||||
-> cpp::result<std::unique_ptr<ArrayDecoder>, CborError>; |
||||
|
||||
ArrayDecoder() {} |
||||
|
||||
template <typename T> |
||||
auto NextValue() -> cpp::result<T, CborError>; |
||||
|
||||
template <typename T> |
||||
auto NextValue(bool (*is_valid)(const CborValue*), |
||||
CborError (*parse)(const CborValue*, T*)) |
||||
-> cpp::result<T, CborError> { |
||||
if (error_ != CborNoError) { |
||||
return cpp::fail(error_); |
||||
} |
||||
if (!is_valid(&it_)) { |
||||
error_ = CborErrorIllegalType; |
||||
return cpp::fail(error_); |
||||
} |
||||
T ret; |
||||
error_ = parse(&it_, &ret); |
||||
if (error_ != CborNoError) { |
||||
return cpp::fail(error_); |
||||
} |
||||
error_ = cbor_value_advance(&it_); |
||||
if (error_ != CborNoError) { |
||||
return cpp::fail(error_); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
auto Failed() -> CborError { return error_; } |
||||
|
||||
auto Iterator() -> CborValue& { return it_; } |
||||
|
||||
ArrayDecoder(const ArrayDecoder&) = delete; |
||||
ArrayDecoder& operator=(const ArrayDecoder&) = delete; |
||||
|
||||
private: |
||||
CborParser parser_; |
||||
CborValue root_; |
||||
|
||||
CborValue it_; |
||||
CborError error_ = CborNoError; |
||||
}; |
||||
|
||||
class MapDecoder { |
||||
public: |
||||
static auto Create(uint8_t* buffer, size_t buffer_len) |
||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError>; |
||||
|
||||
static auto Create(CborValue& root) |
||||
-> cpp::result<std::unique_ptr<MapDecoder>, CborError>; |
||||
|
||||
MapDecoder() {} |
||||
|
||||
template <typename T> |
||||
auto FindValue(const std::string& key) -> std::optional<T>; |
||||
|
||||
template <typename T> |
||||
auto FindValue(const std::string& key, |
||||
bool (*is_valid)(const CborValue*), |
||||
CborError (*parse)(const CborValue*, T*)) -> std::optional<T> { |
||||
if (error_ != CborNoError) { |
||||
return {}; |
||||
} |
||||
CborValue val; |
||||
if (cbor_value_map_find_value(&it_, key.c_str(), &val) != CborNoError) { |
||||
return {}; |
||||
} |
||||
if (!is_valid(&val)) { |
||||
error_ = CborErrorIllegalType; |
||||
return {}; |
||||
} |
||||
T ret; |
||||
error_ = parse(&val, &ret); |
||||
if (error_ != CborNoError) { |
||||
return {}; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
auto Failed() -> CborError { return error_; } |
||||
|
||||
MapDecoder(const MapDecoder&) = delete; |
||||
MapDecoder& operator=(const MapDecoder&) = delete; |
||||
|
||||
private: |
||||
CborParser parser_; |
||||
CborValue root_; |
||||
|
||||
CborValue it_; |
||||
CborError error_ = CborNoError; |
||||
}; |
||||
|
||||
} // namespace cbor
|
@ -1,52 +0,0 @@ |
||||
#pragma once |
||||
|
||||
#include <cstdint> |
||||
#include <optional> |
||||
#include <string> |
||||
|
||||
#include "cbor.h" |
||||
#include "result.hpp" |
||||
|
||||
namespace cbor { |
||||
|
||||
enum ContainerType { CONTAINER_ARRAY, CONTAINER_MAP }; |
||||
|
||||
class Encoder { |
||||
public: |
||||
Encoder(ContainerType type, |
||||
uint32_t container_len, |
||||
uint8_t* buffer, |
||||
size_t buffer_len); |
||||
|
||||
auto WriteValue(const std::string& val) -> void; |
||||
auto WriteValue(uint32_t val) -> void; |
||||
auto WriteValue(int32_t val) -> void; |
||||
|
||||
template <typename T> |
||||
auto WriteKeyValue(const std::string& key, const T&& val) -> void { |
||||
WriteValue(key); |
||||
WriteValue(val); |
||||
} |
||||
|
||||
template <typename T> |
||||
auto WriteKeyValue(const std::string& key, const std::optional<T>& val) |
||||
-> void { |
||||
if (val) { |
||||
WriteKeyValue<T>(key, val.value()); |
||||
} |
||||
} |
||||
|
||||
auto Finish() -> cpp::result<size_t, CborError>; |
||||
|
||||
Encoder(const Encoder&) = delete; |
||||
Encoder& operator=(const Encoder&) = delete; |
||||
|
||||
private: |
||||
uint8_t* buffer_; |
||||
CborEncoder root_encoder_; |
||||
CborEncoder container_encoder_; |
||||
|
||||
CborError error_ = CborNoError; |
||||
}; |
||||
|
||||
} // namespace cbor
|
Loading…
Reference in new issue