Skip to content

Commit ab72519

Browse files
Made it work for most tests
1 parent deb7154 commit ab72519

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1396
-77
lines changed

include/rfl/ubjson/Reader.hpp

Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include <cstddef>
55
#include <exception>
6-
#include <jsoncons_ext/ubjson/ubjson_cursor.hpp>
6+
#include <jsoncons/json.hpp>
77
#include <string>
88
#include <string_view>
99
#include <type_traits>
@@ -15,25 +15,28 @@
1515

1616
namespace rfl::ubjson {
1717

18-
struct Reader {
19-
using CursorType = jsoncons::ubjson::ubjson_bytes_cursor;
20-
18+
class Reader {
19+
public:
2120
struct UBJSONInputArray {
22-
CursorType* cursor_;
21+
jsoncons::json* val_;
2322
};
2423

2524
struct UBJSONInputObject {
26-
CursorType* cursor_;
25+
jsoncons::json* val_;
2726
};
2827

2928
struct UBJSONInputVar {
30-
CursorType* cursor_;
29+
jsoncons::json* val_;
3130
};
3231

3332
using InputArrayType = UBJSONInputArray;
3433
using InputObjectType = UBJSONInputObject;
3534
using InputVarType = UBJSONInputVar;
3635

36+
Reader() {}
37+
38+
~Reader() = default;
39+
3740
template <class T>
3841
static constexpr bool has_custom_constructor = (requires(InputVarType var) {
3942
T::from_ubjson_obj(var);
@@ -49,85 +52,63 @@ struct Reader {
4952

5053
template <class T>
5154
rfl::Result<T> to_basic_type(const InputVarType& _var) const noexcept {
52-
const auto& event = _var.cursor_->current();
53-
const auto event_type = event.event_type();
5455
if constexpr (std::is_same<std::remove_cvref_t<T>, std::string>()) {
55-
if (event_type != jsoncons::staj_event_type::string_value) {
56+
if (!_var.val_->is_string()) {
5657
return Error("Could not cast to string.");
5758
}
58-
return std::string(event.get<std::string_view>());
59-
60-
/* } else if constexpr (std::is_same<std::remove_cvref_t<T>,
61-
rfl::Bytestring>()) {
62-
if (!ubjson_value_is_byte_string(&_var.val_)) {
63-
return Error("Could not cast to bytestring.");
64-
}
65-
rfl::Bytestring bstr;
66-
const auto err = get_bytestring(&_var.val_, &bstr);
67-
if (err != CborNoError) {
68-
return Error(ubjson_error_string(err));
69-
}
70-
return bstr;*/
59+
return _var.val_->as<std::string>();
60+
} else if constexpr (std::is_same<std::remove_cvref_t<T>,
61+
rfl::Bytestring>()) {
62+
if (!_var.val_->is_byte_string()) {
63+
return Error("Could not cast to bytestring.");
64+
}
65+
return rfl::Bytestring(); // TODO
7166
} else if constexpr (std::is_same<std::remove_cvref_t<T>, bool>()) {
72-
if (event_type != jsoncons::staj_event_type::bool_value) {
67+
if (!_var.val_->is_bool()) {
7368
return rfl::Error("Could not cast to boolean.");
7469
}
75-
return std::string(event.get<bool>());
70+
return _var.val_->as<bool>();
7671
} else if constexpr (std::is_floating_point<std::remove_cvref_t<T>>() ||
7772
std::is_integral<std::remove_cvref_t<T>>()) {
78-
switch (event_type) {
79-
case jsoncons::staj_event_type::int64_value:
80-
return static_cast<T>(event.get<int64_t>());
81-
case jsoncons::staj_event_type::uint64_value:
82-
return static_cast<T>(event.get<uint64_t>());
83-
case jsoncons::staj_event_type::double_value:
84-
return static_cast<T>(event.get<double>());
85-
default:
86-
return rfl::Error(
87-
"Could not cast to numeric value. The type must be integral, "
88-
"float or double.");
73+
if (_var.val_->is_double()) {
74+
return static_cast<T>(_var.val_->as<double>());
8975
}
76+
if (_var.val_->is_int64()) {
77+
return static_cast<T>(_var.val_->as<int64_t>());
78+
}
79+
if (_var.val_->is_uint64()) {
80+
return static_cast<T>(_var.val_->as<uint64_t>());
81+
}
82+
return rfl::Error(
83+
"Could not cast to numeric value. The type must be integral, "
84+
"float or double.");
9085
} else {
9186
static_assert(rfl::always_false_v<T>, "Unsupported type.");
9287
}
9388
}
9489

95-
rfl::Result<InputArrayType> to_array(const InputVarType& _var) const noexcept;
90+
rfl::Result<InputArrayType> to_array(InputVarType _var) const noexcept;
9691

97-
rfl::Result<InputObjectType> to_object(
98-
const InputVarType& _var) const noexcept;
92+
rfl::Result<InputObjectType> to_object(InputVarType _var) const noexcept;
9993

10094
template <class ArrayReader>
101-
std::optional<Error> read_array(const ArrayReader& _array_reader,
102-
const InputArrayType& _arr) const noexcept {
103-
for (const auto& event = _arr.cursor_->current();
104-
event.event_type() != jsoncons::staj_event_type::end_array;
105-
_arr.cursor_->next()) {
106-
const auto err = _array_reader.read(InputVarType{_arr.cursor_});
95+
std::optional<Error> read_array(ArrayReader _array_reader,
96+
InputArrayType _arr) const noexcept {
97+
for (auto& val : _arr.val_->array_range()) {
98+
const auto err = _array_reader.read(InputVarType{&val});
10799
if (err) {
108-
// TODO: Go to end of cursor
109100
return err;
110101
}
111102
}
112-
_arr.cursor_->next();
113103
return std::nullopt;
114104
}
115105

116106
template <class ObjectReader>
117107
std::optional<Error> read_object(const ObjectReader& _object_reader,
118-
const InputObjectType& _obj) const noexcept {
119-
for (const auto& event = _obj.cursor_->current();
120-
event.event_type() != jsoncons::staj_event_type::end_object;
121-
_obj.cursor_->next()) {
122-
if (event.event_type() != jsoncons::staj_event_type::key) {
123-
_obj.cursor_->reset();
124-
_obj.cursor_->reset();
125-
return Error("Expected a key.");
126-
}
127-
const auto key = event.get<std::string_view>();
128-
_object_reader.read(key, InputVarType{_obj.cursor_});
108+
InputObjectType _obj) const noexcept {
109+
for (auto& kv : _obj.val_->object_range()) {
110+
_object_reader.read(kv.key(), InputVarType{&kv.value()});
129111
}
130-
_obj.cursor_->next();
131112
return std::nullopt;
132113
}
133114

include/rfl/ubjson/read.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
#include <bit>
55
#include <istream>
6-
#include <jsoncons_ext/ubjson/ubjson_cursor.hpp>
6+
#include <jsoncons/json.hpp>
7+
#include <jsoncons_ext/ubjson/decode_ubjson.hpp>
78
#include <string>
89

910
#include "../Processors.hpp"
@@ -23,9 +24,9 @@ Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
2324
auto buffer =
2425
std::vector<uint8_t>(std::bit_cast<const uint8_t*>(_bytes),
2526
std::bit_cast<const uint8_t*>(_bytes) + _size);
26-
auto cursor = jsoncons::ubjson::ubjson_bytes_cursor(buffer);
27+
auto val = jsoncons::ubjson::decode_ubjson<jsoncons::json>(buffer);
2728
auto r = Reader();
28-
auto result = Parser<T, Processors<Ps...>>::read(r, InputVarType{&cursor});
29+
auto result = Parser<T, Processors<Ps...>>::read(r, InputVarType{&val});
2930
return result;
3031
}
3132

src/rfl/ubjson/Reader.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,40 @@ namespace rfl::ubjson {
44

55
rfl::Result<Reader::InputVarType> Reader::get_field_from_array(
66
const size_t _idx, const InputArrayType& _arr) const noexcept {
7-
return Error("TODO");
7+
if (_idx >= _arr.val_->size()) {
8+
return Error("Index out of range.");
9+
}
10+
return InputVarType{&_arr.val_->at(_idx)};
811
}
912

1013
rfl::Result<Reader::InputVarType> Reader::get_field_from_object(
1114
const std::string& _name, const InputObjectType& _obj) const noexcept {
12-
return Error("TODO");
15+
for (auto& kv : _obj.val_->object_range()) {
16+
if (kv.key() == _name) {
17+
return InputVarType{&kv.value()};
18+
};
19+
}
20+
return Error("Field name '" + _name + "' not found.");
1321
}
1422

1523
bool Reader::is_empty(const InputVarType& _var) const noexcept {
16-
return _var.cursor_->current().event_type() ==
17-
jsoncons::staj_event_type::null_value;
24+
return _var.val_->is_null();
1825
}
1926

2027
rfl::Result<Reader::InputArrayType> Reader::to_array(
21-
const InputVarType& _var) const noexcept {
22-
if (_var.cursor_->current().event_type() !=
23-
jsoncons::staj_event_type::begin_array) {
28+
InputVarType _var) const noexcept {
29+
if (!_var.val_->is_array()) {
2430
return Error("Could not cast to an array.");
2531
}
26-
return InputArrayType{_var.cursor_};
32+
return InputArrayType{_var.val_};
2733
}
2834

2935
rfl::Result<Reader::InputObjectType> Reader::to_object(
30-
const InputVarType& _var) const noexcept {
31-
if (_var.cursor_->current().event_type() !=
32-
jsoncons::staj_event_type::begin_object) {
36+
InputVarType _var) const noexcept {
37+
if (!_var.val_->is_object()) {
3338
return Error("Could not cast to an object.");
3439
}
35-
return InputObjectType{_var.cursor_};
40+
return InputObjectType{_var.val_};
3641
}
3742

3843
} // namespace rfl::ubjson
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <iostream>
2+
#include <string>
3+
#include <vector>
4+
5+
#include "write_and_read.hpp"
6+
7+
namespace test_add_struct_name {
8+
9+
using Age = rfl::Validator<unsigned int, rfl::Minimum<0>, rfl::Maximum<130>>;
10+
11+
struct Person {
12+
rfl::Rename<"firstName", std::string> first_name;
13+
rfl::Rename<"lastName", std::string> last_name = "Simpson";
14+
std::string town = "Springfield";
15+
rfl::Timestamp<"%Y-%m-%d"> birthday;
16+
Age age;
17+
rfl::Email email;
18+
std::vector<Person> children;
19+
};
20+
21+
TEST(ubjson, test_add_struct_name) {
22+
const auto bart = Person{.first_name = "Bart",
23+
.birthday = "1987-04-19",
24+
.age = 10,
25+
.email = "bart@simpson.com"};
26+
27+
const auto lisa = Person{.first_name = "Lisa",
28+
.birthday = "1987-04-19",
29+
.age = 8,
30+
.email = "lisa@simpson.com"};
31+
32+
const auto maggie = Person{.first_name = "Maggie",
33+
.birthday = "1987-04-19",
34+
.age = 0,
35+
.email = "maggie@simpson.com"};
36+
37+
const auto homer =
38+
Person{.first_name = "Homer",
39+
.birthday = "1987-04-19",
40+
.age = 45,
41+
.email = "homer@simpson.com",
42+
.children = std::vector<Person>({bart, lisa, maggie})};
43+
44+
write_and_read<rfl::AddStructName<"type">>(homer);
45+
}
46+
} // namespace test_add_struct_name

tests/ubjson/test_array.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <array>
2+
#include <iostream>
3+
#include <memory>
4+
#include <rfl/ubjson.hpp>
5+
#include <string>
6+
7+
// Make sure things still compile when
8+
// rfl.hpp is included after rfl/ubjson.hpp.
9+
#include <rfl.hpp>
10+
11+
#include "write_and_read.hpp"
12+
13+
namespace test_array {
14+
15+
struct Person {
16+
rfl::Rename<"firstName", std::string> first_name;
17+
rfl::Rename<"lastName", std::string> last_name = "Simpson";
18+
std::unique_ptr<std::array<Person, 3>> children = nullptr;
19+
};
20+
21+
TEST(ubjson, test_array) {
22+
auto bart = Person{.first_name = "Bart"};
23+
24+
auto lisa = Person{.first_name = "Lisa"};
25+
26+
auto maggie = Person{.first_name = "Maggie"};
27+
28+
const auto homer = Person{
29+
.first_name = "Homer",
30+
.children = std::make_unique<std::array<Person, 3>>(std::array<Person, 3>{
31+
std::move(bart), std::move(lisa), std::move(maggie)})};
32+
33+
write_and_read(homer);
34+
}
35+
} // namespace test_array

tests/ubjson/test_box.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <cassert>
2+
#include <iostream>
3+
#include <rfl.hpp>
4+
#include <string>
5+
#include <vector>
6+
7+
#include "write_and_read.hpp"
8+
9+
namespace test_box {
10+
11+
struct DecisionTree {
12+
struct Leaf {
13+
using Tag = rfl::Literal<"Leaf">;
14+
double value;
15+
};
16+
17+
struct Node {
18+
using Tag = rfl::Literal<"Node">;
19+
rfl::Rename<"criticalValue", double> critical_value;
20+
rfl::Box<DecisionTree> lesser;
21+
rfl::Box<DecisionTree> greater;
22+
};
23+
24+
using LeafOrNode = rfl::TaggedUnion<"type", Leaf, Node>;
25+
26+
rfl::Field<"leafOrNode", LeafOrNode> leaf_or_node;
27+
};
28+
29+
TEST(ubjson, test_box) {
30+
auto leaf1 = DecisionTree::Leaf{.value = 3.0};
31+
32+
auto leaf2 = DecisionTree::Leaf{.value = 5.0};
33+
34+
auto node = DecisionTree::Node{
35+
.critical_value = 10.0,
36+
.lesser = rfl::make_box<DecisionTree>(DecisionTree{leaf1}),
37+
.greater = rfl::make_box<DecisionTree>(DecisionTree{leaf2})};
38+
39+
const DecisionTree tree{.leaf_or_node = std::move(node)};
40+
41+
write_and_read(tree);
42+
43+
}
44+
} // namespace test_box

tests/ubjson/test_bytestring.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <iostream>
2+
#include <rfl.hpp>
3+
#include <string>
4+
#include <vector>
5+
6+
#include "write_and_read.hpp"
7+
8+
namespace test_bytestring {
9+
10+
struct TestStruct {
11+
rfl::Bytestring bytestring;
12+
};
13+
14+
TEST(ubjson, test_bytestring) {
15+
const auto test =
16+
TestStruct{.bytestring = rfl::Bytestring({std::byte{13}, std::byte{14},
17+
std::byte{15}, std::byte{16}})};
18+
19+
write_and_read(test);
20+
}
21+
} // namespace test_bytestring

0 commit comments

Comments
 (0)