mirror of
https://github.com/MadeOfJelly/MushMachine.git
synced 2024-10-29 22:45:34 +01:00
Green Sky
f27300a8fa
it has the important stuff, but still misses conviniences like buffers and optimizations like varints. only works for little endian but theoretically only needs endian detection to be able to support bigendian
554 lines
19 KiB
C++
554 lines
19 KiB
C++
#include <mm/s6zer/serialize.hpp>
|
|
|
|
#include <array>
|
|
#include <ostream>
|
|
|
|
#include <mm/random/srng.hpp>
|
|
#include <mm/scalar_range2.hpp>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
namespace MM {
|
|
template<typename Char, typename T>
|
|
std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& out, const MM::ScalarRange2<T>& range) {
|
|
return out << "{ min: " << static_cast<int64_t>(range.min()) << ", max: " << static_cast<int64_t>(range.max()) << " }";
|
|
}
|
|
} // MM
|
|
|
|
TEST(s6zer, bits_required_static) {
|
|
static_assert(MM::s6zer::bits_required(0)== 0);
|
|
static_assert(MM::s6zer::bits_required(1)== 1);
|
|
static_assert(MM::s6zer::bits_required(2)== 2);
|
|
static_assert(MM::s6zer::bits_required(3)== 2);
|
|
static_assert(MM::s6zer::bits_required(4)== 3);
|
|
static_assert(MM::s6zer::bits_required(32)== 6);
|
|
static_assert(MM::s6zer::bits_required(0xffffffff)== 32);
|
|
static_assert(MM::s6zer::bits_required(0xffffff00)== 32);
|
|
static_assert(MM::s6zer::bits_required(0xf0000a00)== 32);
|
|
static_assert(MM::s6zer::bits_required(0x0f000000)== 28);
|
|
static_assert(MM::s6zer::bits_required(0x0000f000)== 16);
|
|
}
|
|
|
|
TEST(s6zer, byte_swap) {
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint8_t>(0x00)) == 0x00);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint8_t>(0xff)) == 0xff);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint8_t>(0x10)) == 0x10);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint8_t>(0xfe)) == 0xfe);
|
|
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint16_t>(0x0000)) == 0x0000);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint16_t>(0xffff)) == 0xffff);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint16_t>(0x00fe)) == 0xfe00);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint16_t>(0xfefe)) == 0xfefe);
|
|
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint32_t>(0x00000000)) == 0x00000000);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint32_t>(0xffffffff)) == 0xffffffff);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint32_t>(0xf0f00000)) == 0x0000f0f0);
|
|
static_assert(MM::s6zer::detail::byte_swap(static_cast<uint32_t>(0xfe0000ef)) == 0xef0000fe);
|
|
}
|
|
|
|
TEST(s6zer, stream_normalcase1) {
|
|
const uint32_t num1_orig {0b111};
|
|
const uint32_t num1_orig_bits {3};
|
|
const uint32_t num2_orig {0b1111111111};
|
|
const uint32_t num2_orig_bits {10};
|
|
const uint32_t num3_orig {0b111111111111111111111111};
|
|
const uint32_t num3_orig_bits {24};
|
|
|
|
std::array<uint32_t, 2> buffer;
|
|
size_t buffer_size = buffer.size()*sizeof(uint32_t);
|
|
{
|
|
MM::s6zer::StreamWriter writer{buffer.data(), buffer_size};
|
|
|
|
bool r = false;
|
|
ASSERT_EQ(writer._scratch, 0x0);
|
|
ASSERT_EQ(writer._scratch_bits, 0);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, 0);
|
|
ASSERT_EQ(writer.bytesWritten(), 0);
|
|
|
|
r = writer.serializeBits(num1_orig, num1_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0b0000000000000000000000000000000000000000000000000000000000000'111);
|
|
ASSERT_EQ(writer._scratch_bits, 3);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits);
|
|
|
|
r = writer.serializeBits(num2_orig, num2_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0b000000000000000000000000000000000000000000000000000'111'1111111111);
|
|
ASSERT_EQ(writer._scratch_bits, 3+10);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits);
|
|
|
|
r = writer.serializeBits(num3_orig, num3_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0b00000000000000000000000000000000000000000000000000000000000'11111);
|
|
ASSERT_EQ(writer._scratch_bits, (3+10+24)-32);
|
|
ASSERT_EQ(writer._word_index, 1);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits+num3_orig_bits);
|
|
|
|
r = writer.flush();
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0);
|
|
ASSERT_EQ(writer._scratch_bits, 0);
|
|
ASSERT_EQ(writer._word_index, 2);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits+num3_orig_bits); // flush does not change bits written
|
|
ASSERT_EQ(writer.bytesWritten(), 5); // 4.625 , so ceil
|
|
|
|
buffer_size = writer.bytesWritten();
|
|
}
|
|
|
|
std::cout << "buffer_size: " << buffer_size << "\n";
|
|
|
|
ASSERT_EQ(buffer[0], 0xffffffff);
|
|
ASSERT_EQ(buffer[1], 0b000000000000000000000000000'11111);
|
|
|
|
{
|
|
MM::s6zer::StreamReader reader{buffer.data(), buffer_size};
|
|
|
|
bool r = false;
|
|
ASSERT_EQ(reader._scratch, 0x0);
|
|
ASSERT_EQ(reader._scratch_bits, 0);
|
|
ASSERT_EQ(reader._word_index, 0);
|
|
|
|
uint32_t num1 {0};
|
|
r = reader.serializeBits(num1, num1_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num1, num1_orig);
|
|
ASSERT_EQ(reader._scratch, 0b00000000'00000000'00000000'00000000'000'11111111111111111111111111111);
|
|
ASSERT_EQ(reader._scratch_bits, 29);
|
|
ASSERT_EQ(reader._word_index, 1); // index refers to next dword
|
|
|
|
uint32_t num2 {0};
|
|
r = reader.serializeBits(num2, num2_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num2, num2_orig);
|
|
ASSERT_EQ(reader._scratch, 0b00000000'00000000'00000000'00000000'000'00000'00000'1111111111111111111);
|
|
ASSERT_EQ(reader._scratch_bits, 19);
|
|
ASSERT_EQ(reader._word_index, 1); // <=32, so should not yet have read next dword
|
|
|
|
uint32_t num3 {0};
|
|
r = reader.serializeBits(num3, num3_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num3, num3_orig);
|
|
ASSERT_EQ(reader._scratch, 0x0); // no data left
|
|
ASSERT_EQ(reader._scratch_bits, 27);
|
|
ASSERT_EQ(reader._word_index, 2);
|
|
|
|
// error case
|
|
uint32_t num4 {0};
|
|
r = reader.serializeBits(num4, 32);
|
|
ASSERT_FALSE(r);
|
|
}
|
|
}
|
|
|
|
TEST(s6zer, stream_normalcase1_1) {
|
|
const uint32_t num1_orig {0b101};
|
|
const uint32_t num1_orig_bits {3};
|
|
const uint32_t num2_orig {0b1010101010};
|
|
const uint32_t num2_orig_bits {10};
|
|
const uint32_t num3_orig {0b101010101010101010101010};
|
|
const uint32_t num3_orig_bits {24};
|
|
|
|
std::array<uint32_t, 2> buffer;
|
|
size_t buffer_size = buffer.size()*sizeof(uint32_t);
|
|
{
|
|
MM::s6zer::StreamWriter writer{buffer.data(), buffer_size};
|
|
|
|
bool r = false;
|
|
ASSERT_EQ(writer._scratch, 0x0);
|
|
ASSERT_EQ(writer._scratch_bits, 0);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, 0);
|
|
ASSERT_EQ(writer.bytesWritten(), 0);
|
|
|
|
r = writer.serializeBits(num1_orig, num1_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0b0000000000000000000000000000000000000000000000000000000000000'101);
|
|
ASSERT_EQ(writer._scratch_bits, 3);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits);
|
|
|
|
r = writer.serializeBits(num2_orig, num2_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0b000000000000000000000000000000000000000000000000000'1010101010'101);
|
|
ASSERT_EQ(writer._scratch_bits, 3+10);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits);
|
|
|
|
r = writer.serializeBits(num3_orig, num3_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0b00000000000000000000000000000000000000000000000000000000000'10101); // the high bits of the 24
|
|
ASSERT_EQ(writer._scratch_bits, (3+10+24)-32);
|
|
ASSERT_EQ(writer._word_index, 1);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits+num3_orig_bits);
|
|
|
|
r = writer.flush();
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0);
|
|
ASSERT_EQ(writer._scratch_bits, 0);
|
|
ASSERT_EQ(writer._word_index, 2);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits+num3_orig_bits); // flush does not change bits written
|
|
ASSERT_EQ(writer.bytesWritten(), 5); // 4.625 , so ceil
|
|
|
|
buffer_size = writer.bytesWritten();
|
|
}
|
|
|
|
std::cout << "buffer_size: " << buffer_size << "\n";
|
|
|
|
ASSERT_EQ(buffer[0], 0b0101010101010101010'1010101010'101);
|
|
ASSERT_EQ(buffer[1], 0b000000000000000000000000000'10101);
|
|
|
|
{
|
|
MM::s6zer::StreamReader reader{buffer.data(), buffer_size};
|
|
|
|
bool r = false;
|
|
ASSERT_EQ(reader._scratch, 0x0);
|
|
ASSERT_EQ(reader._scratch_bits, 0);
|
|
ASSERT_EQ(reader._word_index, 0);
|
|
|
|
uint32_t num1 {0};
|
|
r = reader.serializeBits(num1, num1_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num1, num1_orig);
|
|
ASSERT_EQ(reader._scratch, 0b00000000'00000000'00000000'00000000'000'0101010101010101010'1010101010);
|
|
ASSERT_EQ(reader._scratch_bits, 29);
|
|
ASSERT_EQ(reader._word_index, 1); // index refers to next dword
|
|
|
|
uint32_t num2 {0};
|
|
r = reader.serializeBits(num2, num2_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num2, num2_orig);
|
|
ASSERT_EQ(reader._scratch, 0b00000000'00000000'00000000'00000000'000'00000'00000'0101010101010101010);
|
|
ASSERT_EQ(reader._scratch_bits, 19);
|
|
ASSERT_EQ(reader._word_index, 1); // <=32, so should not yet have read next dword
|
|
|
|
uint32_t num3 {0};
|
|
r = reader.serializeBits(num3, num3_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num3, num3_orig);
|
|
ASSERT_EQ(reader._scratch, 0x0); // no data left
|
|
ASSERT_EQ(reader._scratch_bits, 27);
|
|
ASSERT_EQ(reader._word_index, 2);
|
|
|
|
// error case
|
|
uint32_t num4 {0};
|
|
r = reader.serializeBits(num4, 32);
|
|
ASSERT_FALSE(r);
|
|
}
|
|
}
|
|
|
|
TEST(s6zer, stream_normalcase2) {
|
|
// we now take each number as its maximum, synthetic for testing
|
|
const uint32_t num1_orig {17};
|
|
const uint32_t num1_orig_bits {MM::s6zer::bits_required(num1_orig)};
|
|
const uint32_t num2_orig {1};
|
|
const uint32_t num2_orig_bits {MM::s6zer::bits_required(num2_orig)};
|
|
const uint32_t num3_orig {1298989};
|
|
const uint32_t num3_orig_bits {MM::s6zer::bits_required(num3_orig)};
|
|
|
|
std::array<uint32_t, 2> buffer;
|
|
size_t buffer_size = buffer.size()*sizeof(uint32_t);
|
|
{
|
|
MM::s6zer::StreamWriter writer{buffer.data(), buffer_size};
|
|
|
|
// fewer asserts
|
|
bool r = false;
|
|
ASSERT_EQ(writer._scratch, 0x0);
|
|
ASSERT_EQ(writer._scratch_bits, 0);
|
|
ASSERT_EQ(writer._word_index, 0);
|
|
ASSERT_EQ(writer._bits_written, 0);
|
|
ASSERT_EQ(writer.bytesWritten(), 0);
|
|
|
|
r = writer.serializeBits(num1_orig, num1_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits);
|
|
|
|
r = writer.serializeBits(num2_orig, num2_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits);
|
|
|
|
r = writer.serializeBits(num3_orig, num3_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits+num3_orig_bits);
|
|
|
|
r = writer.flush();
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(writer._scratch, 0);
|
|
ASSERT_EQ(writer._scratch_bits, 0);
|
|
ASSERT_EQ(writer._bits_written, num1_orig_bits+num2_orig_bits+num3_orig_bits); // flush does not change bits written
|
|
|
|
buffer_size = writer.bytesWritten();
|
|
}
|
|
|
|
std::cout << "buffer_size: " << buffer_size << "\n";
|
|
|
|
{
|
|
MM::s6zer::StreamReader reader{buffer.data(), buffer_size};
|
|
|
|
bool r = false;
|
|
ASSERT_EQ(reader._scratch, 0x0);
|
|
ASSERT_EQ(reader._scratch_bits, 0);
|
|
ASSERT_EQ(reader._word_index, 0);
|
|
ASSERT_EQ(reader._bits_read, 0);
|
|
|
|
uint32_t num1 {0};
|
|
r = reader.serializeBits(num1, num1_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num1, num1_orig);
|
|
|
|
uint32_t num2 {0};
|
|
r = reader.serializeBits(num2, num2_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num2, num2_orig);
|
|
|
|
uint32_t num3 {0};
|
|
r = reader.serializeBits(num3, num3_orig_bits);
|
|
ASSERT_TRUE(r);
|
|
ASSERT_EQ(num3, num3_orig);
|
|
|
|
// error case
|
|
uint32_t num4 {0};
|
|
r = reader.serializeBits(num4, 32);
|
|
ASSERT_FALSE(r);
|
|
}
|
|
}
|
|
|
|
// emscripten cant do this
|
|
#ifndef __EMSCRIPTEN__
|
|
bool serialize_int_death_fn(void) {
|
|
std::array<uint32_t, 32> dummy_buffer;
|
|
MM::s6zer::StreamReader reader{dummy_buffer.data(), dummy_buffer.size()*sizeof(uint32_t)};
|
|
int32_t value{0};
|
|
|
|
MM_S6ZER_BAIL(reader.serializeInt(value, 20, -20)); // wrong order
|
|
|
|
return true;
|
|
}
|
|
|
|
TEST(s6zer, serialize_int_death) {
|
|
ASSERT_DEATH({
|
|
[[maybe_unused]] bool ret = serialize_int_death_fn();
|
|
}, "failed");
|
|
}
|
|
#endif
|
|
|
|
TEST(s6zer, reader_bits_bug1) {
|
|
const std::array<uint32_t, 2> buffer {
|
|
0x27'5c'19'a1,
|
|
0x00'00'3a'c3
|
|
};
|
|
const size_t buffer_size {6};
|
|
|
|
MM::s6zer::StreamReader reader{buffer.data(), buffer_size};
|
|
|
|
uint8_t value_0 {0};
|
|
ASSERT_TRUE(reader.serializeBits(value_0));
|
|
ASSERT_EQ(value_0, 0xa1);
|
|
|
|
ASSERT_EQ(reader._scratch_bits, 24);
|
|
ASSERT_EQ(reader._scratch, 0x0000000000'27'5c'19);
|
|
|
|
uint32_t value_1 {0};
|
|
ASSERT_TRUE(reader.serializeBits(value_1));
|
|
ASSERT_EQ(value_1, 0xc3'27'5c'19);
|
|
|
|
ASSERT_EQ(reader._scratch_bits, 24);
|
|
ASSERT_EQ(reader._scratch, 0x00000000000000'3a);
|
|
|
|
uint8_t value_2 {0};
|
|
ASSERT_TRUE(reader.serializeBits(value_2));
|
|
ASSERT_EQ(value_2, 0x3a);
|
|
|
|
ASSERT_EQ(reader._scratch, 0x0000000000000000);
|
|
}
|
|
|
|
struct TestStruct {
|
|
// integers bits
|
|
uint8_t u8 {0};
|
|
uint16_t u16 {0};
|
|
uint32_t u32 {0};
|
|
//uint64_t u64 {0};
|
|
|
|
bool b1 {false};
|
|
|
|
// integers ranges
|
|
uint8_t r_u8 {0};
|
|
constexpr static MM::ScalarRange2<uint8_t> r_u8_r{10, 60};
|
|
int8_t r_i8 {0};
|
|
constexpr static MM::ScalarRange2<int8_t> r_i8_r{-10, 5};
|
|
uint16_t r_u16 {0};
|
|
constexpr static MM::ScalarRange2<uint16_t> r_u16_r{1, 1026};
|
|
int16_t r_i16 {0};
|
|
constexpr static MM::ScalarRange2<int16_t> r_i16_r{-1, 1026};
|
|
uint32_t r_u32 {0};
|
|
constexpr static MM::ScalarRange2<uint32_t> r_u32_r{0, 12341234};
|
|
int32_t r_i32 {0};
|
|
constexpr static MM::ScalarRange2<int32_t> r_i32_r{-12341234, 10};
|
|
|
|
// floats
|
|
float f32 {0.f};
|
|
double f64 {0.};
|
|
|
|
// float compressed [0; 1] range
|
|
constexpr static float c0_f32_resolution = 0.001;
|
|
constexpr static MM::ScalarRange2<float> c0_f32_r{0.f, 1.f};
|
|
float c0_f32_0 {0.f};
|
|
float c0_f32_1 {0.f};
|
|
float c0_f32_2 {0.f};
|
|
float c0_f32_3 {0.f};
|
|
|
|
// float compressed [-1; 1] range
|
|
constexpr static float c1_f32_resolution = 0.05;
|
|
constexpr static MM::ScalarRange2<float> c1_f32_r{-1.f, 1.f};
|
|
float c1_f32_0 {0.f};
|
|
float c1_f32_1 {0.f};
|
|
float c1_f32_2 {0.f};
|
|
float c1_f32_3 {0.f};
|
|
|
|
// float compressed [-1000; 1000] range
|
|
constexpr static float c2_f32_resolution = 0.01;
|
|
constexpr static MM::ScalarRange2<float> c2_f32_r{-1000.f, 1000.f};
|
|
float c2_f32_0 {0.f};
|
|
float c2_f32_1 {0.f};
|
|
float c2_f32_2 {0.f};
|
|
float c2_f32_3 {0.f};
|
|
};
|
|
|
|
MM_DEFINE_SERIALIZE(TestStruct,
|
|
MM_S6ZER_BAIL(stream.serializeBits(data.u8))
|
|
MM_S6ZER_BAIL(stream.serializeBits(data.u16))
|
|
MM_S6ZER_BAIL(stream.serializeBits(data.u32))
|
|
|
|
MM_S6ZER_BAIL(stream.serializeBool(data.b1))
|
|
|
|
MM_S6ZER_BAIL(stream.serializeInt(data.r_u8, data.r_u8_r.min(), data.r_u8_r.max()))
|
|
MM_S6ZER_BAIL(stream.serializeInt(data.r_i8, data.r_i8_r.min(), data.r_i8_r.max()))
|
|
MM_S6ZER_BAIL(stream.serializeInt(data.r_u16, data.r_u16_r.min(), data.r_u16_r.max()))
|
|
MM_S6ZER_BAIL(stream.serializeInt(data.r_i16, data.r_i16_r.min(), data.r_i16_r.max()))
|
|
MM_S6ZER_BAIL(stream.serializeInt(data.r_u32, data.r_u32_r.min(), data.r_u32_r.max()))
|
|
MM_S6ZER_BAIL(stream.serializeInt(data.r_i32, data.r_i32_r.min(), data.r_i32_r.max()))
|
|
|
|
MM_S6ZER_BAIL(stream.serializeFloat(data.f32))
|
|
MM_S6ZER_BAIL(stream.serializeDouble(data.f64))
|
|
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c0_f32_0, data.c0_f32_r.min(), data.c0_f32_r.max(), data.c0_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c0_f32_1, data.c0_f32_r.min(), data.c0_f32_r.max(), data.c0_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c0_f32_2, data.c0_f32_r.min(), data.c0_f32_r.max(), data.c0_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c0_f32_3, data.c0_f32_r.min(), data.c0_f32_r.max(), data.c0_f32_resolution))
|
|
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c1_f32_0, data.c1_f32_r.min(), data.c1_f32_r.max(), data.c1_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c1_f32_1, data.c1_f32_r.min(), data.c1_f32_r.max(), data.c1_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c1_f32_2, data.c1_f32_r.min(), data.c1_f32_r.max(), data.c1_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c1_f32_3, data.c1_f32_r.min(), data.c1_f32_r.max(), data.c1_f32_resolution))
|
|
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c2_f32_0, data.c2_f32_r.min(), data.c2_f32_r.max(), data.c2_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c2_f32_1, data.c2_f32_r.min(), data.c2_f32_r.max(), data.c2_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c2_f32_2, data.c2_f32_r.min(), data.c2_f32_r.max(), data.c2_f32_resolution))
|
|
MM_S6ZER_BAIL(stream.serializeFloatCompressed(data.c2_f32_3, data.c2_f32_r.min(), data.c2_f32_r.max(), data.c2_f32_resolution))
|
|
)
|
|
|
|
TEST(s6zer, stream_normalfull) {
|
|
std::array<uint32_t, 128> buffer;
|
|
size_t buffer_size = buffer.size()*sizeof(uint32_t);
|
|
|
|
MM::Random::SRNG rng{1337, 0};
|
|
|
|
const TestStruct data_in{
|
|
static_cast<uint8_t>(rng()),
|
|
static_cast<uint16_t>(rng()),
|
|
static_cast<uint32_t>(rng()),
|
|
|
|
rng.roll(0.5f),
|
|
|
|
rng.range(TestStruct::r_u8_r),
|
|
rng.range(TestStruct::r_i8_r),
|
|
rng.range(TestStruct::r_u16_r),
|
|
rng.range(TestStruct::r_i16_r),
|
|
rng.range(TestStruct::r_u32_r),
|
|
rng.range(TestStruct::r_i32_r),
|
|
|
|
rng.negOneToOne() * 10000000.f,
|
|
rng.negOneToOne() * 10000000.,
|
|
|
|
rng.range(TestStruct::c0_f32_r),
|
|
rng.range(TestStruct::c0_f32_r),
|
|
rng.range(TestStruct::c0_f32_r),
|
|
rng.range(TestStruct::c0_f32_r),
|
|
|
|
rng.range(TestStruct::c1_f32_r),
|
|
rng.range(TestStruct::c1_f32_r),
|
|
rng.range(TestStruct::c1_f32_r),
|
|
rng.range(TestStruct::c1_f32_r),
|
|
|
|
rng.range(TestStruct::c2_f32_r),
|
|
rng.range(TestStruct::c2_f32_r),
|
|
rng.range(TestStruct::c2_f32_r),
|
|
rng.range(TestStruct::c2_f32_r),
|
|
};
|
|
|
|
std::cout << "struct size: " << sizeof(TestStruct) << "\n";
|
|
|
|
{
|
|
MM::s6zer::StreamWriter writer{buffer.data(), buffer_size};
|
|
|
|
ASSERT_TRUE(mm_serialize(writer, data_in));
|
|
|
|
ASSERT_TRUE(writer.flush());
|
|
buffer_size = writer.bytesWritten();
|
|
}
|
|
|
|
std::cout << "buffer_size: " << buffer_size << "\n";
|
|
|
|
TestStruct data_out{}; // all zero
|
|
|
|
{
|
|
MM::s6zer::StreamReader reader{buffer.data(), buffer_size};
|
|
|
|
ASSERT_TRUE(mm_serialize(reader, data_out));
|
|
|
|
ASSERT_EQ(reader._scratch, 0x0000000000000000);
|
|
}
|
|
|
|
std::cout << "buffer: ";
|
|
for (size_t i = 0; i < buffer_size; i++) {
|
|
std::cout << std::hex << static_cast<uint32_t>(reinterpret_cast<uint8_t*>(buffer.data())[i]) << "'";
|
|
}
|
|
std::cout << "\n";
|
|
|
|
//std::cout << "data_out: \n" << data_out;
|
|
|
|
ASSERT_EQ(data_in.u8, data_out.u8);
|
|
ASSERT_EQ(data_in.u16, data_out.u16);
|
|
ASSERT_EQ(data_in.u32, data_out.u32);
|
|
|
|
ASSERT_EQ(data_in.b1, data_out.b1);
|
|
|
|
ASSERT_EQ(data_in.r_u8, data_out.r_u8) << "value range: " << TestStruct::r_u8_r;
|
|
ASSERT_EQ(data_in.r_i8, data_out.r_i8) << "value range: " << TestStruct::r_i8_r;
|
|
ASSERT_EQ(data_in.r_u16, data_out.r_u16) << "value range: " << TestStruct::r_u16_r;
|
|
ASSERT_EQ(data_in.r_i16, data_out.r_i16) << "value range: " << TestStruct::r_i16_r;
|
|
ASSERT_EQ(data_in.r_u32, data_out.r_u32) << "value range: " << TestStruct::r_u32_r;
|
|
ASSERT_EQ(data_in.r_i32, data_out.r_i32) << "value range: " << TestStruct::r_i32_r;
|
|
|
|
// bit perfect copies, can have wrong results for special values <.<
|
|
ASSERT_EQ(data_in.f32, data_out.f32);
|
|
ASSERT_EQ(data_in.f64, data_out.f64);
|
|
|
|
ASSERT_NEAR(data_in.c0_f32_0, data_out.c0_f32_0, TestStruct::c0_f32_resolution);
|
|
ASSERT_NEAR(data_in.c0_f32_1, data_out.c0_f32_1, TestStruct::c0_f32_resolution);
|
|
ASSERT_NEAR(data_in.c0_f32_2, data_out.c0_f32_2, TestStruct::c0_f32_resolution);
|
|
ASSERT_NEAR(data_in.c0_f32_3, data_out.c0_f32_3, TestStruct::c0_f32_resolution);
|
|
|
|
ASSERT_NEAR(data_in.c1_f32_0, data_out.c1_f32_0, TestStruct::c1_f32_resolution);
|
|
ASSERT_NEAR(data_in.c1_f32_1, data_out.c1_f32_1, TestStruct::c1_f32_resolution);
|
|
ASSERT_NEAR(data_in.c1_f32_2, data_out.c1_f32_2, TestStruct::c1_f32_resolution);
|
|
ASSERT_NEAR(data_in.c1_f32_3, data_out.c1_f32_3, TestStruct::c1_f32_resolution);
|
|
|
|
ASSERT_NEAR(data_in.c2_f32_0, data_out.c2_f32_0, TestStruct::c2_f32_resolution);
|
|
ASSERT_NEAR(data_in.c2_f32_1, data_out.c2_f32_1, TestStruct::c2_f32_resolution);
|
|
ASSERT_NEAR(data_in.c2_f32_2, data_out.c2_f32_2, TestStruct::c2_f32_resolution);
|
|
ASSERT_NEAR(data_in.c2_f32_3, data_out.c2_f32_3, TestStruct::c2_f32_resolution);
|
|
}
|
|
|