Skip to content

Commit

Permalink
Add support for std::chrono::duration. Also split up the test cases i…
Browse files Browse the repository at this point in the history
…nto multiple translation units, because the memory and time for compiling are getting a bit ridiculous.
  • Loading branch information
swatanabe committed Jul 5, 2023
1 parent fdeac6f commit bea7a4f
Show file tree
Hide file tree
Showing 14 changed files with 781 additions and 543 deletions.
170 changes: 170 additions & 0 deletions libraries/psio/include/psio/chrono.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#pragma once

#include <psio/fracpack.hpp>

#include <chrono>

namespace psio
{

template <typename Rep, typename Period>
struct is_packable<std::chrono::duration<Rep, Period>> : std::bool_constant<true>
{
using is_p = is_packable<Rep>;
using T = std::chrono::duration<Rep, Period>;

static constexpr uint32_t fixed_size = is_p::fixed_size;
static constexpr bool is_variable_size = is_p::is_variable_size;
static constexpr bool is_optional = is_p::is_optional;
static constexpr bool supports_0_offset = is_p::supports_0_offset;

static bool has_value(const T& value) { return is_p::has_value(value.count()); }
template <bool Verify>
static bool has_value(const char* src, uint32_t pos, uint32_t end_pos)
{
return is_p::template has_value<Verify>(src, pos, end_pos);
}

template <bool Unpack, typename F>
static bool unpack_impl(F&& f, T* value)
{
if constexpr (Unpack)
{
Rep tmp;
bool result = f(&tmp);
*value = T{tmp};
return result;
}
else
{
return f((Rep*)nullptr);
}
}

template <typename S>
static void pack(const T& value, S& stream)
{
return is_p::pack(value.count(), stream);
}

static bool is_empty_container(const T& value)
{
return is_p::is_empty_container(value.count());
}
static bool is_empty_container(const char* src, uint32_t pos, uint32_t end_pos)
{
return is_p::is_empty_container(src, pos, end_pos);
}

template <typename S>
static void embedded_fixed_pack(const T& value, S& stream)
{
return is_p::embedded_fixed_pack(value.count(), stream);
}

template <typename S>
static void embedded_fixed_repack(const T& value,
uint32_t fixed_pos,
uint32_t heap_pos,
S& stream)
{
return is_p::embedded_fixed_repack(value.count(), fixed_pos, heap_pos, stream);
}

template <typename S>
static void embedded_variable_pack(const T& value, S& stream)
{
return is_p::embedded_variable_pack(value.count(), stream);
}

template <bool Unpack, bool Verify>
[[nodiscard]] static bool unpack(T* value,
bool& has_unknown,
bool& known_end,
const char* src,
uint32_t& pos,
uint32_t end_pos)
{
auto orig_pos = pos;
bool result = unpack_impl<Unpack>(
[&](Rep* value) {
return is_p::template unpack<Unpack, Verify>(value, has_unknown, known_end, src,
pos, end_pos);
},
value);
if constexpr (Verify && (PackableValidatedObject<T> || PackableValidatedView<T>))
{
return result && user_validate<Unpack, false>(value, src, orig_pos);
}
return result;
}

template <bool Unpack, bool Verify>
[[nodiscard]] static bool embedded_variable_unpack(T* value,
bool& has_unknown,
bool& known_end,
const char* src,
uint32_t& fixed_pos,
uint32_t end_fixed_pos,
uint32_t& heap_pos,
uint32_t end_heap_pos)
{
auto orig_pos = fixed_pos;
bool result = unpack_impl<Unpack>(
[&](Rep* value)
{
return is_p::template embedded_variable_unpack<Unpack, Verify>(
value, has_unknown, known_end, src, fixed_pos, end_fixed_pos, heap_pos,
end_heap_pos);
},
value);
if constexpr (Verify && (PackableValidatedObject<T> || PackableValidatedView<T>))
{
return result && user_validate<Unpack, true>(value, src, orig_pos);
}
return result;
}

template <bool Unpack, bool Verify>
[[nodiscard]] static bool embedded_unpack(T* value,
bool& has_unknown,
bool& known_end,
const char* src,
uint32_t& fixed_pos,
uint32_t end_fixed_pos,
uint32_t& heap_pos,
uint32_t end_heap_pos)
{
auto orig_pos = fixed_pos;
bool result = unpack_impl<Unpack>(
[&](Rep* value)
{
return is_p::template embedded_unpack<Unpack, Verify>(value, has_unknown, known_end,
src, fixed_pos, end_fixed_pos,
heap_pos, end_heap_pos);
},
value);
if constexpr (Verify && (PackableValidatedObject<T> || PackableValidatedView<T>))
{
return result && user_validate < Unpack,
!is_optional && is_variable_size > (value, src, orig_pos);
}
return result;
}
};

template <typename Rep, typename Period, typename Stream>
void to_json(const std::chrono::duration<Rep, Period>& obj, Stream& stream)
{
to_json(obj.count(), stream);
}

template <typename Rep, typename Period, typename Stream>
void from_json(std::chrono::duration<Rep, Period>& obj, Stream& stream)
{
Rep tmp;
from_json(tmp, stream);
obj = std::chrono::duration<Rep, Period>(tmp);
}

} // namespace psio
10 changes: 10 additions & 0 deletions libraries/psio/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ if(DEFINED IS_NATIVE)
benchmark.cpp
# crypto.cpp
test_fracpack.cpp
test_bool.cpp
test_char.cpp
test_int8.cpp
test_int16.cpp
test_int32.cpp
test_int64.cpp
test_float.cpp
test_struct.cpp
test_std_array.cpp
test_chrono.cpp
test_view.cpp
)
target_link_libraries(psio-tests psio catch2 Threads::Threads )
Expand Down
6 changes: 6 additions & 0 deletions libraries/psio/tests/test_bool.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "test_fracpack.hpp"

