1+ #pragma once
2+ #include " ../utility/meta.h"
3+
4+ #include " multi.h"
5+ #include " serialize_traits.h"
6+ #include " stream_traits.h"
7+
8+ #include < cstdint>
9+ #include < cstring>
10+ #include < type_traits>
11+
12+ namespace bitstream
13+ {
14+ /* *
15+ * @brief A noop stream
16+ */
17+ class bit_noop
18+ {
19+ public:
20+ static constexpr bool writing = true ;
21+ static constexpr bool reading = false ;
22+
23+ /* *
24+ * @brief Returns the buffer that this reader is currently serializing from
25+ * @return The buffer
26+ */
27+ [[nodiscard]] const uint8_t * get_buffer () const noexcept { return nullptr ; }
28+
29+ /* *
30+ * @brief Returns the number of bits which have been read from the buffer
31+ * @return The number of bits which have been read
32+ */
33+ [[nodiscard]] uint32_t get_num_bits_serialized () const noexcept { return 0 ; }
34+
35+ /* *
36+ * @brief Returns the number of bytes which have been read from the buffer
37+ * @return The number of bytes which have been read
38+ */
39+ [[nodiscard]] uint32_t get_num_bytes_serialized () const noexcept { return 0 ; }
40+
41+ /* *
42+ * @brief Returns whether the @p num_bits be read from the buffer
43+ * @param num_bits The number of bits to test
44+ * @return Whether the number of bits can be read from the buffer
45+ */
46+ [[nodiscard]] bool can_serialize_bits (uint32_t num_bits) const noexcept { return false ; }
47+
48+ /* *
49+ * @brief Returns the number of bits which have not been read yet
50+ * @note The same as get_total_bits() - get_num_bits_serialized()
51+ * @return The remaining space in the buffer
52+ */
53+ [[nodiscard]] uint32_t get_remaining_bits () const noexcept { return 0 ; }
54+
55+ /* *
56+ * @brief Returns the size of the buffer, in bits
57+ * @return The size of the buffer, in bits
58+ */
59+ [[nodiscard]] uint32_t get_total_bits () const noexcept { return 0 ; }
60+
61+ /* *
62+ * @brief Pads the buffer up to the given number of bytes
63+ * @param num_bytes The byte number to pad to
64+ * @return Returns false if the current size of the buffer is bigger than @p num_bytes or if the padded bits are not zeros.
65+ */
66+ [[nodiscard]] bool pad_to_size (uint32_t num_bytes) noexcept { return false ; }
67+
68+ /* *
69+ * @brief Pads the buffer up with the given number of bytes
70+ * @param num_bytes The amount of bytes to pad
71+ * @return Returns false if the current size of the buffer is bigger than @p num_bytes or if the padded bits are not zeros.
72+ */
73+ [[nodiscard]] bool pad (uint32_t num_bytes) noexcept { return false ; }
74+
75+ /* *
76+ * @brief Pads the buffer with up to 8 zeros, so that the next read is byte-aligned
77+ * @notes Return false if the padded bits are not zeros
78+ * @return Returns false if the padded bits are not zeros
79+ */
80+ [[nodiscard]] bool align () noexcept { return false ; }
81+
82+ /* *
83+ * @brief Reads the first @p num_bits bits of @p value from the buffer
84+ * @param value The value to serialize
85+ * @param num_bits The number of bits of the @p value to serialize
86+ * @return Returns false if @p num_bits is less than 1 or greater than 32 or if reading the given number of bits would overflow the buffer
87+ */
88+ [[nodiscard]] bool serialize_bits (uint32_t & value, uint32_t num_bits) noexcept { return false ; }
89+
90+ /* *
91+ * @brief Reads the first @p num_bits bits of the given byte array, 32 bits at a time
92+ * @param bytes The bytes to serialize
93+ * @param num_bits The number of bits of the @p bytes to serialize
94+ * @return Returns false if @p num_bits is less than 1 or if reading the given number of bits would overflow the buffer
95+ */
96+ [[nodiscard]] bool serialize_bytes (uint8_t * bytes, uint32_t num_bits) noexcept { return false ; }
97+
98+ /* *
99+ * @brief Reads from the buffer into mulitple variables.
100+ * @note Pass multi<T>(...) to this in place of multiple calls to the regular serialize functions.
101+ * @tparam ...Args The types of the arguments to pass to the serialize function
102+ * @param ...args The arguments to pass to the serialize function
103+ * @return Whether successful or not
104+ */
105+ template <typename ... Args, typename = std::enable_if_t <(utility::has_instance_serialize_v<Args, bit_noop> && ...)>>
106+ [[nodiscard]] bool serialize (Args&&... args)
107+ noexcept ((noexcept (std::declval<Args&>().serialize(std::declval<bit_noop&>())) && ...))
108+ {
109+ return (std::forward<Args>(args).serialize (*this ) && ...);
110+ }
111+
112+ /* *
113+ * @brief Reads from the buffer, using the given @p Trait.
114+ * @note The Trait type in this function must always be explicitly declared
115+ * @tparam Trait A template specialization of serialize_trait<>
116+ * @tparam ...Args The types of the arguments to pass to the serialize function
117+ * @param ...args The arguments to pass to the serialize function
118+ * @return Whether successful or not
119+ */
120+ template <typename Trait, typename ... Args, typename = utility::has_serialize_t <Trait, bit_noop, Args...>>
121+ [[nodiscard]] bool serialize (Args&&... args) noexcept (utility::is_serialize_noexcept_v<Trait, bit_noop, Args...>)
122+ {
123+ return serialize_traits<Trait>::serialize (*this , std::forward<Args>(args)...);
124+ }
125+
126+ /* *
127+ * @brief Reads from the buffer, by trying to deduce the trait.
128+ * @note The Trait type in this function is always implicit and will be deduced from the first argument if possible.
129+ * If the trait cannot be deduced it will not compile.
130+ * @tparam Trait The type of the first argument, which will be used to deduce the trait specialization
131+ * @tparam ...Args The types of the arguments to pass to the serialize function
132+ * @param arg The first argument to pass to the serialize function
133+ * @param ...args The rest of the arguments to pass to the serialize function
134+ * @return Whether successful or not
135+ */
136+ template <typename ... Args, typename Trait, typename = utility::has_deduce_serialize_t <Trait, bit_noop, Args...>>
137+ [[nodiscard]] bool serialize (Trait&& arg, Args&&... args) noexcept (utility::is_deduce_serialize_noexcept_v<Trait, bit_noop, Args...>)
138+ {
139+ return serialize_traits<utility::deduce_trait_t <Trait, bit_noop, Args...>>::serialize (*this , std::forward<Trait>(arg), std::forward<Args>(args)...);
140+ }
141+ };
142+ }
0 commit comments