1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_NUMERICS_BYTE_CONVERSIONS_H_
6 #define BASE_NUMERICS_BYTE_CONVERSIONS_H_
7
8 #include <array>
9 #include <bit>
10 #include <cstdint>
11 #include <cstring>
12 #include <span>
13 #include <type_traits>
14
15 #include "base/numerics/basic_ops_impl.h"
16 #include "build/build_config.h"
17
18 // Chromium only builds and runs on Little Endian machines.
19 static_assert(ARCH_CPU_LITTLE_ENDIAN);
20
21 namespace base {
22
23 // Returns a value with all bytes in |x| swapped, i.e. reverses the endianness.
24 // TODO(pkasting): Once C++23 is available, replace with std::byteswap.
25 template <class T>
requires(std::is_integral_v<T>)26 requires(std::is_integral_v<T>)
27 inline constexpr T ByteSwap(T value) {
28 return internal::SwapBytes(value);
29 }
30
31 // Returns a uint8_t with the value in `bytes` interpreted as the native endian
32 // encoding of the integer for the machine.
33 //
34 // This is suitable for decoding integers that were always kept in native
35 // encoding, such as when stored in shared-memory (or through IPC) as a byte
36 // buffer. Prefer an explicit little endian when storing and reading data from
37 // storage, and explicit big endian for network order.
38 //
39 // Note that since a single byte can have only one ordering, this just copies
40 // the byte out of the span. This provides a consistent function for the
41 // operation nonetheless.
U8FromNativeEndian(std::span<const uint8_t,1u> bytes)42 inline constexpr uint8_t U8FromNativeEndian(
43 std::span<const uint8_t, 1u> bytes) {
44 return bytes[0];
45 }
46 // Returns a uint16_t with the value in `bytes` interpreted as the native endian
47 // encoding of the integer for the machine.
48 //
49 // This is suitable for decoding integers that were always kept in native
50 // encoding, such as when stored in shared-memory (or through IPC) as a byte
51 // buffer. Prefer an explicit little endian when storing and reading data from
52 // storage, and explicit big endian for network order.
U16FromNativeEndian(std::span<const uint8_t,2u> bytes)53 inline constexpr uint16_t U16FromNativeEndian(
54 std::span<const uint8_t, 2u> bytes) {
55 return internal::FromLittleEndian<uint16_t>(bytes);
56 }
57 // Returns a uint32_t with the value in `bytes` interpreted as the native endian
58 // encoding of the integer for the machine.
59 //
60 // This is suitable for decoding integers that were always kept in native
61 // encoding, such as when stored in shared-memory (or through IPC) as a byte
62 // buffer. Prefer an explicit little endian when storing and reading data from
63 // storage, and explicit big endian for network order.
U32FromNativeEndian(std::span<const uint8_t,4u> bytes)64 inline constexpr uint32_t U32FromNativeEndian(
65 std::span<const uint8_t, 4u> bytes) {
66 return internal::FromLittleEndian<uint32_t>(bytes);
67 }
68 // Returns a uint64_t with the value in `bytes` interpreted as the native endian
69 // encoding of the integer for the machine.
70 //
71 // This is suitable for decoding integers that were always kept in native
72 // encoding, such as when stored in shared-memory (or through IPC) as a byte
73 // buffer. Prefer an explicit little endian when storing and reading data from
74 // storage, and explicit big endian for network order.
U64FromNativeEndian(std::span<const uint8_t,8u> bytes)75 inline constexpr uint64_t U64FromNativeEndian(
76 std::span<const uint8_t, 8u> bytes) {
77 return internal::FromLittleEndian<uint64_t>(bytes);
78 }
79 // Returns a int8_t with the value in `bytes` interpreted as the native endian
80 // encoding of the integer for the machine.
81 //
82 // This is suitable for decoding integers that were always kept in native
83 // encoding, such as when stored in shared-memory (or through IPC) as a byte
84 // buffer. Prefer an explicit little endian when storing and reading data from
85 // storage, and explicit big endian for network order.
86 //
87 // Note that since a single byte can have only one ordering, this just copies
88 // the byte out of the span. This provides a consistent function for the
89 // operation nonetheless.
I8FromNativeEndian(std::span<const uint8_t,1u> bytes)90 inline constexpr int8_t I8FromNativeEndian(std::span<const uint8_t, 1u> bytes) {
91 return static_cast<int8_t>(bytes[0]);
92 }
93 // Returns a int16_t with the value in `bytes` interpreted as the native endian
94 // encoding of the integer for the machine.
95 //
96 // This is suitable for decoding integers that were always kept in native
97 // encoding, such as when stored in shared-memory (or through IPC) as a byte
98 // buffer. Prefer an explicit little endian when storing and reading data from
99 // storage, and explicit big endian for network order.
I16FromNativeEndian(std::span<const uint8_t,2u> bytes)100 inline constexpr int16_t I16FromNativeEndian(
101 std::span<const uint8_t, 2u> bytes) {
102 return internal::FromLittleEndian<int16_t>(bytes);
103 }
104 // Returns a int32_t with the value in `bytes` interpreted as the native endian
105 // encoding of the integer for the machine.
106 //
107 // This is suitable for decoding integers that were always kept in native
108 // encoding, such as when stored in shared-memory (or through IPC) as a byte
109 // buffer. Prefer an explicit little endian when storing and reading data from
110 // storage, and explicit big endian for network order.
I32FromNativeEndian(std::span<const uint8_t,4u> bytes)111 inline constexpr int32_t I32FromNativeEndian(
112 std::span<const uint8_t, 4u> bytes) {
113 return internal::FromLittleEndian<int32_t>(bytes);
114 }
115 // Returns a int64_t with the value in `bytes` interpreted as the native endian
116 // encoding of the integer for the machine.
117 //
118 // This is suitable for decoding integers that were always kept in native
119 // encoding, such as when stored in shared-memory (or through IPC) as a byte
120 // buffer. Prefer an explicit little endian when storing and reading data from
121 // storage, and explicit big endian for network order.
I64FromNativeEndian(std::span<const uint8_t,8u> bytes)122 inline constexpr int64_t I64FromNativeEndian(
123 std::span<const uint8_t, 8u> bytes) {
124 return internal::FromLittleEndian<int64_t>(bytes);
125 }
126
127 // Returns a float with the value in `bytes` interpreted as the native endian
128 // encoding of the number for the machine.
129 //
130 // This is suitable for decoding numbers that were always kept in native
131 // encoding, such as when stored in shared-memory (or through IPC) as a byte
132 // buffer. Prefer an explicit little endian when storing and reading data from
133 // storage, and explicit big endian for network order.
FloatFromNativeEndian(std::span<const uint8_t,4u> bytes)134 inline constexpr float FloatFromNativeEndian(
135 std::span<const uint8_t, 4u> bytes) {
136 return std::bit_cast<float>(U32FromNativeEndian(bytes));
137 }
138 // Returns a double with the value in `bytes` interpreted as the native endian
139 // encoding of the number for the machine.
140 //
141 // This is suitable for decoding numbers that were always kept in native
142 // encoding, such as when stored in shared-memory (or through IPC) as a byte
143 // buffer. Prefer an explicit little endian when storing and reading data from
144 // storage, and explicit big endian for network order.
DoubleFromNativeEndian(std::span<const uint8_t,8u> bytes)145 inline constexpr double DoubleFromNativeEndian(
146 std::span<const uint8_t, 8u> bytes) {
147 return std::bit_cast<double>(U64FromNativeEndian(bytes));
148 }
149
150 // Returns a uint8_t with the value in `bytes` interpreted as a little-endian
151 // encoding of the integer.
152 //
153 // This is suitable for decoding integers encoded explicitly in little endian,
154 // which is a good practice with storing and reading data from storage. Use
155 // the native-endian versions when working with values that were always in
156 // memory, such as when stored in shared-memory (or through IPC) as a byte
157 // buffer.
158 //
159 // Note that since a single byte can have only one ordering, this just copies
160 // the byte out of the span. This provides a consistent function for the
161 // operation nonetheless.
U8FromLittleEndian(std::span<const uint8_t,1u> bytes)162 inline constexpr uint8_t U8FromLittleEndian(
163 std::span<const uint8_t, 1u> bytes) {
164 return bytes[0];
165 }
166 // Returns a uint16_t with the value in `bytes` interpreted as a little-endian
167 // encoding of the integer.
168 //
169 // This is suitable for decoding integers encoded explicitly in little endian,
170 // which is a good practice with storing and reading data from storage. Use
171 // the native-endian versions when working with values that were always in
172 // memory, such as when stored in shared-memory (or through IPC) as a byte
173 // buffer.
U16FromLittleEndian(std::span<const uint8_t,2u> bytes)174 inline constexpr uint16_t U16FromLittleEndian(
175 std::span<const uint8_t, 2u> bytes) {
176 return internal::FromLittleEndian<uint16_t>(bytes);
177 }
178 // Returns a uint32_t with the value in `bytes` interpreted as a little-endian
179 // encoding of the integer.
180 //
181 // This is suitable for decoding integers encoded explicitly in little endian,
182 // which is a good practice with storing and reading data from storage. Use
183 // the native-endian versions when working with values that were always in
184 // memory, such as when stored in shared-memory (or through IPC) as a byte
185 // buffer.
U32FromLittleEndian(std::span<const uint8_t,4u> bytes)186 inline constexpr uint32_t U32FromLittleEndian(
187 std::span<const uint8_t, 4u> bytes) {
188 return internal::FromLittleEndian<uint32_t>(bytes);
189 }
190 // Returns a uint64_t with the value in `bytes` interpreted as a little-endian
191 // encoding of the integer.
192 //
193 // This is suitable for decoding integers encoded explicitly in little endian,
194 // which is a good practice with storing and reading data from storage. Use
195 // the native-endian versions when working with values that were always in
196 // memory, such as when stored in shared-memory (or through IPC) as a byte
197 // buffer.
U64FromLittleEndian(std::span<const uint8_t,8u> bytes)198 inline constexpr uint64_t U64FromLittleEndian(
199 std::span<const uint8_t, 8u> bytes) {
200 return internal::FromLittleEndian<uint64_t>(bytes);
201 }
202 // Returns a int8_t with the value in `bytes` interpreted as a little-endian
203 // encoding of the integer.
204 //
205 // This is suitable for decoding integers encoded explicitly in little endian,
206 // which is a good practice with storing and reading data from storage. Use
207 // the native-endian versions when working with values that were always in
208 // memory, such as when stored in shared-memory (or through IPC) as a byte
209 // buffer.
210 //
211 // Note that since a single byte can have only one ordering, this just copies
212 // the byte out of the span. This provides a consistent function for the
213 // operation nonetheless.
I8FromLittleEndian(std::span<const uint8_t,1u> bytes)214 inline constexpr int8_t I8FromLittleEndian(std::span<const uint8_t, 1u> bytes) {
215 return static_cast<int8_t>(bytes[0]);
216 }
217 // Returns a int16_t with the value in `bytes` interpreted as a little-endian
218 // encoding of the integer.
219 //
220 // This is suitable for decoding integers encoded explicitly in little endian,
221 // which is a good practice with storing and reading data from storage. Use
222 // the native-endian versions when working with values that were always in
223 // memory, such as when stored in shared-memory (or through IPC) as a byte
224 // buffer.
I16FromLittleEndian(std::span<const uint8_t,2u> bytes)225 inline constexpr int16_t I16FromLittleEndian(
226 std::span<const uint8_t, 2u> bytes) {
227 return internal::FromLittleEndian<int16_t>(bytes);
228 }
229 // Returns a int32_t with the value in `bytes` interpreted as a little-endian
230 // encoding of the integer.
231 //
232 // This is suitable for decoding integers encoded explicitly in little endian,
233 // which is a good practice with storing and reading data from storage. Use
234 // the native-endian versions when working with values that were always in
235 // memory, such as when stored in shared-memory (or through IPC) as a byte
236 // buffer.
I32FromLittleEndian(std::span<const uint8_t,4u> bytes)237 inline constexpr int32_t I32FromLittleEndian(
238 std::span<const uint8_t, 4u> bytes) {
239 return internal::FromLittleEndian<int32_t>(bytes);
240 }
241 // Returns a int64_t with the value in `bytes` interpreted as a little-endian
242 // encoding of the integer.
243 //
244 // This is suitable for decoding integers encoded explicitly in little endian,
245 // which is a good practice with storing and reading data from storage. Use
246 // the native-endian versions when working with values that were always in
247 // memory, such as when stored in shared-memory (or through IPC) as a byte
248 // buffer.
I64FromLittleEndian(std::span<const uint8_t,8u> bytes)249 inline constexpr int64_t I64FromLittleEndian(
250 std::span<const uint8_t, 8u> bytes) {
251 return internal::FromLittleEndian<int64_t>(bytes);
252 }
253 // Returns a float with the value in `bytes` interpreted as a little-endian
254 // encoding of the integer.
255 //
256 // This is suitable for decoding numbers encoded explicitly in little endian,
257 // which is a good practice with storing and reading data from storage. Use
258 // the native-endian versions when working with values that were always in
259 // memory, such as when stored in shared-memory (or through IPC) as a byte
260 // buffer.
FloatFromLittleEndian(std::span<const uint8_t,4u> bytes)261 inline constexpr float FloatFromLittleEndian(
262 std::span<const uint8_t, 4u> bytes) {
263 return std::bit_cast<float>(U32FromLittleEndian(bytes));
264 }
265 // Returns a double with the value in `bytes` interpreted as a little-endian
266 // encoding of the integer.
267 //
268 // This is suitable for decoding numbers encoded explicitly in little endian,
269 // which is a good practice with storing and reading data from storage. Use
270 // the native-endian versions when working with values that were always in
271 // memory, such as when stored in shared-memory (or through IPC) as a byte
272 // buffer.
DoubleFromLittleEndian(std::span<const uint8_t,8u> bytes)273 inline constexpr double DoubleFromLittleEndian(
274 std::span<const uint8_t, 8u> bytes) {
275 return std::bit_cast<double>(U64FromLittleEndian(bytes));
276 }
277
278 // Returns a uint8_t with the value in `bytes` interpreted as a big-endian
279 // encoding of the integer.
280 //
281 // This is suitable for decoding integers encoded explicitly in big endian, such
282 // as for network order. Use the native-endian versions when working with values
283 // that were always in memory, such as when stored in shared-memory (or through
284 // IPC) as a byte buffer.
285 //
286 // Note that since a single byte can have only one ordering, this just copies
287 // the byte out of the span. This provides a consistent function for the
288 // operation nonetheless.
U8FromBigEndian(std::span<const uint8_t,1u> bytes)289 inline constexpr uint8_t U8FromBigEndian(std::span<const uint8_t, 1u> bytes) {
290 return bytes[0];
291 }
292 // Returns a uint16_t with the value in `bytes` interpreted as a big-endian
293 // encoding of the integer.
294 //
295 // This is suitable for decoding integers encoded explicitly in big endian, such
296 // as for network order. Use the native-endian versions when working with values
297 // that were always in memory, such as when stored in shared-memory (or through
298 // IPC) as a byte buffer.
U16FromBigEndian(std::span<const uint8_t,2u> bytes)299 inline constexpr uint16_t U16FromBigEndian(std::span<const uint8_t, 2u> bytes) {
300 return ByteSwap(internal::FromLittleEndian<uint16_t>(bytes));
301 }
302 // Returns a uint32_t with the value in `bytes` interpreted as a big-endian
303 // encoding of the integer.
304 //
305 // This is suitable for decoding integers encoded explicitly in big endian, such
306 // as for network order. Use the native-endian versions when working with values
307 // that were always in memory, such as when stored in shared-memory (or through
308 // IPC) as a byte buffer.
U32FromBigEndian(std::span<const uint8_t,4u> bytes)309 inline constexpr uint32_t U32FromBigEndian(std::span<const uint8_t, 4u> bytes) {
310 return ByteSwap(internal::FromLittleEndian<uint32_t>(bytes));
311 }
312 // Returns a uint64_t with the value in `bytes` interpreted as a big-endian
313 // encoding of the integer.
314 //
315 // This is suitable for decoding integers encoded explicitly in big endian, such
316 // as for network order. Use the native-endian versions when working with values
317 // that were always in memory, such as when stored in shared-memory (or through
318 // IPC) as a byte buffer.
U64FromBigEndian(std::span<const uint8_t,8u> bytes)319 inline constexpr uint64_t U64FromBigEndian(std::span<const uint8_t, 8u> bytes) {
320 return ByteSwap(internal::FromLittleEndian<uint64_t>(bytes));
321 }
322 // Returns a int8_t with the value in `bytes` interpreted as a big-endian
323 // encoding of the integer.
324 //
325 // This is suitable for decoding integers encoded explicitly in big endian, such
326 // as for network order. Use the native-endian versions when working with values
327 // that were always in memory, such as when stored in shared-memory (or through
328 // IPC) as a byte buffer.
329 //
330 // Note that since a single byte can have only one ordering, this just copies
331 // the byte out of the span. This provides a consistent function for the
332 // operation nonetheless.
I8FromBigEndian(std::span<const uint8_t,1u> bytes)333 inline constexpr int8_t I8FromBigEndian(std::span<const uint8_t, 1u> bytes) {
334 return static_cast<int8_t>(bytes[0]);
335 }
336 // Returns a int16_t with the value in `bytes` interpreted as a big-endian
337 // encoding of the integer.
338 //
339 // This is suitable for decoding integers encoded explicitly in big endian, such
340 // as for network order. Use the native-endian versions when working with values
341 // that were always in memory, such as when stored in shared-memory (or through
342 // IPC) as a byte buffer.
I16FromBigEndian(std::span<const uint8_t,2u> bytes)343 inline constexpr int16_t I16FromBigEndian(std::span<const uint8_t, 2u> bytes) {
344 return ByteSwap(internal::FromLittleEndian<int16_t>(bytes));
345 }
346 // Returns a int32_t with the value in `bytes` interpreted as a big-endian
347 // encoding of the integer.
348 //
349 // This is suitable for decoding integers encoded explicitly in big endian, such
350 // as for network order. Use the native-endian versions when working with values
351 // that were always in memory, such as when stored in shared-memory (or through
352 // IPC) as a byte buffer.
I32FromBigEndian(std::span<const uint8_t,4u> bytes)353 inline constexpr int32_t I32FromBigEndian(std::span<const uint8_t, 4u> bytes) {
354 return ByteSwap(internal::FromLittleEndian<int32_t>(bytes));
355 }
356 // Returns a int64_t with the value in `bytes` interpreted as a big-endian
357 // encoding of the integer.
358 //
359 // This is suitable for decoding integers encoded explicitly in big endian, such
360 // as for network order. Use the native-endian versions when working with values
361 // that were always in memory, such as when stored in shared-memory (or through
362 // IPC) as a byte buffer.
I64FromBigEndian(std::span<const uint8_t,8u> bytes)363 inline constexpr int64_t I64FromBigEndian(std::span<const uint8_t, 8u> bytes) {
364 return ByteSwap(internal::FromLittleEndian<int64_t>(bytes));
365 }
366 // Returns a float with the value in `bytes` interpreted as a big-endian
367 // encoding of the integer.
368 //
369 // This is suitable for decoding numbers encoded explicitly in big endian, such
370 // as for network order. Use the native-endian versions when working with values
371 // that were always in memory, such as when stored in shared-memory (or through
372 // IPC) as a byte buffer.
FloatFromBigEndian(std::span<const uint8_t,4u> bytes)373 inline constexpr float FloatFromBigEndian(std::span<const uint8_t, 4u> bytes) {
374 return std::bit_cast<float>(U32FromBigEndian(bytes));
375 }
376 // Returns a double with the value in `bytes` interpreted as a big-endian
377 // encoding of the integer.
378 //
379 // This is suitable for decoding numbers encoded explicitly in big endian, such
380 // as for network order. Use the native-endian versions when working with values
381 // that were always in memory, such as when stored in shared-memory (or through
382 // IPC) as a byte buffer.
DoubleFromBigEndian(std::span<const uint8_t,8u> bytes)383 inline constexpr double DoubleFromBigEndian(
384 std::span<const uint8_t, 8u> bytes) {
385 return std::bit_cast<double>(U64FromBigEndian(bytes));
386 }
387
388 // Returns a byte array holding the value of a uint8_t encoded as the native
389 // endian encoding of the integer for the machine.
390 //
391 // This is suitable for encoding integers that will always be kept in native
392 // encoding, such as for storing in shared-memory (or sending through IPC) as a
393 // byte buffer. Prefer an explicit little endian when storing data into external
394 // storage, and explicit big endian for network order.
U8ToNativeEndian(uint8_t val)395 inline constexpr std::array<uint8_t, 1u> U8ToNativeEndian(uint8_t val) {
396 return {val};
397 }
398 // Returns a byte array holding the value of a uint16_t encoded as the native
399 // endian encoding of the integer for the machine.
400 //
401 // This is suitable for encoding integers that will always be kept in native
402 // encoding, such as for storing in shared-memory (or sending through IPC) as a
403 // byte buffer. Prefer an explicit little endian when storing data into external
404 // storage, and explicit big endian for network order.
U16ToNativeEndian(uint16_t val)405 inline constexpr std::array<uint8_t, 2u> U16ToNativeEndian(uint16_t val) {
406 return internal::ToLittleEndian(val);
407 }
408 // Returns a byte array holding the value of a uint32_t encoded as the native
409 // endian encoding of the integer for the machine.
410 //
411 // This is suitable for encoding integers that will always be kept in native
412 // encoding, such as for storing in shared-memory (or sending through IPC) as a
413 // byte buffer. Prefer an explicit little endian when storing data into external
414 // storage, and explicit big endian for network order.
U32ToNativeEndian(uint32_t val)415 inline constexpr std::array<uint8_t, 4u> U32ToNativeEndian(uint32_t val) {
416 return internal::ToLittleEndian(val);
417 }
418 // Returns a byte array holding the value of a uint64_t encoded as the native
419 // endian encoding of the integer for the machine.
420 //
421 // This is suitable for encoding integers that will always be kept in native
422 // encoding, such as for storing in shared-memory (or sending through IPC) as a
423 // byte buffer. Prefer an explicit little endian when storing data into external
424 // storage, and explicit big endian for network order.
U64ToNativeEndian(uint64_t val)425 inline constexpr std::array<uint8_t, 8u> U64ToNativeEndian(uint64_t val) {
426 return internal::ToLittleEndian(val);
427 }
428 // Returns a byte array holding the value of a int8_t encoded as the native
429 // endian encoding of the integer for the machine.
430 //
431 // This is suitable for encoding integers that will always be kept in native
432 // encoding, such as for storing in shared-memory (or sending through IPC) as a
433 // byte buffer. Prefer an explicit little endian when storing data into external
434 // storage, and explicit big endian for network order.
I8ToNativeEndian(int8_t val)435 inline constexpr std::array<uint8_t, 1u> I8ToNativeEndian(int8_t val) {
436 return {static_cast<uint8_t>(val)};
437 }
438 // Returns a byte array holding the value of a int16_t encoded as the native
439 // endian encoding of the integer for the machine.
440 //
441 // This is suitable for encoding integers that will always be kept in native
442 // encoding, such as for storing in shared-memory (or sending through IPC) as a
443 // byte buffer. Prefer an explicit little endian when storing data into external
444 // storage, and explicit big endian for network order.
I16ToNativeEndian(int16_t val)445 inline constexpr std::array<uint8_t, 2u> I16ToNativeEndian(int16_t val) {
446 return internal::ToLittleEndian(val);
447 }
448 // Returns a byte array holding the value of a int32_t encoded as the native
449 // endian encoding of the integer for the machine.
450 //
451 // This is suitable for encoding integers that will always be kept in native
452 // encoding, such as for storing in shared-memory (or sending through IPC) as a
453 // byte buffer. Prefer an explicit little endian when storing data into external
454 // storage, and explicit big endian for network order.
I32ToNativeEndian(int32_t val)455 inline constexpr std::array<uint8_t, 4u> I32ToNativeEndian(int32_t val) {
456 return internal::ToLittleEndian(val);
457 }
458 // Returns a byte array holding the value of a int64_t encoded as the native
459 // endian encoding of the integer for the machine.
460 //
461 // This is suitable for encoding integers that will always be kept in native
462 // encoding, such as for storing in shared-memory (or sending through IPC) as a
463 // byte buffer. Prefer an explicit little endian when storing data into external
464 // storage, and explicit big endian for network order.
I64ToNativeEndian(int64_t val)465 inline constexpr std::array<uint8_t, 8u> I64ToNativeEndian(int64_t val) {
466 return internal::ToLittleEndian(val);
467 }
468 // Returns a byte array holding the value of a float encoded as the native
469 // endian encoding of the number for the machine.
470 //
471 // This is suitable for encoding numbers that will always be kept in native
472 // encoding, such as for storing in shared-memory (or sending through IPC) as a
473 // byte buffer. Prefer an explicit little endian when storing data into external
474 // storage, and explicit big endian for network order.
FloatToNativeEndian(float val)475 inline constexpr std::array<uint8_t, 4u> FloatToNativeEndian(float val) {
476 return U32ToNativeEndian(std::bit_cast<uint32_t>(val));
477 }
478 // Returns a byte array holding the value of a double encoded as the native
479 // endian encoding of the number for the machine.
480 //
481 // This is suitable for encoding numbers that will always be kept in native
482 // encoding, such as for storing in shared-memory (or sending through IPC) as a
483 // byte buffer. Prefer an explicit little endian when storing data into external
484 // storage, and explicit big endian for network order.
DoubleToNativeEndian(double val)485 inline constexpr std::array<uint8_t, 8u> DoubleToNativeEndian(double val) {
486 return U64ToNativeEndian(std::bit_cast<uint64_t>(val));
487 }
488
489 // Returns a byte array holding the value of a uint8_t encoded as the
490 // little-endian encoding of the integer.
491 //
492 // This is suitable for encoding integers explicitly in little endian, which is
493 // a good practice with storing and reading data from storage. Use the
494 // native-endian versions when working with values that will always be in
495 // memory, such as when stored in shared-memory (or passed through IPC) as a
496 // byte buffer.
U8ToLittleEndian(uint8_t val)497 inline constexpr std::array<uint8_t, 1u> U8ToLittleEndian(uint8_t val) {
498 return {val};
499 }
500 // Returns a byte array holding the value of a uint16_t encoded as the
501 // little-endian encoding of the integer.
502 //
503 // This is suitable for encoding integers explicitly in little endian, which is
504 // a good practice with storing and reading data from storage. Use the
505 // native-endian versions when working with values that will always be in
506 // memory, such as when stored in shared-memory (or passed through IPC) as a
507 // byte buffer.
U16ToLittleEndian(uint16_t val)508 inline constexpr std::array<uint8_t, 2u> U16ToLittleEndian(uint16_t val) {
509 return internal::ToLittleEndian(val);
510 }
511 // Returns a byte array holding the value of a uint32_t encoded as the
512 // little-endian encoding of the integer.
513 //
514 // This is suitable for encoding integers explicitly in little endian, which is
515 // a good practice with storing and reading data from storage. Use the
516 // native-endian versions when working with values that will always be in
517 // memory, such as when stored in shared-memory (or passed through IPC) as a
518 // byte buffer.
U32ToLittleEndian(uint32_t val)519 inline constexpr std::array<uint8_t, 4u> U32ToLittleEndian(uint32_t val) {
520 return internal::ToLittleEndian(val);
521 }
522 // Returns a byte array holding the value of a uint64_t encoded as the
523 // little-endian encoding of the integer.
524 //
525 // This is suitable for encoding integers explicitly in little endian, which is
526 // a good practice with storing and reading data from storage. Use the
527 // native-endian versions when working with values that will always be in
528 // memory, such as when stored in shared-memory (or passed through IPC) as a
529 // byte buffer.
U64ToLittleEndian(uint64_t val)530 inline constexpr std::array<uint8_t, 8u> U64ToLittleEndian(uint64_t val) {
531 return internal::ToLittleEndian(val);
532 }
533 // Returns a byte array holding the value of a int8_t encoded as the
534 // little-endian encoding of the integer.
535 //
536 // This is suitable for encoding integers explicitly in little endian, which is
537 // a good practice with storing and reading data from storage. Use the
538 // native-endian versions when working with values that will always be in
539 // memory, such as when stored in shared-memory (or passed through IPC) as a
540 // byte buffer.
I8ToLittleEndian(int8_t val)541 inline constexpr std::array<uint8_t, 1u> I8ToLittleEndian(int8_t val) {
542 return {static_cast<uint8_t>(val)};
543 }
544 // Returns a byte array holding the value of a int16_t encoded as the
545 // little-endian encoding of the integer.
546 //
547 // This is suitable for encoding integers explicitly in little endian, which is
548 // a good practice with storing and reading data from storage. Use the
549 // native-endian versions when working with values that will always be in
550 // memory, such as when stored in shared-memory (or passed through IPC) as a
551 // byte buffer.
I16ToLittleEndian(int16_t val)552 inline constexpr std::array<uint8_t, 2u> I16ToLittleEndian(int16_t val) {
553 return internal::ToLittleEndian(val);
554 }
555 // Returns a byte array holding the value of a int32_t encoded as the
556 // little-endian encoding of the integer.
557 //
558 // This is suitable for encoding integers explicitly in little endian, which is
559 // a good practice with storing and reading data from storage. Use the
560 // native-endian versions when working with values that will always be in
561 // memory, such as when stored in shared-memory (or passed through IPC) as a
562 // byte buffer.
I32ToLittleEndian(int32_t val)563 inline constexpr std::array<uint8_t, 4u> I32ToLittleEndian(int32_t val) {
564 return internal::ToLittleEndian(val);
565 }
566 // Returns a byte array holding the value of a int64_t encoded as the
567 // little-endian encoding of the integer.
568 //
569 // This is suitable for encoding integers explicitly in little endian, which is
570 // a good practice with storing and reading data from storage. Use the
571 // native-endian versions when working with values that will always be in
572 // memory, such as when stored in shared-memory (or passed through IPC) as a
573 // byte buffer.
I64ToLittleEndian(int64_t val)574 inline constexpr std::array<uint8_t, 8u> I64ToLittleEndian(int64_t val) {
575 return internal::ToLittleEndian(val);
576 }
577 // Returns a byte array holding the value of a float encoded as the
578 // little-endian encoding of the number.
579 //
580 // This is suitable for encoding numbers explicitly in little endian, which is
581 // a good practice with storing and reading data from storage. Use the
582 // native-endian versions when working with values that will always be in
583 // memory, such as when stored in shared-memory (or passed through IPC) as a
584 // byte buffer.
FloatToLittleEndian(float val)585 inline constexpr std::array<uint8_t, 4u> FloatToLittleEndian(float val) {
586 return internal::ToLittleEndian(std::bit_cast<uint32_t>(val));
587 }
588 // Returns a byte array holding the value of a double encoded as the
589 // little-endian encoding of the number.
590 //
591 // This is suitable for encoding numbers explicitly in little endian, which is
592 // a good practice with storing and reading data from storage. Use the
593 // native-endian versions when working with values that will always be in
594 // memory, such as when stored in shared-memory (or passed through IPC) as a
595 // byte buffer.
DoubleToLittleEndian(double val)596 inline constexpr std::array<uint8_t, 8u> DoubleToLittleEndian(double val) {
597 return internal::ToLittleEndian(std::bit_cast<uint64_t>(val));
598 }
599
600 // Returns a byte array holding the value of a uint8_t encoded as the big-endian
601 // encoding of the integer.
602 //
603 // This is suitable for encoding integers explicitly in big endian, such as for
604 // network order. Use the native-endian versions when working with values that
605 // are always in memory, such as when stored in shared-memory (or passed through
606 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
607 // from storage.
U8ToBigEndian(uint8_t val)608 inline constexpr std::array<uint8_t, 1u> U8ToBigEndian(uint8_t val) {
609 return {val};
610 }
611 // Returns a byte array holding the value of a uint16_t encoded as the
612 // big-endian encoding of the integer.
613 //
614 // This is suitable for encoding integers explicitly in big endian, such as for
615 // network order. Use the native-endian versions when working with values that
616 // are always in memory, such as when stored in shared-memory (or passed through
617 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
618 // from storage.
U16ToBigEndian(uint16_t val)619 inline constexpr std::array<uint8_t, 2u> U16ToBigEndian(uint16_t val) {
620 return internal::ToLittleEndian(ByteSwap(val));
621 }
622 // Returns a byte array holding the value of a uint32_t encoded as the
623 // big-endian encoding of the integer.
624 //
625 // This is suitable for encoding integers explicitly in big endian, such as for
626 // network order. Use the native-endian versions when working with values that
627 // are always in memory, such as when stored in shared-memory (or passed through
628 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
629 // from storage.
U32ToBigEndian(uint32_t val)630 inline constexpr std::array<uint8_t, 4u> U32ToBigEndian(uint32_t val) {
631 return internal::ToLittleEndian(ByteSwap(val));
632 }
633 // Returns a byte array holding the value of a uint64_t encoded as the
634 // big-endian encoding of the integer.
635 //
636 // This is suitable for encoding integers explicitly in big endian, such as for
637 // network order. Use the native-endian versions when working with values that
638 // are always in memory, such as when stored in shared-memory (or passed through
639 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
640 // from storage.
U64ToBigEndian(uint64_t val)641 inline constexpr std::array<uint8_t, 8u> U64ToBigEndian(uint64_t val) {
642 return internal::ToLittleEndian(ByteSwap(val));
643 }
644 // Returns a byte array holding the value of a int8_t encoded as the big-endian
645 // encoding of the integer.
646 //
647 // This is suitable for encoding integers explicitly in big endian, such as for
648 // network order. Use the native-endian versions when working with values that
649 // are always in memory, such as when stored in shared-memory (or passed through
650 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
651 // from storage.
I8ToBigEndian(int8_t val)652 inline constexpr std::array<uint8_t, 1u> I8ToBigEndian(int8_t val) {
653 return {static_cast<uint8_t>(val)};
654 }
655 // Returns a byte array holding the value of a int16_t encoded as the
656 // big-endian encoding of the integer.
657 //
658 // This is suitable for encoding integers explicitly in big endian, such as for
659 // network order. Use the native-endian versions when working with values that
660 // are always in memory, such as when stored in shared-memory (or passed through
661 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
662 // from storage.
I16ToBigEndian(int16_t val)663 inline constexpr std::array<uint8_t, 2u> I16ToBigEndian(int16_t val) {
664 return internal::ToLittleEndian(ByteSwap(val));
665 }
666 // Returns a byte array holding the value of a int32_t encoded as the
667 // big-endian encoding of the integer.
668 //
669 // This is suitable for encoding integers explicitly in big endian, such as for
670 // network order. Use the native-endian versions when working with values that
671 // are always in memory, such as when stored in shared-memory (or passed through
672 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
673 // from storage.
I32ToBigEndian(int32_t val)674 inline constexpr std::array<uint8_t, 4u> I32ToBigEndian(int32_t val) {
675 return internal::ToLittleEndian(ByteSwap(val));
676 }
677 // Returns a byte array holding the value of a int64_t encoded as the
678 // big-endian encoding of the integer.
679 //
680 // This is suitable for encoding integers explicitly in big endian, such as for
681 // network order. Use the native-endian versions when working with values that
682 // are always in memory, such as when stored in shared-memory (or passed through
683 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
684 // from storage.
I64ToBigEndian(int64_t val)685 inline constexpr std::array<uint8_t, 8u> I64ToBigEndian(int64_t val) {
686 return internal::ToLittleEndian(ByteSwap(val));
687 }
688 // Returns a byte array holding the value of a float encoded as the big-endian
689 // encoding of the number.
690 //
691 // This is suitable for encoding numbers explicitly in big endian, such as for
692 // network order. Use the native-endian versions when working with values that
693 // are always in memory, such as when stored in shared-memory (or passed through
694 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
695 // from storage.
FloatToBigEndian(float val)696 inline constexpr std::array<uint8_t, 4u> FloatToBigEndian(float val) {
697 return internal::ToLittleEndian(ByteSwap(std::bit_cast<uint32_t>(val)));
698 }
699 // Returns a byte array holding the value of a double encoded as the big-endian
700 // encoding of the number.
701 //
702 // This is suitable for encoding numbers explicitly in big endian, such as for
703 // network order. Use the native-endian versions when working with values that
704 // are always in memory, such as when stored in shared-memory (or passed through
705 // IPC) as a byte buffer. Use the little-endian encoding for storing and reading
706 // from storage.
DoubleToBigEndian(double val)707 inline constexpr std::array<uint8_t, 8u> DoubleToBigEndian(double val) {
708 return internal::ToLittleEndian(ByteSwap(std::bit_cast<uint64_t>(val)));
709 }
710
711 // Deprecated: Prefer the shorter, less-namespaced names.
712 // TODO(crbug.com/40284755): Remove these when callers have been migrated to
713 // the shorter name.
714 namespace numerics {
715 using ::base::ByteSwap;
716 using ::base::DoubleFromBigEndian;
717 using ::base::DoubleFromLittleEndian;
718 using ::base::DoubleFromNativeEndian;
719 using ::base::DoubleToBigEndian;
720 using ::base::DoubleToLittleEndian;
721 using ::base::DoubleToNativeEndian;
722 using ::base::FloatFromBigEndian;
723 using ::base::FloatFromLittleEndian;
724 using ::base::FloatFromNativeEndian;
725 using ::base::FloatToBigEndian;
726 using ::base::FloatToLittleEndian;
727 using ::base::FloatToNativeEndian;
728 using ::base::I16FromBigEndian;
729 using ::base::I16FromLittleEndian;
730 using ::base::I16FromNativeEndian;
731 using ::base::I16ToBigEndian;
732 using ::base::I16ToLittleEndian;
733 using ::base::I16ToNativeEndian;
734 using ::base::I32FromBigEndian;
735 using ::base::I32FromLittleEndian;
736 using ::base::I32FromNativeEndian;
737 using ::base::I32ToBigEndian;
738 using ::base::I32ToLittleEndian;
739 using ::base::I32ToNativeEndian;
740 using ::base::I64FromBigEndian;
741 using ::base::I64FromLittleEndian;
742 using ::base::I64FromNativeEndian;
743 using ::base::I64ToBigEndian;
744 using ::base::I64ToLittleEndian;
745 using ::base::I64ToNativeEndian;
746 using ::base::I8FromBigEndian;
747 using ::base::I8FromLittleEndian;
748 using ::base::I8FromNativeEndian;
749 using ::base::I8ToBigEndian;
750 using ::base::I8ToLittleEndian;
751 using ::base::I8ToNativeEndian;
752 using ::base::U16FromBigEndian;
753 using ::base::U16FromLittleEndian;
754 using ::base::U16FromNativeEndian;
755 using ::base::U16ToBigEndian;
756 using ::base::U16ToLittleEndian;
757 using ::base::U16ToNativeEndian;
758 using ::base::U32FromBigEndian;
759 using ::base::U32FromLittleEndian;
760 using ::base::U32FromNativeEndian;
761 using ::base::U32ToBigEndian;
762 using ::base::U32ToLittleEndian;
763 using ::base::U32ToNativeEndian;
764 using ::base::U64FromBigEndian;
765 using ::base::U64FromLittleEndian;
766 using ::base::U64FromNativeEndian;
767 using ::base::U64ToBigEndian;
768 using ::base::U64ToLittleEndian;
769 using ::base::U64ToNativeEndian;
770 using ::base::U8FromBigEndian;
771 using ::base::U8FromLittleEndian;
772 using ::base::U8FromNativeEndian;
773 using ::base::U8ToBigEndian;
774 using ::base::U8ToLittleEndian;
775 using ::base::U8ToNativeEndian;
776 } // namespace numerics
777
778 } // namespace base
779
780 #endif // BASE_NUMERICS_BYTE_CONVERSIONS_H_
781