Skip to content

Commit 2c637cc

Browse files
committed
Add multi serialize function
1 parent ff32b32 commit 2c637cc

4 files changed

Lines changed: 101 additions & 5 deletions

File tree

include/bitstream/stream/bit_reader.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
#pragma once
22
#include "../utility/assert.h"
3-
#include "../utility/crc.h"
43
#include "../utility/endian.h"
54
#include "../utility/meta.h"
65

76
#include "byte_buffer.h"
7+
#include "multi.h"
88
#include "serialize_traits.h"
99
#include "stream_traits.h"
1010

1111
#include <cstdint>
12-
#include <cstring>
13-
#include <string>
1412
#include <type_traits>
1513

1614
namespace bitstream
@@ -272,6 +270,13 @@ namespace bitstream
272270
return true;
273271
}
274272

273+
template<typename... Args, typename = std::enable_if_t<(utility::has_instance_serialize_v<Args, bit_reader> && ...)>>
274+
[[nodiscard]] bool serialize(Args&&... args)
275+
noexcept((noexcept(std::declval<Args&>().serialize(std::declval<bit_reader&>())) && ...))
276+
{
277+
return (std::forward<Args>(args).serialize(*this) && ...);
278+
}
279+
275280
/**
276281
* @brief Reads from the buffer, using the given @p Trait.
277282
* @note The Trait type in this function must always be explicitly declared

include/bitstream/stream/bit_writer.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
#pragma once
22
#include "../utility/assert.h"
3-
#include "../utility/crc.h"
43
#include "../utility/endian.h"
54
#include "../utility/meta.h"
65

76
#include "byte_buffer.h"
7+
#include "multi.h"
88
#include "serialize_traits.h"
99
#include "stream_traits.h"
1010

1111
#include <cstdint>
12-
#include <cstring>
1312
#include <memory>
1413
#include <type_traits>
1514

@@ -316,6 +315,13 @@ namespace bitstream
316315
return true;
317316
}
318317

318+
template<typename... Args, typename = std::enable_if_t<(utility::has_instance_serialize_v<Args, bit_writer> && ...)>>
319+
[[nodiscard]] bool serialize(Args&&... args)
320+
noexcept((noexcept(std::declval<Args&>().serialize(std::declval<bit_writer&>())) && ...))
321+
{
322+
return (std::forward<Args>(args).serialize(*this) && ...);
323+
}
324+
319325
/**
320326
* @brief Writes to the buffer, using the given @p Trait.
321327
* @note The Trait type in this function must always be explicitly declared

include/bitstream/stream/multi.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
#include "../utility/meta.h"
3+
#include "../utility/parameter.h"
4+
5+
#include "serialize_traits.h"
6+
7+
#include <tuple>
8+
9+
namespace bitstream
10+
{
11+
namespace utility
12+
{
13+
// Check if type has a serializable trait
14+
template<typename T, typename Stream, typename Void = void>
15+
struct has_instance_serialize : std::false_type {};
16+
17+
template<typename T, typename Stream>
18+
struct has_instance_serialize<T, Stream, std::void_t<decltype(std::declval<T&>().serialize(std::declval<Stream&>()))>> : std::true_type {};
19+
20+
template<typename T, typename Stream>
21+
constexpr bool has_instance_serialize_v = has_instance_serialize<T, Stream>::value;
22+
}
23+
24+
25+
template<typename T, typename... Ts>
26+
struct multi_tuple
27+
{
28+
std::tuple<Ts...> Args;
29+
30+
template<typename Stream, typename = utility::has_serialize_t<T, Stream, Ts...>>
31+
bool serialize(Stream& stream) noexcept(utility::is_serialize_noexcept_v<T, Stream, Ts...>)
32+
{
33+
return std::apply([&](auto&&... args) { return serialize_traits<T>::serialize(stream, args ...); }, std::move(Args));
34+
}
35+
};
36+
37+
template<typename T, typename... Args>
38+
multi_tuple<T, Args&&...> multi(Args&&... args) noexcept
39+
{
40+
return multi_tuple<T, Args&&...>{ std::forward_as_tuple(std::forward<Args>(args) ...) };
41+
}
42+
}

src/test/serialize_multi_test.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "../shared/assert.h"
2+
#include "../shared/test.h"
3+
4+
#include <bitstream/stream/bit_reader.h>
5+
#include <bitstream/stream/bit_writer.h>
6+
7+
#include <bitstream/traits/integral_traits.h>
8+
9+
namespace bitstream::test::multi_serialize
10+
{
11+
BS_ADD_TEST(test_serialize_multi)
12+
{
13+
// Test serializing multiple values at once
14+
uint32_t in_value1 = 511;
15+
uint32_t in_value2 = 99;
16+
17+
// Write some values
18+
byte_buffer<16> buffer;
19+
fixed_bit_writer writer(buffer);
20+
21+
BS_TEST_ASSERT(writer.serialize(
22+
multi<uint32_t>(in_value1, 328, 611),
23+
multi<uint32_t>(in_value2, 11, 111)
24+
));
25+
26+
uint32_t num_bits = writer.flush();
27+
28+
BS_TEST_ASSERT(num_bits == 16);
29+
30+
// Read the values back and validate
31+
uint32_t out_value1;
32+
uint32_t out_value2;
33+
fixed_bit_reader reader(buffer, num_bits);
34+
35+
BS_TEST_ASSERT(reader.serialize(
36+
multi<uint32_t>(out_value1, 328U, 611U),
37+
multi<uint32_t>(out_value2, 11U, 111U)
38+
));
39+
40+
BS_TEST_ASSERT(out_value1 == in_value1);
41+
BS_TEST_ASSERT(out_value2 == in_value2);
42+
}
43+
}

0 commit comments

Comments
 (0)