LibQuicR
bytes.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) 2026 Cisco Systems
2 // SPDX-License-Identifier: BSD-2-Clause
3 
4 #pragma once
5 
6 #include <bit>
7 #include <cstdint>
8 #include <span>
9 #include <string>
10 #include <type_traits>
11 #include <vector>
12 
13 namespace quicr {
15  using Byte = uint8_t;
16 
18  using Bytes = std::vector<Byte>;
19 
21  using BytesSpan = std::span<const Byte>;
22 
32  template<class T>
33  requires std::is_standard_layout_v<T> || std::is_same_v<std::decay_t<T>, std::string>
34  inline std::span<const uint8_t> AsBytes(const T& value)
35  {
36  return std::span{ reinterpret_cast<const std::uint8_t*>(&value), sizeof(T) };
37  }
38 
44  template<>
45  inline std::span<const uint8_t> AsBytes<std::string>(const std::string& value)
46  {
47  return std::span{ reinterpret_cast<const std::uint8_t*>(value.data()), value.size() };
48  }
49 
58  template<class T>
59  requires std::is_standard_layout_v<T> || std::is_same_v<std::decay_t<T>, std::string>
60  inline Bytes AsOwnedBytes(const T& value)
61  {
62  auto bytes = AsBytes<T>(value);
63  return Bytes{ bytes.begin(), bytes.end() };
64  }
65 
77  template<class T>
78  T FromBytes(std::span<const uint8_t> bytes)
79  {
80  if (bytes.empty()) {
81  return {};
82  }
83 
84  if constexpr (std::is_same_v<std::string, std::decay_t<T>>) {
85  return std::string(bytes.begin(), bytes.end());
86  }
87 
88  T value{};
89  std::copy(bytes.begin(), bytes.end(), reinterpret_cast<std::uint8_t*>(&value));
90  return value;
91  }
92 
99  inline void AppendBytes(Bytes& buffer, BytesSpan bytes)
100  {
101  buffer.reserve(buffer.size() + bytes.size());
102  buffer.insert(buffer.end(), bytes.begin(), bytes.end());
103  }
104 
106  constexpr std::uint16_t SwapBytes(const std::uint16_t value)
107  {
108  if constexpr (std::endian::native == std::endian::big) {
109  return value;
110  }
111 
112  return ((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00);
113  }
114 
116  constexpr std::uint32_t SwapBytes(const std::uint32_t value)
117  {
118  if constexpr (std::endian::native == std::endian::big) {
119  return value;
120  }
121 
122  return ((value >> 24) & 0x000000FF) | ((value >> 8) & 0x0000FF00) | ((value << 8) & 0x00FF0000) |
123  ((value << 24) & 0xFF000000);
124  }
125 
127  constexpr std::uint64_t SwapBytes(const std::uint64_t value)
128  {
129  if constexpr (std::endian::native == std::endian::big) {
130  return value;
131  }
132 
133  return ((value >> 56) & 0x00000000000000FF) | ((value >> 40) & 0x000000000000FF00) |
134  ((value >> 24) & 0x0000000000FF0000) | ((value >> 8) & 0x00000000FF000000) |
135  ((value << 8) & 0x000000FF00000000) | ((value << 24) & 0x0000FF0000000000) |
136  ((value << 40) & 0x00FF000000000000) | ((value << 56) & 0xFF00000000000000);
137  }
138 }
Definition: attributes.h:13
T FromBytes(std::span< const uint8_t > bytes)
Constructs a value from bytes.
Definition: bytes.h:78
uint8_t Byte
One octet of binary data.
Definition: bytes.h:15
std::vector< Byte > Bytes
Owning contiguous byte buffer.
Definition: bytes.h:18
std::span< const Byte > BytesSpan
Non-owning, read-only view of contiguous bytes.
Definition: bytes.h:21
requires std::is_standard_layout_v< T > std::is_same_v< std::decay_t< T >, std::string > std::span< const uint8_t > AsBytes(const T &value)
Views a value's in-memory object representation as bytes.
Definition: bytes.h:34
requires std::is_standard_layout_v< T > std::is_same_v< std::decay_t< T >, std::string > Bytes AsOwnedBytes(const T &value)
Copies a value's native object representation into an owning byte buffer.
Definition: bytes.h:60
void AppendBytes(Bytes &buffer, BytesSpan bytes)
Appends bytes to an owning buffer.
Definition: bytes.h:99
constexpr std::uint16_t SwapBytes(const std::uint16_t value)
Converts a 16-bit value between native and big-endian byte order.
Definition: bytes.h:106