#include "CBOR/Decoder.hpp" #include "CBOR/Encoder.hpp" #include "Cbor/Printer.hpp" #include #include #include #include #include #include #include struct SomeStruct { std::string name; double speed; float fov; std::int8_t thing; std::int64_t slots; std::uint32_t times; std::vector tools; }; std::size_t Encode(const SomeStruct &value, auto &buffer) { CBOR::BasicEncoder enc(buffer); enc.EncodeTag(15'000); enc.BeginMap(7); enc.Encode("name"); enc.Encode(value.name); enc.Encode("speed"); enc.Encode(value.speed); enc.Encode("fov"); enc.Encode(value.fov); enc.Encode("thing"); enc.Encode(value.thing); enc.Encode("slots"); enc.Encode(value.slots); enc.Encode("times"); enc.Encode(value.times); enc.Encode("tools"); enc.BeginIndefiniteArray(); for (std::string_view tool: value.tools) { enc.Encode(tool); } enc.End(); return enc.Size(); } SomeStruct Decode1(std::span buffer) { SomeStruct result; CBOR::Decoder dec(buffer); CBOR::TaggedItem tagged = dec.TaggedItem(); if (tagged.Tag() != 15'000) { throw std::runtime_error("test error: could not extract object tag"); } CBOR::Map object = tagged.Item().Map(); while (!object.Done()) { CBOR::KeyValue kv = object.Next(); std::string_view key = kv.Key().String(); CBOR::Item value = kv.Value(); if (key == "name") { result.name = value.String(); } else if (key == "speed") { result.speed = value.Double(); } else if (key == "fov") { result.fov = value.Float(); } else if (key == "thing") { result.thing = value.Int8(); } else if (key == "slots") { result.slots = value.Int64(); } else if (key == "times") { result.times = value.Uint32(); } else if (key == "tools") { CBOR::Array tools = value.Array(); while(!tools.Done()) { result.tools.push_back(std::string(tools.Next().String())); } } } return result; } SomeStruct Decode2(std::span buffer) { SomeStruct result; CBOR::Decoder dec(buffer); CBOR::TaggedItem tagged = dec.TaggedItem(); if (tagged.Tag() != 15'000) { throw std::runtime_error("test error: could not extract object tag"); } CBOR::Map object = tagged.Item().Map(); while (!object.Done()) { CBOR::KeyValue kv = object.Next(); std::string_view key = kv.Key().String(); CBOR::Item value = kv.Value(); if (key == "name") { result.name = value.String(); } else if (key == "speed") { result.speed = value.Double(); } else if (key == "fov") { result.fov = value.Float(); } else if (key == "thing") { result.thing = value.Int8(); } else if (key == "slots") { result.slots = value.Int64(); } else if (key == "times") { result.times = value.Uint32(); } else if (key == "tools") { CBOR::Array tools = value.Array(); while(!tools.Done()) { result.tools.push_back(""); CBOR::String tool = tools.Next().IndefiniteString(); while (!tool.Done()) { result.tools.back().append(tool.Next()); } } } } return result; } void Compare(const SomeStruct &s1, const SomeStruct &s2) { if (s1.name != s2.name) { throw std::runtime_error("test error: names are not the same"); } if (s1.speed != s2.speed) { throw std::runtime_error("test error: speed is not the same"); } if (s1.fov != s2.fov) { throw std::runtime_error("test error: fovs are not the same"); } if (s1.thing != s2.thing) { throw std::runtime_error("test error: things are not the same"); } if (s1.slots != s2.slots) { throw std::runtime_error("test error: slots are not the same"); } if (s1.times != s2.times) { throw std::runtime_error("test error: times are not the same"); } for (const auto &[t1, t2]: std::ranges::views::zip(s1.tools, s2.tools)) { if (t1 != t2) { throw std::runtime_error("test error: some tools are not the same"); } } } int main() { using namespace std::string_view_literals; //std::array buffer {}; std::vector buffer; SomeStruct expected { .name = "Player1", .speed = 5.0, .fov = 110.0f, .thing = -15, .slots = 40'000'000, .times = 1234567, .tools = { "pickaxe", "sword", "axe", "magical arrow", "iron ore", }, }; try { std::size_t encodedSize = Encode(expected, buffer); std::println("Encoded size: {}", encodedSize); std::print("Encoded hex: "); for (std::size_t i = 0; i < encodedSize; ++i) { std::print("{:02X} ", buffer[i]); } std::println(); SomeStruct result1 = Decode1(std::span(buffer.data(), encodedSize)); SomeStruct result2 = Decode2(std::span(buffer.data(), encodedSize)); std::println("JSON-esque serialization:"); CBOR::Print(std::cout, std::span(buffer.data(), encodedSize)); Compare(expected, result1); Compare(expected, result2); std::println("The test has been completed successfully."); } catch (const std::exception &e) { std::println("Error: {}", e.what()); } }