/rust/registry/src/index.crates.io-1949cf8c6b5b557f/aws-lc-rs-1.14.1/src/endian.rs
Line | Count | Source |
1 | | // Copyright 2015-2021 Brian Smith. |
2 | | // SPDX-License-Identifier: ISC |
3 | | // Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
4 | | // SPDX-License-Identifier: Apache-2.0 OR ISC |
5 | | |
6 | | /// An `Encoding` of a type `T` can be converted to/from its byte |
7 | | /// representation without any byte swapping or other computation. |
8 | | /// |
9 | | /// The `Self: Copy` constraint addresses `clippy::declare_interior_mutable_const`. |
10 | | pub trait Encoding<T>: From<T> + Into<T> |
11 | | where |
12 | | Self: Copy, |
13 | | { |
14 | | const ZERO: Self; |
15 | | } |
16 | | |
17 | | use core::mem::size_of_val; |
18 | | |
19 | 0 | pub fn as_byte_slice<E: Encoding<T>, T>(x: &[E]) -> &[u8] { |
20 | 0 | unsafe { core::slice::from_raw_parts(x.as_ptr().cast::<u8>(), size_of_val(x)) } |
21 | 0 | } Unexecuted instantiation: aws_lc_rs::endian::as_byte_slice::<aws_lc_rs::endian::LittleEndian<u32>, u32> Unexecuted instantiation: aws_lc_rs::endian::as_byte_slice::<aws_lc_rs::endian::LittleEndian<u64>, u64> Unexecuted instantiation: aws_lc_rs::endian::as_byte_slice::<aws_lc_rs::endian::BigEndian<u32>, u32> Unexecuted instantiation: aws_lc_rs::endian::as_byte_slice::<aws_lc_rs::endian::BigEndian<u64>, u64> |
22 | | |
23 | | /// Work around the inability to implement `AsRef` for arrays of `Encoding`s |
24 | | /// due to the coherence rules. |
25 | | pub trait ArrayEncoding<T> { |
26 | | fn as_byte_array(&self) -> &T; |
27 | | } |
28 | | |
29 | | /// Work around the inability to implement `from` for arrays of `Encoding`s |
30 | | /// due to the coherence rules. |
31 | | pub trait FromArray<const N: usize, T> |
32 | | where |
33 | | Self: Sized, |
34 | | { |
35 | | fn from_array(a: &[T; N]) -> [Self; N]; |
36 | | } |
37 | | |
38 | | macro_rules! define_endian { |
39 | | ($endian:ident) => { |
40 | | #[derive(Copy, Clone)] |
41 | | #[repr(transparent)] |
42 | | pub struct $endian<T>(T); |
43 | | }; |
44 | | } |
45 | | |
46 | | macro_rules! impl_array_encoding { |
47 | | // This may be converted to use const generics once generic_const_exprs is stable. |
48 | | // https://github.com/rust-lang/rust/issues/76560 |
49 | | ($endian:ident, $base:ident, $elems:expr) => { |
50 | | impl ArrayEncoding<[u8; $elems * core::mem::size_of::<$base>()]> |
51 | | for [$endian<$base>; $elems] |
52 | | { |
53 | 0 | fn as_byte_array(&self) -> &[u8; $elems * core::mem::size_of::<$base>()] { |
54 | 0 | as_byte_slice(self).try_into().unwrap() |
55 | 0 | } Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u32>; 1] as aws_lc_rs::endian::ArrayEncoding<[u8; 4]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u32>; 2] as aws_lc_rs::endian::ArrayEncoding<[u8; 8]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u32>; 3] as aws_lc_rs::endian::ArrayEncoding<[u8; 12]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u32>; 4] as aws_lc_rs::endian::ArrayEncoding<[u8; 16]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u64>; 4] as aws_lc_rs::endian::ArrayEncoding<[u8; 32]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u64>; 8] as aws_lc_rs::endian::ArrayEncoding<[u8; 64]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u32>; 8] as aws_lc_rs::endian::ArrayEncoding<[u8; 32]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u64>; 1] as aws_lc_rs::endian::ArrayEncoding<[u8; 8]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u64>; 2] as aws_lc_rs::endian::ArrayEncoding<[u8; 16]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u64>; 3] as aws_lc_rs::endian::ArrayEncoding<[u8; 24]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u64>; 4] as aws_lc_rs::endian::ArrayEncoding<[u8; 32]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::BigEndian<u64>; 8] as aws_lc_rs::endian::ArrayEncoding<[u8; 64]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u32>; 1] as aws_lc_rs::endian::ArrayEncoding<[u8; 4]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u32>; 2] as aws_lc_rs::endian::ArrayEncoding<[u8; 8]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u32>; 3] as aws_lc_rs::endian::ArrayEncoding<[u8; 12]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u32>; 4] as aws_lc_rs::endian::ArrayEncoding<[u8; 16]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u32>; 8] as aws_lc_rs::endian::ArrayEncoding<[u8; 32]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u64>; 1] as aws_lc_rs::endian::ArrayEncoding<[u8; 8]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u64>; 2] as aws_lc_rs::endian::ArrayEncoding<[u8; 16]>>::as_byte_array Unexecuted instantiation: <[aws_lc_rs::endian::LittleEndian<u64>; 3] as aws_lc_rs::endian::ArrayEncoding<[u8; 24]>>::as_byte_array |
56 | | } |
57 | | }; |
58 | | } |
59 | | |
60 | | macro_rules! impl_endian { |
61 | | ($endian:ident, $base:ident, $to_endian:ident, $from_endian:ident, $size:expr) => { |
62 | | impl Encoding<$base> for $endian<$base> { |
63 | | const ZERO: Self = Self(0); |
64 | | } |
65 | | |
66 | | impl From<$base> for $endian<$base> { |
67 | | #[inline] |
68 | 0 | fn from(value: $base) -> Self { |
69 | 0 | Self($base::$to_endian(value)) |
70 | 0 | } Unexecuted instantiation: <aws_lc_rs::endian::BigEndian<u32> as core::convert::From<u32>>::from Unexecuted instantiation: <aws_lc_rs::endian::BigEndian<u64> as core::convert::From<u64>>::from Unexecuted instantiation: <aws_lc_rs::endian::LittleEndian<u32> as core::convert::From<u32>>::from Unexecuted instantiation: <aws_lc_rs::endian::LittleEndian<u64> as core::convert::From<u64>>::from |
71 | | } |
72 | | |
73 | | impl From<$endian<$base>> for $base { |
74 | | #[inline] |
75 | 0 | fn from($endian(value): $endian<$base>) -> Self { |
76 | 0 | $base::$from_endian(value) |
77 | 0 | } Unexecuted instantiation: <u32 as core::convert::From<aws_lc_rs::endian::BigEndian<u32>>>::from Unexecuted instantiation: <u64 as core::convert::From<aws_lc_rs::endian::BigEndian<u64>>>::from Unexecuted instantiation: <u32 as core::convert::From<aws_lc_rs::endian::LittleEndian<u32>>>::from Unexecuted instantiation: <u64 as core::convert::From<aws_lc_rs::endian::LittleEndian<u64>>>::from |
78 | | } |
79 | | |
80 | | impl<const N: usize> FromArray<N, $base> for $endian<$base> { |
81 | 0 | fn from_array(value: &[$base; N]) -> [Self; N] { |
82 | 0 | let mut result: [$endian<$base>; N] = [$endian::ZERO; N]; |
83 | 0 | for i in 0..N { |
84 | 0 | result[i] = $endian::from(value[i]); |
85 | 0 | } |
86 | 0 | return result; |
87 | 0 | } Unexecuted instantiation: <aws_lc_rs::endian::BigEndian<u32> as aws_lc_rs::endian::FromArray<_, u32>>::from_array Unexecuted instantiation: <aws_lc_rs::endian::BigEndian<u64> as aws_lc_rs::endian::FromArray<_, u64>>::from_array Unexecuted instantiation: <aws_lc_rs::endian::LittleEndian<u32> as aws_lc_rs::endian::FromArray<_, u32>>::from_array Unexecuted instantiation: <aws_lc_rs::endian::LittleEndian<u64> as aws_lc_rs::endian::FromArray<_, u64>>::from_array |
88 | | } |
89 | | |
90 | | impl_array_encoding!($endian, $base, 1); |
91 | | impl_array_encoding!($endian, $base, 2); |
92 | | impl_array_encoding!($endian, $base, 3); |
93 | | impl_array_encoding!($endian, $base, 4); |
94 | | impl_array_encoding!($endian, $base, 8); |
95 | | }; |
96 | | } |
97 | | |
98 | | define_endian!(BigEndian); |
99 | | define_endian!(LittleEndian); |
100 | | impl_endian!(BigEndian, u32, to_be, from_be, 4); |
101 | | impl_endian!(BigEndian, u64, to_be, from_be, 8); |
102 | | impl_endian!(LittleEndian, u32, to_le, from_le, 4); |
103 | | impl_endian!(LittleEndian, u64, to_le, from_le, 8); |
104 | | |
105 | | #[cfg(test)] |
106 | | mod tests { |
107 | | use super::*; |
108 | | |
109 | | #[test] |
110 | | fn test_big_endian() { |
111 | | let x = BigEndian::from(1u32); |
112 | | let x2 = x; |
113 | | assert_eq!(u32::from(x), 1); |
114 | | assert_eq!(u32::from(x2), 1); |
115 | | } |
116 | | |
117 | | #[test] |
118 | | fn test_endian_from_array() { |
119 | | let be: [BigEndian<u32>; 2] = |
120 | | BigEndian::<u32>::from_array(&[0x_AABB_CCDD_u32, 0x_2233_4455_u32]); |
121 | | let le: [LittleEndian<u32>; 2] = |
122 | | LittleEndian::<u32>::from_array(&[0x_DDCC_BBAA_u32, 0x_5544_3322_u32]); |
123 | | assert_eq!(be.as_byte_array(), le.as_byte_array()); |
124 | | |
125 | | let be: [BigEndian<u64>; 2] = |
126 | | BigEndian::<u64>::from_array(&[0x_AABB_CCDD_EEFF_0011_u64, 0x_2233_4455_6677_8899_u64]); |
127 | | let le: [LittleEndian<u64>; 2] = LittleEndian::<u64>::from_array(&[ |
128 | | 0x_1100_FFEE_DDCC_BBAA_u64, |
129 | | 0x_9988_7766_5544_3322_u64, |
130 | | ]); |
131 | | assert_eq!(be.as_byte_array(), le.as_byte_array()); |
132 | | } |
133 | | } |