diff options
author | Claudius Holeksa <mail@keldu.de> | 2023-04-29 18:03:24 +0200 |
---|---|---|
committer | Claudius Holeksa <mail@keldu.de> | 2023-04-29 18:03:24 +0200 |
commit | 937e67ff5ae9e770367bfee3100154b6a6957ce7 (patch) | |
tree | c09be3b6929ce6fd533c83564a89fe523be7a46f /forstio/codec/message_container.h | |
parent | 4e18f3798465ae952e15a2620177421d8b8c1f00 (diff) |
Added codec and ammended async build
Diffstat (limited to 'forstio/codec/message_container.h')
-rw-r--r-- | forstio/codec/message_container.h | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/forstio/codec/message_container.h b/forstio/codec/message_container.h new file mode 100644 index 0000000..191052a --- /dev/null +++ b/forstio/codec/message_container.h @@ -0,0 +1,246 @@ +#pragma once + +#include "schema.h" + +#include <variant> +#include <vector> + +namespace saw { +template <class T> class message_container; + +template <class T, class Container = message_container<T>> class message; + +template <size_t N, class... T> struct message_parameter_pack_type; + +template <class TN, class... T> +struct message_parameter_pack_type<0, TN, T...> { + using Type = TN; +}; + +template <size_t N, class TN, class... T> +struct message_parameter_pack_type<N, TN, T...> { + static_assert(sizeof...(T) > 0, "Exhausted parameters"); + using Type = typename message_parameter_pack_type<N - 1, T...>::Type; +}; + +template <class T, class... TL> struct MessageParameterPackIndex; + +template <class T, class... TL> struct MessageParameterPackIndex<T, T, TL...> { + static constexpr size_t Value = 0u; +}; + +template <class T, class TL0, class... TL> +struct MessageParameterPackIndex<T, TL0, TL...> { + static constexpr size_t Value = + 1u + MessageParameterPackIndex<T, TL...>::Value; +}; + +/* + * Nightmare inducing compiler problems found here. Somehow non-type + * StringLiterals cannot be resolved as non-type primitive template values can. + * This is the workaround + */ +template <string_literal V, string_literal Key0, string_literal... Keys> +struct message_parameter_key_pack_index_helper { + static constexpr size_t Value = + (V == Key0) + ? (0u) + : (1u + message_parameter_key_pack_index_helper<V, Keys...>::Value); +}; + +template <string_literal V, string_literal Key0> +struct message_parameter_key_pack_index_helper<V, Key0> { + static constexpr size_t Value = (V == Key0) ? (0u) : (1u); +}; + +template <string_literal V, string_literal... Keys> +struct message_parameter_key_pack_index { + static constexpr size_t Value = + message_parameter_key_pack_index_helper<V, Keys...>::Value; + static_assert(Value < sizeof...(Keys), + "Provided StringLiteral doesn't exist in searched list"); +}; + +template <class T> struct schema_is_array { + constexpr static bool Value = false; +}; + +template <class T> struct schema_is_array<schema::Array<T>> { + constexpr static bool Value = true; +}; + +template <class... V, string_literal... Keys> +class message_container<schema::Struct<schema::NamedMember<V, Keys>...>> { +private: + using ValueType = std::tuple<message<V, message_container<V>>...>; + ValueType values_; + +public: + using SchemaType = schema::Struct<schema::NamedMember<V, Keys>...>; + + template <size_t i> + using ElementType = typename message_parameter_pack_type< + i, message<V, message_container<V>>...>::Type; + + template <size_t i> ElementType<i> &get() { return std::get<i>(values_); } +}; + +/* + * Union storage + */ +template <class... V, string_literal... Keys> +class message_container<schema::Union<schema::NamedMember<V, Keys>...>> { +private: + using ValueType = std::variant<message<V, message_container<V>>...>; + ValueType value_; + +public: + using SchemaType = schema::Union<schema::NamedMember<V, Keys>...>; + + template <size_t i> + using ElementType = typename message_parameter_pack_type< + i, message<V, message_container<V>>...>::Type; + + template <size_t i> ElementType<i> &get() { + if (i != value_.index()) { + using MessageIV = + typename message_parameter_pack_type<i, V...>::Type; + value_ = message<MessageIV, message_container<MessageIV>>{}; + } + return std::get<i>(value_); + } + + size_t index() const noexcept { return value_.index(); } +}; + +/* + * Array storage + */ + +template <class T> class message_container<schema::Array<T>> { +private: + using ValueType = std::vector<message<T, message_container<T>>>; + ValueType values_; + +public: + using SchemaType = schema::Array<T>; + + using ElementType = message<T, message_container<T>>; + + message<T, message_container<T>> &get(size_t index) { + return values_.at(index); + } + + void resize(size_t size) { values_.resize(size); } + + size_t size() const { return values_.size(); } +}; + +/* + * Tuple storage + */ +template <class... T> class message_container<schema::Tuple<T...>> { +private: + using ValueType = std::tuple<message<T, message_container<T>>...>; + ValueType values_; + +public: + using SchemaType = schema::Tuple<T...>; + + template <size_t i> + using ElementType = typename message_parameter_pack_type< + i, message<T, message_container<T>>...>::Type; + + template <size_t i> ElementType<i> &get() { return std::get<i>(values_); } +}; + +/* + * Helper for the basic message container, so the class doesn't have to be + * specialized 10 times. + */ +template <class T> struct PrimitiveTypeHelper; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 1>> { + using Type = int8_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 2>> { + using Type = int16_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 4>> { + using Type = int32_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::SignedInteger, 8>> { + using Type = int64_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 1>> { + using Type = uint8_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 2>> { + using Type = uint16_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 4>> { + using Type = uint32_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::UnsignedInteger, 8>> { + using Type = uint64_t; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::FloatingPoint, 4>> { + using Type = float; +}; + +template <> +struct PrimitiveTypeHelper<schema::Primitive<schema::FloatingPoint, 8>> { + using Type = double; +}; + +template <class T, size_t N> class message_container<schema::Primitive<T, N>> { +public: + using SchemaType = schema::Primitive<T, N>; + using ValueType = + typename PrimitiveTypeHelper<schema::Primitive<T, N>>::Type; + +private: + ValueType value_; + +public: + message_container() : value_{0} {} + + void set(const ValueType &v) { value_ = v; } + + const ValueType &get() const { return value_; } +}; + +template <> class message_container<schema::String> { +public: + using SchemaType = schema::String; + using ValueType = std::string; + using ValueViewType = std::string_view; + +private: + ValueType value_; + +public: + void set(ValueType &&v) { value_ = std::move(v); } + void set(const ValueType &v) { value_ = v; } + void set(const ValueViewType v) { value_ = std::string{v}; } + + const ValueType &get() const { return value_; } +}; +} // namespace saw |