Skip to content

Commit

Permalink
Added support for all other formats
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Urbanke committed Jun 18, 2024
1 parent b09f386 commit 84114c3
Show file tree
Hide file tree
Showing 22 changed files with 320 additions and 25 deletions.
23 changes: 23 additions & 0 deletions include/rfl/bson/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@ struct Reader {
T::from_bson_obj(var);
});

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType& _arr) const noexcept {
bson_t b;
bson_iter_t iter;
const auto doc = _arr.val_->value.v_doc;
if (bson_init_static(&b, doc.data, doc.data_len)) {
if (bson_iter_init(&iter, &b)) {
size_t i = 0;
while (bson_iter_next(&iter)) {
if (i == _idx) {
return to_input_var(&iter);
}
++i;
}
} else {
return Error("Could not init the array iteration.");
}
} else {
return Error("Could not init array.");
}
return Error("Index " + std::to_string(_idx) + " of of bounds.");
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType& _obj) const noexcept {
bson_t b;
Expand Down
6 changes: 5 additions & 1 deletion include/rfl/bson/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ using InputVarType = typename Reader::InputVarType;
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const InputVarType& _obj) {
const auto r = Reader();
return Parser<T, Processors<Ps...>>::read(r, _obj);
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
return Parser<T, ProcessorsType>::read(r, _obj);
}

