Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions include/rfl/boost_serialization/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../Result.hpp"
#include "../always_false.hpp"
#include "../internal/is_literal.hpp"
#include "../parsing/read_array_elements.hpp"

namespace rfl::boost_serialization {

Expand Down Expand Up @@ -140,19 +141,16 @@ struct Reader {
template <class ArrayReader>
std::optional<Error> read_array(const ArrayReader& _array_reader,
const InputArrayType& _arr) const noexcept {
if constexpr (requires { _array_reader.reserve(_arr.size); }) {
if (const auto err = _array_reader.reserve(_arr.size)) {
return err;
}
}
for (size_t i = 0; i < _arr.size; ++i) {
auto var = InputVarType{_arr.ar};
const auto err = _array_reader.read(var);
if (err) {
return err;
}
}
return std::nullopt;
return parsing::read_array_elements(_array_reader, InputVarType{_arr.ar},
_arr.size);
}

/// Reads exactly the compile-time extent without consuming a length prefix.
template <size_t _size, class ArrayReader>
std::optional<Error> read_fixed_array(
const ArrayReader& _array_reader,
const InputVarType& _var) const noexcept {
return parsing::read_array_elements(_array_reader, _var, _size);
}

/// Reads all key-value pairs from a map using the provided map reader.
Expand Down
30 changes: 30 additions & 0 deletions include/rfl/boost_serialization/Writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ class Writer {
return OutputArrayType{};
}

/// Fixed-size arrays store only their elements; parent metadata is retained.
OutputArrayType fixed_array_as_root(const size_t /*_size*/) const {
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_array(const size_t /*_size*/,
OutputArrayType* /*_parent*/) const {
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_object(
const std::string_view& /*_name*/, const size_t /*_size*/,
OutputObjectType* /*_parent*/) const {
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_map(const std::string_view& _name,
const size_t /*_size*/,
OutputMapType* /*_parent*/) const {
write_key(_name);
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_union(const size_t _index,
const size_t /*_size*/,
OutputUnionType* /*_parent*/) const {
write_index(_index);
return OutputArrayType{};
}

/// Creates a map as the root element.
/// Writes the size to the archive first.
/// @param _size The number of entries in the map
Expand Down
28 changes: 16 additions & 12 deletions include/rfl/cereal/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <cereal/cereal.hpp>
#include <cereal/types/string.hpp>
#include <exception>
#include <optional>
#include <sstream>
#include <string>
#include <type_traits>
Expand All @@ -16,6 +17,7 @@
#include "../always_false.hpp"
#include "../internal/always_inline.hpp"
#include "../internal/is_literal.hpp"
#include "../parsing/read_array_elements.hpp"
#include "../parsing/schemaful/IsSchemafulReader.hpp"

namespace rfl::cereal {
Expand Down Expand Up @@ -129,18 +131,20 @@ struct Reader {
try {
size_t size;
(*_arr.archive_)(::cereal::make_size_tag(size));
if constexpr (requires { _array_reader.reserve(size); }) {
if (const auto err = _array_reader.reserve(size)) {
return err;
}
}
for (size_t i = 0; i < size; ++i) {
const auto err = _array_reader.read(InputVarType{_arr.archive_});
if (err) {
return err;
}
}
return std::nullopt;
return parsing::read_array_elements(_array_reader,
InputVarType{_arr.archive_}, size);
} catch (std::exception& e) {
return Error(std::string("Cereal array read error: ") + e.what());
}
}

/// Reads exactly the compile-time extent without consuming a length prefix.
template <size_t _size, class ArrayReader>
std::optional<Error> read_fixed_array(
const ArrayReader& _array_reader,
const InputVarType& _var) const noexcept {
try {
return parsing::read_array_elements(_array_reader, _var, _size);
} catch (std::exception& e) {
return Error(std::string("Cereal array read error: ") + e.what());
}
Expand Down
30 changes: 30 additions & 0 deletions include/rfl/cereal/Writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,36 @@ class Writer {
/// @return An OutputArrayType
OutputArrayType array_as_root(const size_t _size) const;

/// Fixed-size arrays store only their elements; parent metadata is retained.
OutputArrayType fixed_array_as_root(const size_t /*_size*/) const {
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_array(const size_t /*_size*/,
OutputArrayType* /*_parent*/) const {
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_object(
const std::string_view& /*_name*/, const size_t /*_size*/,
OutputObjectType* /*_parent*/) const {
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_map(const std::string_view& _name,
const size_t /*_size*/,
OutputMapType* /*_parent*/) const {
add_string_view(_name);
return OutputArrayType{};
}

OutputArrayType add_fixed_array_to_union(const size_t _index,
const size_t /*_size*/,
OutputUnionType* /*_parent*/) const {
(*archive_)(_index);
return OutputArrayType{};
}

/// Creates a map as the root element.
/// Writes the size tag to the archive first.
/// @param _size The number of entries in the map
Expand Down
28 changes: 28 additions & 0 deletions include/rfl/parsing/Parent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,34 @@ struct Parent {
}
}

/// Adds a fixed-size array, omitting its length when the writer supports it.
template <class ParentType>
static OutputArrayType add_fixed_array(const W& _w, const size_t _size,
const ParentType& _parent) {
using Type = std::remove_cvref_t<ParentType>;
if constexpr (!requires { _w.fixed_array_as_root(_size); }) {
return add_array(_w, _size, _parent);
} else if constexpr (std::is_same_v<Type, Array>) {
return _w.add_fixed_array_to_array(_size, _parent.arr_);
} else if constexpr (std::is_same_v<Type, Object>) {
return _w.add_fixed_array_to_object(_parent.name_, _size, _parent.obj_);
} else if constexpr (std::is_same_v<Type, Root>) {
return _w.fixed_array_as_root(_size);
} else if constexpr (schemaful::IsSchemafulWriter<W>) {
if constexpr (std::is_same_v<Type, Map<typename W::OutputMapType>>) {
return _w.add_fixed_array_to_map(_parent.name_, _size, _parent.map_);
} else if constexpr (std::is_same_v<Type,
Union<typename W::OutputUnionType>>) {
return _w.add_fixed_array_to_union(_parent.index_, _size,
_parent.union_);
} else {
static_assert(always_false_v<Type>, "Unsupported option.");
}
} else {
static_assert(always_false_v<Type>, "Unsupported option.");
}
}

/**
* @brief Adds a comment to the parent.
*
Expand Down
52 changes: 30 additions & 22 deletions include/rfl/parsing/ParserArray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <array>
#include <map>
#include <optional>
#include <type_traits>

#include "../Ref.hpp"
Expand Down Expand Up @@ -45,29 +46,36 @@ struct ParserArray {
*/
static Result<std::array<T, _size>> read(const R& _r,
const InputVarType& _var) noexcept {
const auto parse =
[&](const InputArrayType& _arr) -> Result<std::array<T, _size>> {
alignas(
std::array<T, _size>) unsigned char buf[sizeof(std::array<T, _size>)];
auto ptr = internal::ptr_cast<std::array<T, _size>*>(&buf);
const auto array_reader =
ArrayReader<R, W, ProcessorsType, T, _size>(&_r, ptr);
auto err = _r.read_array(array_reader, _arr);
if (err) {
call_destructors_on_array_where_necessary(array_reader.num_set(), ptr);
return error(*err);
alignas(
std::array<T, _size>) unsigned char buf[sizeof(std::array<T, _size>)];
auto ptr = internal::ptr_cast<std::array<T, _size>*>(&buf);
const auto array_reader =
ArrayReader<R, W, ProcessorsType, T, _size>(&_r, ptr);
auto err = [&]() -> std::optional<Error> {
if constexpr (requires {
_r.template read_fixed_array<_size>(array_reader, _var);
}) {
return _r.template read_fixed_array<_size>(array_reader, _var);
} else {
const auto arr = _r.to_array(_var);
if (!arr) {
return arr.error();
}
return _r.read_array(array_reader, *arr);
}
err = array_reader.check_size();
if (err) {
call_destructors_on_array_where_necessary(array_reader.num_set(), ptr);
return error(*err);
}
auto result = Result<std::array<T, _size>>(std::move(*ptr));
}();
if (err) {
call_destructors_on_array_where_necessary(array_reader.num_set(), ptr);
return result;
};

return _r.to_array(_var).and_then(parse);
return error(*err);
}
err = array_reader.check_size();
if (err) {
call_destructors_on_array_where_necessary(array_reader.num_set(), ptr);
return error(*err);
}
auto result = Result<std::array<T, _size>>(std::move(*ptr));
call_destructors_on_array_where_necessary(array_reader.num_set(), ptr);
return result;
}

/**
Expand All @@ -80,7 +88,7 @@ struct ParserArray {
template <class P>
static void write(const W& _w, const std::array<T, _size>& _arr,
const P& _parent) {
auto arr = ParentType::add_array(_w, _size, _parent);
auto arr = ParentType::add_fixed_array(_w, _size, _parent);
const auto new_parent = typename ParentType::Array{&arr};
for (const auto& e : _arr) {
Parser<R, W, std::remove_cvref_t<T>, ProcessorsType>::write(_w, e,
Expand Down
2 changes: 1 addition & 1 deletion include/rfl/parsing/ParserCArray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct ParserCArray {
*/
template <class P>
static void write(const W& _w, const CArray& _arr, const P& _parent) {
auto arr = ParentType::add_array(_w, _size, _parent);
auto arr = ParentType::add_fixed_array(_w, _size, _parent);
const auto new_parent = typename ParentType::Array{&arr};
for (const auto& e : _arr) {
Parser<R, W, std::remove_cvref_t<T>, ProcessorsType>::write(_w, e,
Expand Down
33 changes: 33 additions & 0 deletions include/rfl/parsing/read_array_elements.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef RFL_PARSING_READ_ARRAY_ELEMENTS_HPP_
#define RFL_PARSING_READ_ARRAY_ELEMENTS_HPP_

#include <cstddef>
#include <optional>

#include "../Result.hpp"

namespace rfl::parsing {

/// Reads elements from a sequential archive after its extent is known.
/// Fixed-size readers supply their compile-time extent; dynamic readers first
/// consume the length prefix. Each element advances the archive in _var.
template <class ArrayReader, class InputVarType>
std::optional<Error> read_array_elements(const ArrayReader& _array_reader,
const InputVarType& _var,
const std::size_t _size) {
if constexpr (requires { _array_reader.reserve(_size); }) {
if (const auto err = _array_reader.reserve(_size)) {
return err;
}
}
for (std::size_t i = 0; i < _size; ++i) {
if (const auto err = _array_reader.read(_var)) {
return err;
}
}
return std::nullopt;
}

} // namespace rfl::parsing

#endif
29 changes: 16 additions & 13 deletions include/rfl/yas/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "../Result.hpp"
#include "../always_false.hpp"
#include "../internal/is_literal.hpp"
#include "../parsing/read_array_elements.hpp"
#include "../parsing/schemaful/IsSchemafulReader.hpp"

namespace rfl::yas {
Expand Down Expand Up @@ -119,20 +120,22 @@ struct Reader {
std::optional<Error> read_array(const ArrayReader& _array_reader,
const InputArrayType& _arr) const noexcept {
try {
std::size_t size;
size_t size;
(*_arr.ar) & size;
if constexpr (requires { _array_reader.reserve(size); }) {
if (const auto err = _array_reader.reserve(size)) {
return err;
}
}
for (std::size_t i = 0; i < size; ++i) {
const auto err = _array_reader.read(InputVarType{_arr.ar});
if (err) {
return err;
}
}
return std::nullopt;
return parsing::read_array_elements(_array_reader, InputVarType{_arr.ar},
size);
} catch (std::exception& e) {
return Error(std::string("yas array read error: ") + e.what());
}
}

/// Reads exactly the compile-time extent without consuming a length prefix.
template <size_t _size, class ArrayReader>
std::optional<Error> read_fixed_array(
const ArrayReader& _array_reader,
const InputVarType& _var) const noexcept {
try {
return parsing::read_array_elements(_array_reader, _var, _size);
} catch (std::exception& e) {
return Error(std::string("yas array read error: ") + e.what());
}
Expand Down
30 changes: 30 additions & 0 deletions include/rfl/yas/Writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ struct Writer {
return OutputArrayType{ar_};
}

/// Fixed-size arrays store only their elements; parent metadata is retained.
OutputArrayType fixed_array_as_root(const size_t /*_size*/) const {
return OutputArrayType{ar_};
}

OutputArrayType add_fixed_array_to_array(const size_t /*_size*/,
OutputArrayType* /*_parent*/) const {
return OutputArrayType{ar_};
}

OutputArrayType add_fixed_array_to_object(
const std::string_view& /*_name*/, const size_t /*_size*/,
OutputObjectType* /*_parent*/) const {
return OutputArrayType{ar_};
}

OutputArrayType add_fixed_array_to_map(const std::string_view& _name,
const size_t /*_size*/,
OutputMapType* /*_parent*/) const {
add_string_view(_name);
return OutputArrayType{ar_};
}

OutputArrayType add_fixed_array_to_union(const size_t _index,
const size_t /*_size*/,
OutputUnionType* /*_parent*/) const {
(*ar_) & _index;
return OutputArrayType{ar_};
}

///
/// @brief Begins serializing a map as the root object.
/// @param _size The number of key-value pairs in the map.
Expand Down
Loading
Loading