TEST_CASE("roundtrip bool")
{
test<bool>({false, true});
}
6 changes: 6 additions & 0 deletions libraries/psio/tests/test_char.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "test_fracpack.hpp"

TEST_CASE("roundtrip char")
{
test<char>({'a', 'b', 'c'});
}
10 changes: 10 additions & 0 deletions libraries/psio/tests/test_chrono.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <psio/chrono.hpp>

#include "test_fracpack.hpp"

TEST_CASE("chrono")
{
test<std::chrono::nanoseconds>({std::chrono::nanoseconds(0), std::chrono::nanoseconds(1),
std::chrono::nanoseconds::min(),
std::chrono::nanoseconds::max()});
}
21 changes: 21 additions & 0 deletions libraries/psio/tests/test_float.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "test_fracpack.hpp"

TEST_CASE("roudtrip float/double")
{
test<float>({std::copysign(std::numeric_limits<float>::quiet_NaN(), -1.0f),
std::copysign(std::numeric_limits<float>::signaling_NaN(), -1.0f),
-std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::max(),
-std::numeric_limits<float>::min(), -std::numeric_limits<float>::denorm_min(), -1,
-0.0f, std::numeric_limits<float>::min(), 0, 1,
std::numeric_limits<float>::denorm_min(), std::numeric_limits<float>::max(),
std::numeric_limits<float>::infinity(), std::numeric_limits<float>::signaling_NaN(),
std::numeric_limits<float>::quiet_NaN()});
test<double>(
{std::copysign(std::numeric_limits<double>::quiet_NaN(), -1.0),
std::copysign(std::numeric_limits<double>::signaling_NaN(), -1.0),
-std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::max(),
-std::numeric_limits<double>::min(), -std::numeric_limits<double>::denorm_min(), -1, -0.0,
std::numeric_limits<double>::min(), 0, 1, std::numeric_limits<double>::denorm_min(),
std::numeric_limits<double>::max(), std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::signaling_NaN(), std::numeric_limits<double>::quiet_NaN()});
}
Loading

0 comments on commit bea7a4f

Please sign in to comment.