diff --git a/openVulkanoCpp/Extensions/RymlConverters.hpp b/openVulkanoCpp/Extensions/RymlConverters.hpp index 268d9cc..29748dc 100644 --- a/openVulkanoCpp/Extensions/RymlConverters.hpp +++ b/openVulkanoCpp/Extensions/RymlConverters.hpp @@ -10,6 +10,13 @@ #include "Math/Math.hpp" #include "Math/AABB.hpp" #include "Math/Pose.hpp" +#include "Math/DenseVector3i.hpp" +#include "Math/Int24.hpp" +#include "Math/Range.hpp" +#include "Math/RGB10A2.hpp" +#include "Math/RGB565.hpp" +#include "Math/RGBA5551.hpp" +#include "Math/Timestamp.hpp" #include #include #include @@ -142,4 +149,134 @@ namespace c4 uuid->assign(buf.str); return true; } + + template + inline size_t to_chars( + ryml::substr buf, + const OpenVulkano::Math::DenseVector3i& vec) + { + return ryml::format(buf, "({},{},{})", vec.X(), vec.Y(), vec.Z()); + } + + template + inline bool + from_chars(ryml::csubstr buf, + OpenVulkano::Math::DenseVector3i* vec) + { + int x, y, z; + size_t ret = ryml::unformat(buf, "({},{},{})", x, y, z); + if (ret != ryml::yml::npos) + { + *vec = DenseVector3i(x, y, z); + return true; + } + return false; + } + + size_t to_chars(c4::substr buf, const OpenVulkano::int24& value) + { + int intValue = static_cast(value); + return ryml::format(buf, "{}", intValue); + } + + bool from_chars(c4::csubstr buf, OpenVulkano::int24* value) + { + int intValue; + size_t ret = ryml::unformat(buf, "{}", intValue); + if (ret != ryml::yml::npos) + { + *value = OpenVulkano::int24(intValue); + return true; + } + return false; + } + + template size_t to_chars(c4::substr buf, const OpenVulkano::Math::Range& range) + { + return ryml::format(buf, "[{},{}]", range.GetMin(), range.GetMax()); + } + + template bool from_chars(c4::csubstr buf, OpenVulkano::Math::Range* range) + { + T minVal, maxVal; + size_t ret = ryml::unformat(buf, "[{},{}]", minVal, maxVal); + if (ret != ryml::yml::npos) + { + *range = Range(minVal, maxVal); + return true; + } + return false; + } + + template size_t to_chars(c4::substr buf, const OpenVulkano::Math::RGB10A2& color) + { + return ryml::format(buf, "[{},{},{},{}]", color.r, color.g, color.b, color.a); + } + + template bool from_chars(c4::csubstr buf, OpenVulkano::Math::RGB10A2* color) + { + T r, g, b, a; + size_t ret = ryml::unformat(buf, "[{},{},{},{}]", r, g, b, a); + if (ret != ryml::yml::npos) + { + color->r = r; + color->g = g; + color->b = b; + color->a = a; + return true; + } + return false; + } + + size_t to_chars(ryml::substr buf, const OpenVulkano::Math::RGB565& rgb) + { + return ryml::format(buf, "[{},{},{}]", rgb.r, rgb.g, rgb.b); + } + + bool from_chars(ryml::csubstr buf, OpenVulkano::Math::RGB565* rgb) + { + int r, g, b; + size_t ret = ryml::unformat (buf, "[{},{},{}]", r, g, b); + rgb->r = r; + rgb->g = g; + rgb->b = b; + return ret != ryml::yml::npos; + } + + size_t to_chars(c4::substr buf, const OpenVulkano::Math::RGBA5551& color) + { + return ryml::format(buf, "[{},{},{},{}]", color.r, color.g, color.b, color.a); + } + + bool from_chars(c4::csubstr buf, OpenVulkano::Math::RGBA5551* color) + { + int r, g, b, a; + size_t ret = ryml::unformat(buf, "[{},{},{},{}]", r, g, b, a); + if (ret != ryml::yml::npos) + { + color->r = r; + color->g = g; + color->b = b; + color->a = a; + return true; + } + return false; + } + + size_t to_chars(c4::substr buf, const OpenVulkano::Math::Timestamp& ts) + { + return ryml::format(buf, "{}", ts.GetNanos()); + } + + bool from_chars(c4::csubstr buf, OpenVulkano::Math::Timestamp* ts) + { + uint64_t nanos; + size_t ret = ryml::unformat(buf, "{}", nanos); + if (ret != ryml::yml::npos) + { + *ts = OpenVulkano::Math::Timestamp(nanos); + return true; + } + return false; + } } \ No newline at end of file diff --git a/openVulkanoCpp/Math/RGB565.hpp b/openVulkanoCpp/Math/RGB565.hpp index 7b1977e..f4aacd6 100644 --- a/openVulkanoCpp/Math/RGB565.hpp +++ b/openVulkanoCpp/Math/RGB565.hpp @@ -80,9 +80,9 @@ namespace OpenVulkano::Math { } - uint8_t GetR() { return Unmake5(r); } - uint8_t GetG() { return Unmake6(g); } - uint8_t GetB() { return Unmake5(b); } + uint8_t GetR() const { return Unmake5(r); } + uint8_t GetG() const { return Unmake6(g); } + uint8_t GetB() const { return Unmake5(b); } template, bool> = true> Math::Vector3 Get3() diff --git a/tests/Extensions/RymlConverters.cpp b/tests/Extensions/RymlConverters.cpp index 7d8ae03..f49d97c 100644 --- a/tests/Extensions/RymlConverters.cpp +++ b/tests/Extensions/RymlConverters.cpp @@ -172,3 +172,273 @@ TEST_CASE("UUID to_chars and from_chars", "[RymlConverters]") REQUIRE(from_chars("123e4567-e89b-12d3-a456-426655440000", &parsed_uuid)); REQUIRE(parsed_uuid.string() == uuid.string()); } + +TEST_CASE("DenseVector3i to_chars and from_chars", "[RymlConverters]") +{ + using MyDenseVector3i = DenseVector3i; + MyDenseVector3i vec(12, -5, 7); + char buffer[64]; + + size_t len = to_chars(ryml::substr(buffer, sizeof(buffer)), vec); + REQUIRE(len > 0); + + std::string expected = "(12,-5,7)"; + REQUIRE(std::string(buffer, len) == expected); + + std::string serialized = "(12,-5,7)"; + MyDenseVector3i deserialized_vec(0, 0, 0); + + bool success = from_chars(ryml::csubstr(serialized.c_str(), serialized.size()), &deserialized_vec); + REQUIRE(success); + + REQUIRE(deserialized_vec.X() == 12); + REQUIRE(deserialized_vec.Y() == -5); + REQUIRE(deserialized_vec.Z() == 7); + + len = to_chars(ryml::substr(buffer, sizeof(buffer)), vec); + + MyDenseVector3i roundtrip_vec(0, 0, 0); + success = from_chars(ryml::csubstr(buffer, len), &roundtrip_vec); + REQUIRE(success); + + REQUIRE(roundtrip_vec.X() == vec.X()); + REQUIRE(roundtrip_vec.Y() == vec.Y()); + REQUIRE(roundtrip_vec.Z() == vec.Z()); +} + +TEST_CASE("int24 to_chars and from_chars", "[RymlConverters]") +{ + char buffer[20]; + int24 originalValue = 1234567; + c4::substr buf(buffer); + + size_t written = to_chars(buf, originalValue); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "1234567"); + + { + int24 parsedValue; + c4::csubstr buf("1234567"); + bool success = from_chars(buf, &parsedValue); + REQUIRE(success); + REQUIRE(static_cast(parsedValue) == 1234567); + } + + originalValue = -7654321; + written = to_chars(buf, originalValue); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "-7654321"); + + { + int24 parsedValue; + c4::csubstr buf("-7654321"); + bool success = from_chars(buf, &parsedValue); + REQUIRE(success); + REQUIRE(static_cast(parsedValue) == -7654321); + } +} + +TEST_CASE("Range serialization and deserialization", "[RymlConverters]") +{ + char buffer[30]; + c4::substr buf(buffer); + + SECTION("Serialization") + { + Range range(5, 15); + size_t written = to_chars(buf, range); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "[5,15]"); + } + + SECTION("Deserialization") + { + Range range; + c4::csubstr buf("[5, 15]"); + bool success = from_chars(buf, &range); + REQUIRE(success); + REQUIRE(range.GetMin() == 5); + REQUIRE(range.GetMax() == 15); + } + + SECTION("Negative Range") + { + Range range(-10, -2); + size_t written = to_chars(buf, range); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "[-10,-2]"); + + Range parsedRange; + c4::csubstr negBuf("[-10,-2]"); + bool success = from_chars(negBuf, &parsedRange); + REQUIRE(success); + REQUIRE(parsedRange.GetMin() == -10); + REQUIRE(parsedRange.GetMax() == -2); + } + + SECTION("Floating Point Range") + { + Range range(1.5, 3.75); + size_t written = to_chars(buf, range); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "[1.5,3.75]"); + + Range parsedRange; + c4::csubstr floatBuf("[1.5,3.75]"); + bool success = from_chars(floatBuf, &parsedRange); + REQUIRE(success); + REQUIRE(parsedRange.GetMin() == 1.5); + REQUIRE(parsedRange.GetMax() == 3.75); + } +} + +TEST_CASE("RGB10A2 serialization and deserialization", "[RymlConverters]") +{ + char buffer[50]; + c4::substr buf(buffer); + + SECTION("Serialization") + { + RGB10A2 color(0); + color.r = 512; + color.g = 768; + color.b = 256; + color.a = 3; + + size_t written = to_chars(buf, color); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "[512,768,256,3]"); + } + + SECTION("Deserialization") + { + RGB10A2 color; + c4::csubstr buf("[512,768,256,3]"); + bool success = from_chars(buf, &color); + REQUIRE(success); + REQUIRE(color.r == 512); + REQUIRE(color.g == 768); + REQUIRE(color.b == 256); + REQUIRE(color.a == 3); + } + + SECTION("Boundary Values") + { + RGB10A2 color; + color.r = RGB10A2::MAX_VALUE; + color.g = RGB10A2::MAX_VALUE; + color.b = RGB10A2::MAX_VALUE; + color.a = RGB10A2::MAX_ALPHA_VALUE; + + size_t written = to_chars(buf, color); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) + == "[" + std::to_string(RGB10A2::MAX_VALUE) + "," + + std::to_string(RGB10A2::MAX_VALUE) + "," + std::to_string(RGB10A2::MAX_VALUE) + + "," + std::to_string(RGB10A2::MAX_ALPHA_VALUE) + "]"); + + RGB10A2 parsedColor; + c4::csubstr boundaryBuf(buffer, written); + bool success = from_chars(boundaryBuf, &parsedColor); + REQUIRE(success); + REQUIRE(parsedColor.r == RGB10A2::MAX_VALUE); + REQUIRE(parsedColor.g == RGB10A2::MAX_VALUE); + REQUIRE(parsedColor.b == RGB10A2::MAX_VALUE); + REQUIRE(parsedColor.a == RGB10A2::MAX_ALPHA_VALUE); + } + + SECTION("Negative Values (Signed Type)") + { + RGB10A2 color; + color.r = -512; + color.g = -256; + color.b = -128; + color.a = -1; + + size_t written = to_chars(buf, color); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "[-512,-256,-128,-1]"); + + RGB10A2 parsedColor; + c4::csubstr negBuf(buffer, written); + bool success = from_chars(negBuf, &parsedColor); + REQUIRE(success); + REQUIRE(parsedColor.r == -512); + REQUIRE(parsedColor.g == -256); + REQUIRE(parsedColor.b == -128); + REQUIRE(parsedColor.a == -1); + } +} + +TEST_CASE("RGB565 Serialization and Deserialization", "[RymlConverters]") +{ + Vector3 color { 255, 128, 64 }; + RGB565 rgb(color); + + char buffer[50]; + c4::substr buf(buffer); + size_t written = to_chars(buffer, rgb); + REQUIRE(written > 0); + + RGB565 rgbDeserialized; + bool success = from_chars(buffer, &rgbDeserialized); + REQUIRE(success); + + REQUIRE(rgb.GetR() == rgbDeserialized.GetR()); + REQUIRE(rgb.GetG() == rgbDeserialized.GetG()); + REQUIRE(rgb.GetB() == rgbDeserialized.GetB()); +} + +TEST_CASE("RGBA5551 serialization and deserialization", "[RymlConverters]") +{ + char buffer[50]; + c4::substr buf(buffer); + + SECTION("Serialization") + { + RGBA5551 color; + color.r = 31; + color.g = 31; + color.b = 31; + color.a = 1; + + size_t written = to_chars(buf, color); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "[31,31,31,1]"); + } + + SECTION("Deserialization") + { + RGBA5551 color; + c4::csubstr buf("[31,31,31,1]"); + bool success = from_chars(buf, &color); + REQUIRE(success); + REQUIRE(color.r == 31); + REQUIRE(color.g == 31); + REQUIRE(color.b == 31); + REQUIRE(color.a == 1); + } +} + +TEST_CASE("Timestamp serialization and deserialization", "[RymlConverters]") +{ + char buffer[50]; + c4::substr buf(buffer); + + SECTION("Serialization") + { + Timestamp ts((uint64_t)123); + size_t written = to_chars(buf, ts); + REQUIRE(written > 0); + REQUIRE(std::string(buffer, written) == "123"); + } + + SECTION("Deserialization") + { + Timestamp ts; + c4::csubstr buf("123"); + bool success = from_chars(buf, &ts); + REQUIRE(success); + REQUIRE(ts.GetNanos() == 123); + } +} \ No newline at end of file