2828#include < tcb/span.hpp>
2929#include " exceptions.h"
3030
31+ inline constexpr size_t kSizePrefixBytes = sizeof (uint32_t );
32+
3133// Utility functions for little-endian number reading and writing.
3234
3335inline void append_u32_le (std::vector<uint8_t >& out, uint32_t v) {
@@ -88,12 +90,12 @@ inline uint32_t read_u32_le(tcb::span<const uint8_t> in, size_t offset) {
8890
8991// Utility functions for splitting and joining byte vectors.
9092
91- struct SplitBytesPair {
93+ struct BytesPair {
9294 std::vector<uint8_t > leading;
9395 std::vector<uint8_t > trailing;
9496};
9597
96- struct SplitSpansPair {
98+ struct SpansPair {
9799 tcb::span<const uint8_t > leading;
98100 tcb::span<const uint8_t > trailing;
99101};
@@ -119,11 +121,11 @@ inline std::vector<uint8_t> Join(const std::vector<uint8_t>& leading, const std:
119121 *
120122 * @param bytes The bytes to split
121123 * @param index The index at which to split (bytes before index go to leading, bytes from index go to trailing)
122- * @return SplitBytesPair structure with split bytes
124+ * @return BytesPair structure with split bytes
123125 * @throws InvalidInputException if index is invalid
124126 */
125- inline SplitBytesPair Split (const std::vector<uint8_t >& bytes, int index) {
126- SplitBytesPair result;
127+ inline BytesPair Split (const std::vector<uint8_t >& bytes, int index) {
128+ BytesPair result;
127129
128130 if (index < 0 || index > static_cast <int >(bytes.size ())) {
129131 throw InvalidInputException (" Invalid index for splitting bytes: " + std::to_string (index));
@@ -139,15 +141,15 @@ inline SplitBytesPair Split(const std::vector<uint8_t>& bytes, int index) {
139141 *
140142 * @param bytes The span to split
141143 * @param index The index at which to split (bytes before index go to leading, bytes from index go to trailing)
142- * @return SplitSpansPair structure with split spans
144+ * @return SpansPair structure with split spans
143145 * @throws InvalidInputException if index is invalid
144146 */
145- inline SplitSpansPair Split (tcb::span<const uint8_t > bytes, int index) {
147+ inline SpansPair Split (tcb::span<const uint8_t > bytes, int index) {
146148 if (index < 0 || index > static_cast <int >(bytes.size ())) {
147149 throw InvalidInputException (" Invalid index for splitting bytes: " + std::to_string (index));
148150 }
149151 const size_t split_index = static_cast <size_t >(index);
150- return SplitSpansPair {
152+ return SpansPair {
151153 tcb::span<const uint8_t >(bytes.data (), split_index),
152154 tcb::span<const uint8_t >(bytes.data () + split_index, bytes.size () - split_index)};
153155}
@@ -170,7 +172,7 @@ inline std::vector<uint8_t> JoinWithLengthPrefix(const std::vector<uint8_t>& lea
170172 // Calculate the length of the leading bytes
171173 uint32_t leading_length = static_cast <uint32_t >(leading.size ());
172174 std::vector<uint8_t > result;
173- result.reserve (4 + leading.size () + trailing.size ());
175+ result.reserve (kSizePrefixBytes + leading.size () + trailing.size ());
174176
175177 // Prepend 4-byte length
176178 append_u32_le (result, leading_length);
@@ -183,60 +185,44 @@ inline std::vector<uint8_t> JoinWithLengthPrefix(const std::vector<uint8_t>& lea
183185}
184186
185187/* *
186- * Parse a self-contained byte vector that was created with JoinWithLengthPrefix.
187- * Extracts the leading and trailing parts based on the embedded length prefix.
188- *
188+ * Parse a self-contained byte span that was created with JoinWithLengthPrefix.
189+ * Extracts leading and trailing span views based on the embedded length prefix.
190+ *
189191 * @param bytes The combined bytes with length prefix
190- * @return SplitBytesPair structure with leading and trailing bytes
192+ * @return SpansPair structure with leading and trailing span views
191193 * @throws InvalidInputException if the data is invalid or malformed
192194 */
193- inline SplitBytesPair SplitWithLengthPrefix (const std::vector< uint8_t >& bytes) {
194- if (bytes.size () < 4 ) {
195+ inline SpansPair SplitWithLengthPrefix (tcb::span< const uint8_t > bytes) {
196+ if (bytes.size () < kSizePrefixBytes ) {
195197 throw InvalidInputException (" Invalid length-prefixed data: insufficient bytes for length prefix" );
196198 }
197-
198- // Read 4-byte length
199+
199200 uint32_t leading_length = read_u32_le (bytes, 0 );
200-
201- if (bytes.size () < 4 + leading_length) {
201+
202+ if (bytes.size () < kSizePrefixBytes + leading_length) {
202203 throw InvalidInputException (" Invalid length-prefixed data: insufficient bytes for leading data (expected " +
203- std::to_string (4 + leading_length) + " , got " + std::to_string (bytes.size ()) + " )" );
204+ std::to_string (kSizePrefixBytes + leading_length) + " , got " + std::to_string (bytes.size ()) + " )" );
204205 }
205-
206- SplitBytesPair result;
207-
208- // Extract leading bytes (skip the 4-byte length prefix)
209- result.leading = std::vector<uint8_t >(bytes.begin () + 4 , bytes.begin () + 4 + leading_length);
210206
211- // Extract trailing bytes (everything after leading)
212- result. trailing = std::vector< uint8_t >( bytes.begin () + 4 + leading_length, bytes. end ());
213-
214- return result ;
207+ auto payload = tcb::span< const uint8_t >(
208+ bytes.data () + kSizePrefixBytes ,
209+ bytes. size () - kSizePrefixBytes );
210+ return Split (payload, static_cast < int >(leading_length)) ;
215211}
216212
217213/* *
218- * Parse a self-contained byte span that was created with JoinWithLengthPrefix.
219- * Extracts leading and trailing span views based on the embedded length prefix.
220- *
214+ * Parse a self-contained byte vector that was created with JoinWithLengthPrefix.
215+ * Extracts the leading and trailing parts based on the embedded length prefix.
216+ *
221217 * @param bytes The combined bytes with length prefix
222- * @return SplitSpansPair structure with leading and trailing span views
218+ * @return BytesPair structure with leading and trailing bytes
223219 * @throws InvalidInputException if the data is invalid or malformed
224220 */
225- inline SplitSpansPair SplitWithLengthPrefix (tcb::span<const uint8_t > bytes) {
226- if (bytes.size () < 4 ) {
227- throw InvalidInputException (" Invalid length-prefixed data: insufficient bytes for length prefix" );
228- }
229-
230- uint32_t leading_length = read_u32_le (bytes, 0 );
231-
232- if (bytes.size () < 4 + leading_length) {
233- throw InvalidInputException (" Invalid length-prefixed data: insufficient bytes for leading data (expected " +
234- std::to_string (4 + leading_length) + " , got " + std::to_string (bytes.size ()) + " )" );
235- }
236-
237- return SplitSpansPair{
238- tcb::span<const uint8_t >(bytes.data () + 4 , leading_length),
239- tcb::span<const uint8_t >(bytes.data () + 4 + leading_length, bytes.size () - 4 - leading_length)};
221+ inline BytesPair SplitWithLengthPrefix (const std::vector<uint8_t >& bytes) {
222+ const auto spans = SplitWithLengthPrefix (tcb::span<const uint8_t >(bytes));
223+ return BytesPair{
224+ std::vector<uint8_t >(spans.leading .begin (), spans.leading .end ()),
225+ std::vector<uint8_t >(spans.trailing .begin (), spans.trailing .end ())};
240226}
241227
242228// Utility functions for creating an AttributesMap
0 commit comments