/// Parses an BSON object using reflection.
Expand Down
8 changes: 6 additions & 2 deletions include/rfl/bson/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ std::pair<uint8_t*, size_t> to_buffer(const auto& _obj) noexcept {
bson_writer_new(&buf, &buflen, 0, bson_realloc_ctx, NULL);
bson_writer_begin(bson_writer, &doc);
const auto rfl_writer = Writer(doc);
Parser<T, Processors<Ps...>>::write(rfl_writer, _obj,
typename ParentType::Root{});
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
Parser<T, ProcessorsType>::write(rfl_writer, _obj,
typename ParentType::Root{});
bson_writer_end(bson_writer);
const auto len = bson_writer_get_length(bson_writer);
bson_writer_destroy(bson_writer);
Expand Down
24 changes: 24 additions & 0 deletions include/rfl/cbor/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,30 @@ struct Reader {
T::from_cbor_obj(var);
});

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType& _arr) const noexcept {
InputVarType var;
auto err = cbor_value_enter_container(&_arr.val_, &var.val_);
if (err != CborNoError && err != CborErrorOutOfMemory) {
return Error(cbor_error_string(err));
}
size_t length = 0;
err = cbor_value_get_array_length(&_arr.val_, &length);
if (err != CborNoError && err != CborErrorOutOfMemory) {
return Error(cbor_error_string(err));
}
if (_idx >= length) {
return Error("Index " + std::to_string(_idx) + " of of bounds.");
}
for (size_t i = 0; i < _idx; ++i) {
err = cbor_value_advance(&var.val_);
if (err != CborNoError && err != CborErrorOutOfMemory) {
return Error(cbor_error_string(err));
}
}
return var;
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType& _obj) const noexcept {
InputVarType var;
Expand Down
8 changes: 8 additions & 0 deletions include/rfl/flexbuf/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ struct Reader {
template <class T>
static constexpr bool has_custom_constructor = has_from_flexbuf<T>::value;

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType& _arr) const noexcept {
if (_idx >= _arr.size()) {
return rfl::Error("Index " + std::to_string(_idx) + " of of bounds.");
}
return _arr[_idx];
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType& _obj) const noexcept {
const auto keys = _obj.Keys();
Expand Down
8 changes: 8 additions & 0 deletions include/rfl/msgpack/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ struct Reader {
T::from_msgpack_obj(var);
});

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType _arr) const noexcept {
if (_idx >= _arr.size) {
return rfl::Error("Index " + std::to_string(_idx) + " of of bounds.");
}
return _arr.ptr[_idx];
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType& _obj) const noexcept {
for (uint32_t i = 0; i < _obj.size; ++i) {
Expand Down
28 changes: 24 additions & 4 deletions include/rfl/parsing/Parser_tagged_union.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
#include "../TaggedUnion.hpp"
#include "../always_false.hpp"
#include "../internal/strings/join.hpp"
#include "../named_tuple_t.hpp"
#include "Parser_base.hpp"
#include "TaggedUnionWrapper.hpp"
#include "is_tagged_union_wrapper.hpp"
#include "schema/Type.hpp"
#include "tagged_union_wrapper_no_ptr.hpp"

namespace rfl {
namespace parsing {
Expand Down Expand Up @@ -106,6 +109,14 @@ struct Parser<R, W, TaggedUnion<_discriminator, AlternativeTypes...>,
std::variant_alternative_t<_i, std::variant<AlternativeTypes...>>>;

if (!*_match_found && contains_disc_value<AlternativeType>(_disc_value)) {
const auto get_fields = [](auto&& _val) -> AlternativeType {
if constexpr (is_tagged_union_wrapper_v<decltype(_val)>) {
return std::move(_val.fields());
} else {
return std::move(_val);
}
};

const auto to_tagged_union = [](auto&& _val) {
return TaggedUnion<_discriminator, AlternativeTypes...>(
std::move(_val));
Expand All @@ -118,9 +129,18 @@ struct Parser<R, W, TaggedUnion<_discriminator, AlternativeTypes...>,
_discriminator.str() + " '" + _disc_value + "': " + _e.what());
};

*_res = Parser<R, W, AlternativeType, ProcessorsType>::read(_r, _var)
.transform(to_tagged_union)
.or_else(embellish_error);
if constexpr (no_field_names_) {
using T = tagged_union_wrapper_no_ptr_t<std::invoke_result_t<
decltype(wrap_if_necessary<AlternativeType>), AlternativeType>>;
*_res = Parser<R, W, T, ProcessorsType>::read(_r, _var)
.transform(get_fields)
.transform(to_tagged_union)
.or_else(embellish_error);
} else {
*_res = Parser<R, W, AlternativeType, ProcessorsType>::read(_r, _var)
.transform(to_tagged_union)
.or_else(embellish_error);
}

*_match_found = true;
}
Expand Down Expand Up @@ -162,7 +182,7 @@ struct Parser<R, W, TaggedUnion<_discriminator, AlternativeTypes...>,
template <class T, class P>
static void write_wrapped(const W& _w, const T& _val,
const P& _parent) noexcept {
const auto wrapped = wrap_if_necessary(_val);
const auto wrapped = wrap_if_necessary<T>(_val);
Parser<R, W, std::remove_cvref_t<decltype(wrapped)>, ProcessorsType>::write(
_w, wrapped, _parent);
}
Expand Down
17 changes: 12 additions & 5 deletions include/rfl/parsing/TaggedUnionWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define RFL_PARSING_TAGGEDUNIONWRAPPER_HPP_

#include <string>
#include <type_traits>

#include "../Flatten.hpp"
#include "../Rename.hpp"
Expand All @@ -10,18 +11,24 @@
namespace rfl {
namespace parsing {

template <class T, class TagType, internal::StringLiteral _discriminator>
template <class T, class TagType, internal::StringLiteral _discriminator,
bool _as_const_pointer = true>
struct TaggedUnionWrapperNoFields {
using Type = T;
using Type = std::remove_cvref_t<T>;
using FlattenedType =
std::conditional_t<_as_const_pointer, const Type*, Type>;
rfl::Rename<_discriminator, TagType> tag;
rfl::Flatten<const T*> fields;
rfl::Flatten<FlattenedType> fields;
};

template <class T, class TagType, internal::StringLiteral _discriminator>
template <class T, class TagType, internal::StringLiteral _discriminator,
bool _as_const_pointer = true>
struct TaggedUnionWrapperWithFields {
using Type = T;
using FlattenedType =
std::conditional_t<_as_const_pointer, const Type*, Type>;
rfl::Field<_discriminator, TagType> tag;
rfl::Flatten<const T*> fields;
rfl::Flatten<FlattenedType> fields;
};

} // namespace parsing
Expand Down
13 changes: 8 additions & 5 deletions include/rfl/parsing/is_tagged_union_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@ class is_tagged_union_wrapper;
template <class T>
class is_tagged_union_wrapper : public std::false_type {};

template <class T, class TagType, internal::StringLiteral _discriminator>
template <class T, class TagType, internal::StringLiteral _discriminator,
bool _as_const_pointer>
class is_tagged_union_wrapper<
TaggedUnionWrapperNoFields<T, TagType, _discriminator>>
TaggedUnionWrapperNoFields<T, TagType, _discriminator, _as_const_pointer>>
: public std::true_type {};

template <class T, class TagType, internal::StringLiteral _discriminator>
template <class T, class TagType, internal::StringLiteral _discriminator,
bool _as_const_pointer>
class is_tagged_union_wrapper<
TaggedUnionWrapperWithFields<T, TagType, _discriminator>>
TaggedUnionWrapperWithFields<T, TagType, _discriminator, _as_const_pointer>>
: public std::true_type {};

template <class T>
constexpr bool is_tagged_union_wrapper_v = is_tagged_union_wrapper<T>::value;
constexpr bool is_tagged_union_wrapper_v =
is_tagged_union_wrapper<std::remove_cvref_t<T>>::value;

} // namespace parsing
} // namespace rfl
Expand Down
41 changes: 41 additions & 0 deletions include/rfl/parsing/tagged_union_wrapper_no_ptr.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef RFL_PARSING_TAGGEDUNIONWRAPPERNOPTR_HPP_
#define RFL_PARSING_TAGGEDUNIONWRAPPERNOPTR_HPP_

#include <type_traits>

#include "../internal/StringLiteral.hpp"
#include "TaggedUnionWrapper.hpp"

namespace rfl {
namespace parsing {

template <class T>
struct tagged_union_wrapper_no_ptr;

template <class T>
struct tagged_union_wrapper_no_ptr {
using Type = T;
};

template <class T, class TagType, internal::StringLiteral _discriminator,
bool _as_const_pointer>
struct tagged_union_wrapper_no_ptr<
TaggedUnionWrapperNoFields<T, TagType, _discriminator, _as_const_pointer>> {
using Type = TaggedUnionWrapperNoFields<T, TagType, _discriminator, false>;
};

template <class T, class TagType, internal::StringLiteral _discriminator,
bool _as_const_pointer>
struct tagged_union_wrapper_no_ptr<TaggedUnionWrapperWithFields<
T, TagType, _discriminator, _as_const_pointer>> {
using Type = TaggedUnionWrapperWithFields<T, TagType, _discriminator, false>;
};

template <class T>
using tagged_union_wrapper_no_ptr_t =
typename tagged_union_wrapper_no_ptr<std::remove_cvref_t<T>>::Type;

} // namespace parsing
} // namespace rfl

#endif
8 changes: 8 additions & 0 deletions include/rfl/toml/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ struct Reader {
T::from_toml_obj(var);
});

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType _arr) const noexcept {
if (_idx >= _arr->size()) {
return rfl::Error("Index " + std::to_string(_idx) + " of of bounds.");
}
return _arr->get(_idx);
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType& _obj) const noexcept {
auto var = (*_obj)[_name];
Expand Down
6 changes: 5 additions & 1 deletion include/rfl/toml/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ using InputVarType = typename Reader::InputVarType;
template <class T, class... Ps>
auto read(InputVarType _var) {
const auto r = Reader();
return Parser<T, Processors<Ps...>>::read(r, _var);
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
return Parser<T, ProcessorsType>::read(r, _var);
}

/// Parses an object from TOML using reflection.
Expand Down
12 changes: 10 additions & 2 deletions include/rfl/toml/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ std::ostream& write(const auto& _obj, std::ostream& _stream) {
using ParentType = parsing::Parent<Writer>;
::toml::table root;
auto w = Writer(&root);
Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root{});
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
Parser<T, ProcessorsType>::write(w, _obj, typename ParentType::Root{});
_stream << root;
return _stream;
}
Expand All @@ -33,7 +37,11 @@ std::string write(const auto& _obj) {
std::stringstream sstream;
::toml::table root;
auto w = Writer(&root);
Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root{});
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
Parser<T, ProcessorsType>::write(w, _obj, typename ParentType::Root{});
sstream << root;
return sstream.str();
}
Expand Down
12 changes: 12 additions & 0 deletions include/rfl/xml/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ struct Reader {
return std::visit(cast, _node_or_attribute);
}

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType& _arr) const noexcept {
const auto name = _arr.node_.name();
size_t i = 0;
for (auto node = _arr.node_; node; node = node.next_sibling(name)) {
if (i == _idx) {
return InputVarType(node);
}
}
return rfl::Error("Index " + std::to_string(_idx) + " of of bounds.");
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType _obj) const noexcept {
const auto node = _obj.node_.child(_name.c_str());
Expand Down
6 changes: 5 additions & 1 deletion include/rfl/xml/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ using InputVarType = typename Reader::InputVarType;
template <class T, class... Ps>
auto read(const InputVarType& _var) {
const auto r = Reader();
return Parser<T, Processors<Ps...>>::read(r, _var);
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
return Parser<T, ProcessorsType>::read(r, _var);
}

/// Parses an object from XML using reflection.
Expand Down
6 changes: 5 additions & 1 deletion include/rfl/xml/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ std::ostream& write(const auto& _obj, std::ostream& _stream,

auto w = Writer(doc, root_name.str());

Parser<T, Processors<Ps...>>::write(w, _obj, typename ParentType::Root{});
using ProcessorsType = Processors<Ps...>;
static_assert(!ProcessorsType::no_field_names_,
"The NoFieldNames processor is not supported for BSON, XML, "
"TOML, or YAML.");
Parser<T, ProcessorsType>::write(w, _obj, typename ParentType::Root{});

doc->save(_stream, _indent.c_str());

Expand Down
8 changes: 8 additions & 0 deletions include/rfl/yaml/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ struct Reader {
T::from_yaml_obj(var);
});

rfl::Result<InputVarType> get_field_from_array(
const size_t _idx, const InputArrayType& _arr) const noexcept {
if (_idx >= _arr.node_.size()) {
return rfl::Error("Index " + std::to_string(_idx) + " of of bounds.");
}
return InputVarType(_arr.node_[_idx]);
}

rfl::Result<InputVarType> get_field_from_object(
const std::string& _name, const InputObjectType& _obj) const noexcept {
auto var = InputVarType(_obj.node_[_name]);
Expand Down
Loading

0 comments on commit 84114c3

Please sign in to comment.