clang formatted and schema changes
parent
1f4eabffb9
commit
7dbbfc1d7f
|
@ -112,9 +112,6 @@ SpacesInCStyleCastParentheses: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
Standard: Cpp11
|
Standard: Cpp11
|
||||||
StatementMacros:
|
|
||||||
- Q_UNUSED
|
|
||||||
- QT_REQUIRE_VERSION
|
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseTab: ForContinuationAndIndentation
|
UseTab: ForContinuationAndIndentation
|
||||||
...
|
...
|
||||||
|
|
|
@ -29,8 +29,8 @@ def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, ta
|
||||||
sources.append( self.StaticObject( target=target_name, source=path ) )
|
sources.append( self.StaticObject( target=target_name, source=path ) )
|
||||||
pass
|
pass
|
||||||
|
|
||||||
env=Environment(CPPPATH=['#source/kelgin','#source','#','#driver'],
|
env=Environment(ENV=os.environ, CPPPATH=['#source/kelgin','#source','#','#driver'],
|
||||||
CXX='clang++',
|
CXX='g++',
|
||||||
CPPDEFINES=['GIN_UNIX'],
|
CPPDEFINES=['GIN_UNIX'],
|
||||||
CXXFLAGS=['-std=c++17','-g','-Wall','-Wextra'],
|
CXXFLAGS=['-std=c++17','-g','-Wall','-Wextra'],
|
||||||
LIBS=['gnutls'])
|
LIBS=['gnutls'])
|
||||||
|
|
|
@ -183,7 +183,7 @@ public:
|
||||||
* Useful for resource lifetime control.
|
* Useful for resource lifetime control.
|
||||||
*/
|
*/
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
[[nodiscard]] Conveyor<T> attach(Args &&...args);
|
[[nodiscard]] Conveyor<T> attach(Args &&... args);
|
||||||
|
|
||||||
/** @todo implement
|
/** @todo implement
|
||||||
* This method limits the total amount of passed elements
|
* This method limits the total amount of passed elements
|
||||||
|
@ -601,7 +601,7 @@ private:
|
||||||
std::tuple<Args...> attached_data;
|
std::tuple<Args...> attached_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AttachConveyorNode(Own<ConveyorNode> &&dep, Args &&...args)
|
AttachConveyorNode(Own<ConveyorNode> &&dep, Args &&... args)
|
||||||
: AttachConveyorNodeBase(std::move(dep)), attached_data{
|
: AttachConveyorNodeBase(std::move(dep)), attached_data{
|
||||||
std::move(args...)} {}
|
std::move(args...)} {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,7 +73,7 @@ template <typename T> Conveyor<T> Conveyor<T>::buffer(size_t size) {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
Conveyor<T> Conveyor<T>::attach(Args &&...args) {
|
Conveyor<T> Conveyor<T>::attach(Args &&... args) {
|
||||||
Own<AttachConveyorNode<Args...>> attach_node =
|
Own<AttachConveyorNode<Args...>> attach_node =
|
||||||
heap<AttachConveyorNode<Args...>>(std::move(node), std::move(args...));
|
heap<AttachConveyorNode<Args...>>(std::move(node), std::move(args...));
|
||||||
return Conveyor<T>{std::move(attach_node), storage};
|
return Conveyor<T>{std::move(attach_node), storage};
|
||||||
|
|
|
@ -39,11 +39,11 @@ template <typename T> using Our = std::shared_ptr<T>;
|
||||||
|
|
||||||
template <typename T> using Lent = std::weak_ptr<T>;
|
template <typename T> using Lent = std::weak_ptr<T>;
|
||||||
|
|
||||||
template <typename T, class... Args> Own<T> heap(Args &&...args) {
|
template <typename T, class... Args> Own<T> heap(Args &&... args) {
|
||||||
return Own<T>(new T(std::forward<Args>(args)...));
|
return Own<T>(new T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, class... Args> Our<T> share(Args &&...args) {
|
template <typename T, class... Args> Our<T> share(Args &&... args) {
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -835,9 +835,7 @@ Error JsonCodec::decodeValue(Own<DynamicMessage> &message, Buffer &buffer,
|
||||||
decodeNull(buffer);
|
decodeNull(buffer);
|
||||||
message = std::move(msg_null);
|
message = std::move(msg_null);
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: { return criticalError("Cannot identify next JSON value"); }
|
||||||
return criticalError("Cannot identify next JSON value");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
skipWhitespace(buffer);
|
skipWhitespace(buffer);
|
||||||
|
|
|
@ -4,122 +4,47 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "schema.h"
|
||||||
#include "string_literal.h"
|
#include "string_literal.h"
|
||||||
|
|
||||||
namespace gin {
|
namespace gin {
|
||||||
class Message {
|
class MessageBase {
|
||||||
protected:
|
protected:
|
||||||
bool set_explicitly = false;
|
bool set_explicitly = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename T> T &as() {
|
template <class T> T &as() {
|
||||||
static_assert(std::is_base_of<Message, T>());
|
static_assert(std::is_base_of<MessageBase, T>());
|
||||||
return reinterpret_cast<T &>(*this);
|
return dynamic_cast<T &>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> const T &as() const {
|
template <class T> const T &as() const {
|
||||||
static_assert(std::is_base_of<Message, T>());
|
static_assert(std::is_base_of<MessageBase, T>());
|
||||||
return reinterpret_cast<const T &>(*this);
|
return dynamic_cast<const T &>(*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* Representing all primitive types
|
* Representing all message types
|
||||||
|
* Description which type to use happens through the use of the schema classes in schema.h
|
||||||
|
* The message classes are a container class which either contains singular types or has
|
||||||
|
* some form of encoding in a buffer present
|
||||||
*/
|
*/
|
||||||
template <typename T> class MessagePrimitive : public Message {
|
|
||||||
|
template <class... V, StringLiteral... Keys, class Container>
|
||||||
|
class Message<schema::Struct<schema::NamedMember<V, Keys>...>, Container> final
|
||||||
|
: public MessageBase {
|
||||||
private:
|
private:
|
||||||
T value;
|
using SchemaType = schema::Struct<schema::NamedMember<V,Keys>...>;
|
||||||
|
using MessageType =
|
||||||
|
Message<SchemaType, Container>;
|
||||||
|
Container container;
|
||||||
|
|
||||||
friend class Builder;
|
static_assert(std::is_same_v<SchemaType, typename Container::SchemaType>, "Container should have same Schema as Message");
|
||||||
friend class Reader;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MessagePrimitive() = default;
|
|
||||||
|
|
||||||
class Reader;
|
|
||||||
class Builder {
|
|
||||||
private:
|
|
||||||
MessagePrimitive<T> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Builder(MessagePrimitive<T> &message) : message{message} {}
|
|
||||||
|
|
||||||
constexpr void set(const T &value) {
|
|
||||||
message.value = value;
|
|
||||||
message.set_explicitly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reader asReader() { return Reader{message}; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Reader {
|
|
||||||
private:
|
|
||||||
MessagePrimitive<T> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Reader(MessagePrimitive<T> &message) : message{message} {}
|
|
||||||
|
|
||||||
const T &get() const { return message.value; }
|
|
||||||
|
|
||||||
bool isSetExplicitly() const { return message.set_explicitly; }
|
|
||||||
|
|
||||||
Builder asBuilder() { return Builder{message}; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> class MessagePrimitive<std::string> : public Message {
|
|
||||||
private:
|
|
||||||
std::string value;
|
|
||||||
|
|
||||||
friend class Builder;
|
|
||||||
friend class Reader;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MessagePrimitive() = default;
|
|
||||||
|
|
||||||
class Reader;
|
|
||||||
class Builder {
|
|
||||||
private:
|
|
||||||
MessagePrimitive<std::string> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Builder(MessagePrimitive<std::string> &message) : message{message} {}
|
|
||||||
|
|
||||||
void set(std::string_view value) {
|
|
||||||
message.value = std::string{value};
|
|
||||||
message.set_explicitly = true;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
void set(std::string &&value) {
|
|
||||||
message.value = std::move(value);
|
|
||||||
message.set_explicitly = true;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Reader asReader() { return Reader{message}; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Reader {
|
|
||||||
private:
|
|
||||||
MessagePrimitive<std::string> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Reader(MessagePrimitive<std::string> &message) : message{message} {}
|
|
||||||
|
|
||||||
std::string_view get() const { return std::string_view{message.value}; }
|
|
||||||
|
|
||||||
bool isSetExplicitly() const { return message.set_explicitly; }
|
|
||||||
|
|
||||||
Builder asBuilder() { return Builder{message}; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... Args> class MessageList : public Message {
|
|
||||||
private:
|
|
||||||
using tuple_type = std::tuple<Args...>;
|
|
||||||
tuple_type elements;
|
|
||||||
friend class Builder;
|
friend class Builder;
|
||||||
friend class Reader;
|
friend class Reader;
|
||||||
|
|
||||||
|
@ -127,312 +52,53 @@ public:
|
||||||
class Reader;
|
class Reader;
|
||||||
class Builder {
|
class Builder {
|
||||||
private:
|
private:
|
||||||
MessageList<Args...> &message;
|
MessageType &message;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Builder(MessageList<Args...> &message) : message{message} {
|
Builder(MessageType &msg) : message{msg} {}
|
||||||
message.set_explicitly = true;
|
|
||||||
|
Reader asReader() { return Reader{MessageType & message}; }
|
||||||
|
|
||||||
|
template<size_t i>
|
||||||
|
typename Container::Element<i>::Builder init(){
|
||||||
|
return typename Container::Element<i>::Builder{message.container.get<i>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t i>
|
template<StringLiteral Literal> typename Container::Element<i>::Builder init(){
|
||||||
constexpr typename std::tuple_element_t<i, tuple_type>::Builder init() {
|
constexpr size_t i = MessageParameterPackIndex<Literal, Keys...>::Value;
|
||||||
std::tuple_element_t<i, tuple_type> &msg_ref =
|
|
||||||
std::get<i>(message.elements);
|
|
||||||
return
|
|
||||||
typename std::tuple_element_t<i, tuple_type>::Builder{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
Reader asReader() { return Reader{message}; }
|
return init<i>();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
private:
|
private:
|
||||||
MessageList<Args...> &message;
|
MessageType &message;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Reader(MessageList<Args...> &message) : message{message} {}
|
Reader(MessageType &msg) : message{msg} {}
|
||||||
|
|
||||||
template <size_t i>
|
Builder asBuilder() { return Builder{MessageType & message}; }
|
||||||
constexpr typename std::tuple_element_t<i, tuple_type>::Reader get() {
|
|
||||||
return std::get<i>(message.elements);
|
template<size_t i>
|
||||||
|
typename Container::Element<i>::Reader get(){
|
||||||
|
return typename Container::Element<i>::Reader{message.container.get<i>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const { return std::tuple_size<tuple_type>::value; }
|
template<StringLiteral Literal> typename Container::Element<i>::Reader get(){
|
||||||
|
constexpr size_t i = MessageParameterPackIndex<Literal, Keys...>::Value;
|
||||||
|
|
||||||
bool isSetExplicitly() const { return message.set_explicitly; }
|
return get<i>();
|
||||||
|
}
|
||||||
Builder asBuilder() { return Builder{message}; }
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @todo how to do initialization?
|
template<class T, size_t N, class Container>
|
||||||
template <typename T> class MessageArray : public Message {
|
class Message<schema::Primitive<T,N>, Container> final : public MessageBase {
|
||||||
private:
|
private:
|
||||||
using array_type = std::vector<T>;
|
Container container;
|
||||||
array_type elements;
|
|
||||||
friend class Builder;
|
|
||||||
friend class Reader;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Reader;
|
|
||||||
class Builder {
|
|
||||||
private:
|
|
||||||
MessageArray<T> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Builder(MessageArray<T> &message) : message{message} {
|
|
||||||
message.set_explicitly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr typename T::Builder init(size_t i) {
|
|
||||||
T &msg_ref = message.elements.at(i);
|
|
||||||
return typename T::Builder{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
Reader asReader() { return Reader{message}; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class Reader {
|
|
||||||
private:
|
|
||||||
MessageArray<T> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Reader(MessageArray<T> &message) : message{message} {}
|
|
||||||
|
|
||||||
constexpr typename T::Reader get(size_t i) {
|
|
||||||
return message.elements.at(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const { return message.elements.size(); }
|
|
||||||
|
|
||||||
bool isSetExplicitly() const { return message.set_explicitly; }
|
|
||||||
|
|
||||||
Builder asBuilder() { return Builder{message}; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename K> struct MessageStructMember;
|
|
||||||
|
|
||||||
template <typename T, typename C, C... Chars>
|
|
||||||
struct MessageStructMember<T, StringLiteral<C, Chars...>> {
|
|
||||||
T value;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper structs which retrieve
|
|
||||||
* the index of a parameter pack based on the index
|
|
||||||
* or
|
|
||||||
* a type based on the index
|
|
||||||
* Pass N as the index for the desired type
|
|
||||||
* or
|
|
||||||
* a type to get the first occurence of a type index
|
|
||||||
*/
|
|
||||||
template <size_t N, typename... T> struct ParameterPackType;
|
|
||||||
|
|
||||||
template <typename T, typename... TL> struct ParameterPackType<0, T, TL...> {
|
|
||||||
using type = T;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t N, typename T, typename... TL>
|
|
||||||
struct ParameterPackType<N, T, TL...> {
|
|
||||||
using type = typename ParameterPackType<N - 1, TL...>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename... TL> struct ParameterPackIndex;
|
|
||||||
|
|
||||||
template <typename T, typename... TL> struct ParameterPackIndex<T, T, TL...> {
|
|
||||||
static constexpr size_t value = 0u;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename TL0, typename... TL>
|
|
||||||
struct ParameterPackIndex<T, TL0, TL...> {
|
|
||||||
static constexpr size_t value = 1u + ParameterPackIndex<T, TL...>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... T> class MessageStruct;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Since no value is retrieved from the keys, I only need a value tuple
|
|
||||||
*/
|
|
||||||
template <typename... V, typename... K>
|
|
||||||
class MessageStruct<MessageStructMember<V, K>...> : public Message {
|
|
||||||
private:
|
|
||||||
using value_type = std::tuple<V...>;
|
|
||||||
value_type values;
|
|
||||||
friend class Builder;
|
|
||||||
friend class Reader;
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Reader;
|
|
||||||
class Builder {
|
|
||||||
private:
|
|
||||||
MessageStruct<MessageStructMember<V, K>...> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Builder(MessageStruct<MessageStructMember<V, K>...> &message)
|
|
||||||
: message{message} {
|
|
||||||
message.set_explicitly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t i>
|
|
||||||
constexpr typename std::tuple_element_t<i, value_type>::Builder init() {
|
|
||||||
std::tuple_element_t<i, value_type> &msg_ref =
|
|
||||||
std::get<i>(message.values);
|
|
||||||
return
|
|
||||||
typename std::tuple_element_t<i, value_type>::Builder{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
typename std::tuple_element_t<ParameterPackIndex<T, K...>::value,
|
|
||||||
value_type>::Builder
|
|
||||||
init() {
|
|
||||||
std::tuple_element_t<ParameterPackIndex<T, K...>::value, value_type>
|
|
||||||
&msg_ref = std::get<ParameterPackIndex<T, K...>::value>(
|
|
||||||
message.values);
|
|
||||||
return typename std::tuple_element_t<
|
|
||||||
ParameterPackIndex<T, K...>::value, value_type>::Builder{
|
|
||||||
msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
Reader asReader() { return Reader{message}; }
|
|
||||||
};
|
|
||||||
class Reader {
|
|
||||||
private:
|
|
||||||
MessageStruct<MessageStructMember<V, K>...> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Reader(MessageStruct<MessageStructMember<V, K>...> &message)
|
|
||||||
: message{message} {}
|
|
||||||
|
|
||||||
template <size_t i>
|
|
||||||
constexpr typename std::tuple_element_t<i, value_type>::Reader get() {
|
|
||||||
std::tuple_element_t<i, value_type> &msg_ref =
|
|
||||||
std::get<i>(message.values);
|
|
||||||
return
|
|
||||||
typename std::tuple_element_t<i, value_type>::Reader{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
typename std::tuple_element_t<ParameterPackIndex<T, K...>::value,
|
|
||||||
value_type>::Reader
|
|
||||||
get() {
|
|
||||||
std::tuple_element_t<ParameterPackIndex<T, K...>::value, value_type>
|
|
||||||
&msg_ref = std::get<ParameterPackIndex<T, K...>::value>(
|
|
||||||
message.values);
|
|
||||||
return typename std::tuple_element_t<
|
|
||||||
ParameterPackIndex<T, K...>::value, value_type>::Reader{
|
|
||||||
msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr size_t size() { return std::tuple_size<value_type>::value; }
|
|
||||||
|
|
||||||
bool isSetExplicitly() const { return message.set_explicitly; }
|
|
||||||
|
|
||||||
Builder asBuilder() { return Builder{message}; }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename K> struct MessageUnionMember;
|
|
||||||
|
|
||||||
template <typename T, typename C, C... Chars>
|
|
||||||
struct MessageUnionMember<T, StringLiteral<C, Chars...>> {
|
|
||||||
T value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename... T> class MessageUnion;
|
|
||||||
|
|
||||||
/// @todo copied from MessageStruct, but the acces is different, since
|
|
||||||
/// only one value can be set at the same time.
|
|
||||||
template <typename... V, typename... K>
|
|
||||||
class MessageUnion<MessageUnionMember<V, K>...> : public Message {
|
|
||||||
private:
|
|
||||||
using value_type = std::variant<MessageUnionMember<V, K>...>;
|
|
||||||
value_type values;
|
|
||||||
friend class Builder;
|
|
||||||
friend class Reader;
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Reader;
|
|
||||||
class Builder {
|
|
||||||
private:
|
|
||||||
MessageUnion<MessageUnionMember<V, K>...> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Builder(MessageUnion<MessageUnionMember<V, K>...> &message)
|
|
||||||
: message{message} {
|
|
||||||
message.set_explicitly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t i>
|
|
||||||
constexpr typename ParameterPackType<i, V...>::type::Builder init() {
|
|
||||||
message.values =
|
|
||||||
typename std::variant_alternative_t<i, value_type>{};
|
|
||||||
typename ParameterPackType<i, V...>::type &msg_ref =
|
|
||||||
std::get<i>(message.values).value;
|
|
||||||
return typename ParameterPackType<i, V...>::type::Builder{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr typename ParameterPackType<ParameterPackIndex<T, K...>::value,
|
|
||||||
V...>::type::Builder
|
|
||||||
init() {
|
|
||||||
message.values = typename std::variant_alternative_t<
|
|
||||||
ParameterPackIndex<T, K...>::value, value_type>{};
|
|
||||||
typename ParameterPackType<ParameterPackIndex<T, K...>::value,
|
|
||||||
V...>::type &msg_ref =
|
|
||||||
std::get<ParameterPackIndex<T, K...>::value>(message.values)
|
|
||||||
.value;
|
|
||||||
return
|
|
||||||
typename ParameterPackType<ParameterPackIndex<T, K...>::value,
|
|
||||||
V...>::type::Builder{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
Reader asReader() { return Reader{message}; }
|
|
||||||
};
|
|
||||||
class Reader {
|
|
||||||
private:
|
|
||||||
MessageUnion<MessageUnionMember<V, K>...> &message;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Reader(MessageUnion<MessageUnionMember<V, K>...> &message)
|
|
||||||
: message{message} {}
|
|
||||||
|
|
||||||
template <size_t i>
|
|
||||||
constexpr typename ParameterPackType<i, V...>::type::Reader get() {
|
|
||||||
typename ParameterPackType<i, V...>::type &msg_ref =
|
|
||||||
std::get<i>(message.values).value;
|
|
||||||
return typename ParameterPackType<i, V...>::type::Reader{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr typename ParameterPackType<ParameterPackIndex<T, K...>::value,
|
|
||||||
V...>::type::Reader
|
|
||||||
get() {
|
|
||||||
typename ParameterPackType<ParameterPackIndex<T, K...>::value,
|
|
||||||
V...>::type &msg_ref =
|
|
||||||
std::get<ParameterPackIndex<T, K...>::value>(message.values)
|
|
||||||
.value;
|
|
||||||
return
|
|
||||||
typename ParameterPackType<ParameterPackIndex<T, K...>::value,
|
|
||||||
V...>::type::Reader{msg_ref};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> constexpr bool holdsAlternative() {
|
|
||||||
return std::holds_alternative<std::variant_alternative_t<
|
|
||||||
ParameterPackIndex<T, K...>::value, value_type>>(
|
|
||||||
message.values);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t index() const { return message.values.index(); }
|
|
||||||
|
|
||||||
bool isSetExplicitly() const { return message.set_explicitly; }
|
|
||||||
|
|
||||||
constexpr size_t size() { return std::variant_size<value_type>::value; }
|
|
||||||
|
|
||||||
Builder asBuilder() { return Builder{message}; }
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MessageReader {
|
class MessageReader {
|
||||||
|
@ -454,5 +120,5 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline MessageBuilder heapMessageBuilder() { return MessageBuilder{}; }
|
inline MessageBuilder messageBuilder() { return MessageBuilder{}; }
|
||||||
} // namespace gin
|
} // namespace gin
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "schema.h"
|
||||||
|
|
||||||
|
namespace gin {
|
||||||
|
template<class T>
|
||||||
|
class MessageContainer;
|
||||||
|
|
||||||
|
template <class T, class Container> class Message;
|
||||||
|
|
||||||
|
template <size_t N, class... T> struct MessageParameterPackType ;
|
||||||
|
|
||||||
|
template <class TN, class... T> struct MessageParameterPackType <0, TN, T...> {
|
||||||
|
using Type = T;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <size_t N, class TN, class... T> struct MessageParameterPackType <N, TN, T...> {
|
||||||
|
using Type = typename MessageParameterPackType<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;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class... V, class... K> class MessageContainer<schema::Struct<schema::NamedMember<V,K>...>> {
|
||||||
|
private:
|
||||||
|
using ValueType = std::tuple<Message<V, MessageContainer<V>>...>;
|
||||||
|
ValueType values;
|
||||||
|
public:
|
||||||
|
using SchemaType = schema::Struct<schema::NamedMember<V,K>...>;
|
||||||
|
|
||||||
|
template<size_t i>
|
||||||
|
using Element = MessageParameterPackType<N, Message<V,MessageContainer<V>>...>;
|
||||||
|
|
||||||
|
template<size_t i>
|
||||||
|
Element<i>& get(){
|
||||||
|
return std::get<i>(values);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,14 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kelgin/string_literal.h>
|
#include "string_literal.h"
|
||||||
|
|
||||||
namespace gin {
|
namespace gin {
|
||||||
namespace schema {
|
namespace schema {
|
||||||
|
|
||||||
template <typename T, typename K> struct NamedMember;
|
template <class T, StringLiteral Literal> struct NamedMember {};
|
||||||
|
|
||||||
template <typename T, typename C, C... Chars>
|
|
||||||
struct NamedMember<T, StringLiteral<C, C...>> {};
|
|
||||||
|
|
||||||
template <typename... T> struct Struct {};
|
template <typename... T> struct Struct {};
|
||||||
|
|
||||||
|
@ -21,5 +18,38 @@ template <typename... V, typename... K> struct Union<NamedMember<V, K>...> {};
|
||||||
template <typename T> struct Array {};
|
template <typename T> struct Array {};
|
||||||
|
|
||||||
struct String {};
|
struct String {};
|
||||||
|
|
||||||
|
struct SignedIntegral {};
|
||||||
|
struct UnsignedIntegral {};
|
||||||
|
struct FloatingPoint {};
|
||||||
|
|
||||||
|
template<class T, size_t N>
|
||||||
|
struct Primitive {
|
||||||
|
static_assert(
|
||||||
|
(
|
||||||
|
(std::is_same_v<T, SignedIntegral> || std::is_same_v<T,UnsignedIntegral>) &&
|
||||||
|
(N == 1 || N == 2 || N == 4 || N == 8)
|
||||||
|
)||
|
||||||
|
(
|
||||||
|
std::is_same_v<T,FloatingPoint> &&
|
||||||
|
(N==4 || N == 8)
|
||||||
|
),
|
||||||
|
"Primitive Type is not supported"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
using Int8 = Primitive<SignedIntegral, 1>;
|
||||||
|
using Int16 = Primitive<SignedIntegral, 2>;
|
||||||
|
using Int32 = Primitive<SignedIntegral, 4>;
|
||||||
|
using Int64 = Primitive<SignedIntegral, 8>;
|
||||||
|
|
||||||
|
using UInt8 = Primitive<UnsignedIntegral, 1>;
|
||||||
|
using UInt16 = Primitive<UnsignedIntegral, 2>;
|
||||||
|
using UInt32 = Primitive<UnsignedIntegral, 4>;
|
||||||
|
using UInt64 = Primitive<UnsignedIntegral, 8>;
|
||||||
|
|
||||||
|
using Float32 = Primitive<FloatingPoint, 4>;
|
||||||
|
using Float64 = Primitive<FloatingPoint, 8>;
|
||||||
|
|
||||||
} // namespace schema
|
} // namespace schema
|
||||||
} // namespace gin
|
} // namespace gin
|
||||||
|
|
|
@ -9,17 +9,23 @@ namespace gin {
|
||||||
* literal. It guarantees compile time uniqueness and thus allows using strings
|
* literal. It guarantees compile time uniqueness and thus allows using strings
|
||||||
* in template parameters.
|
* in template parameters.
|
||||||
*/
|
*/
|
||||||
template <typename T, T... Chars> class StringLiteral {
|
template <template CharT, size_t N> class StringLiteral {
|
||||||
public:
|
public:
|
||||||
static constexpr std::array<T, sizeof...(Chars) + 1u> data = {Chars...,
|
constexpr StringLiteral(const CharT (&input)[N]) noexcept {
|
||||||
'\0'};
|
for(size_t i = 0; i < N ; ++i){
|
||||||
static constexpr std::string_view view() {
|
data[i] = input[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<CharT, N> data{};
|
||||||
|
|
||||||
|
constexpr std::string_view view() const noexcept {
|
||||||
return std::string_view{data.data()};
|
return std::string_view{data.data()};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace gin
|
|
||||||
|
|
||||||
template <typename T, T... Chars>
|
template <typename T, T... Chars>
|
||||||
constexpr gin::StringLiteral<T, Chars...> operator""_t() {
|
constexpr gin::StringLiteral<T, sizeof...(Chars)> operator""_key() {
|
||||||
return {};
|
return gin::StringLiteral<T,sizeof...(Chars)+1u>{Chars..., '\0'};
|
||||||
}
|
}
|
||||||
|
} // namespace gin
|
||||||
|
|
Loading…
Reference in New Issue