1#[cfg(feature = "alloc")]
4pub(crate) use alloc::vec::Vec;
5
6pub(crate) use subtle::ConstantTimeEq;
7
8#[macro_export]
12macro_rules! newtype_accessors_impls {
13 ($($wrapper:ident, $inner:ty;)*) => {$(
14 impl AsMut<$inner> for $wrapper {
15 fn as_mut(&mut self) -> &mut $inner {
16 &mut self.0
17 }
18 }
19
20 impl AsRef<$inner> for $wrapper {
21 fn as_ref(&self) -> &$inner {
22 &self.0
23 }
24 }
25
26 impl From<$inner> for $wrapper {
27 fn from(src: $inner) -> Self {
28 Self(src)
29 }
30 }
31
32 impl<'src> From<&'src $inner> for $wrapper {
33 fn from(src: &$inner) -> Self {
34 Self(src.clone())
35 }
36 }
37
38 impl From<$wrapper> for $inner {
39 fn from(src: $wrapper) -> $inner {
40 src.0
41 }
42 }
43
44 )*}
45}
46
47#[macro_export]
48macro_rules! impl_newtype_no_display {
51 ($($wrapper:ident, $inner:ty;)*) => {$(
52 $crate::newtype_accessors_impls! {
53 $wrapper, $inner;
54 }
55 )*}
56}
57#[macro_export]
59macro_rules! impl_newtype {
60 ($($wrapper:ident, $inner:ty;)*) => {$(
61 $crate::newtype_accessors_impls! {
62 $wrapper, $inner;
63 }
64
65 impl ::core::fmt::Display for $wrapper {
66 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
67 ::core::fmt::Debug::fmt(&self.0, f)
68 }
69 }
70 )*}
71}
72
73#[macro_export]
78macro_rules! impl_newtype_for_bytestruct {
79 ($($wrapper:ident, $inner:ident, $size:ident, $fieldname:ident;)*) => {$(
80
81 $crate::newtype_accessors_impls! {
82 $wrapper, $inner;
83 }
84
85 impl $wrapper {
86 #[doc="Size of the internal array"]
87 pub const SIZE: usize = $size;
88 }
89
90 impl AsRef<[u8]> for $wrapper {
91 fn as_ref(&self) -> &[u8] {
92 &(self.0).$fieldname[..]
93 }
94 }
95
96 impl AsMut<[u8]> for $wrapper {
97 fn as_mut(&mut self) -> &mut [u8] {
98 &mut (self.0).$fieldname[..]
99 }
100 }
101
102 impl $crate::macros::ConstantTimeEq for $wrapper {
103 fn ct_eq(&self, other: &Self) -> subtle::Choice {
104 (self.0).$fieldname[..].ct_eq(&(other.0).$fieldname[..])
105 }
106 }
107
108 impl Ord for $wrapper {
109 fn cmp(&self, other: &$wrapper) -> core::cmp::Ordering {
110 self.0.$fieldname.cmp(&other.0.$fieldname)
111 }
112 }
113
114 impl PartialOrd for $wrapper {
115 fn partial_cmp(&self, other: &$wrapper) -> Option<core::cmp::Ordering> {
116 Some(self.0.$fieldname.cmp(&other.0.$fieldname))
117 }
118 }
119
120 impl<'bytes> TryFrom<&'bytes [u8]> for $wrapper {
121 type Error = $crate::FfiError;
122
123 fn try_from(src: &[u8]) -> ::core::result::Result<Self, Self::Error> {
124 if src.len() < $size {
125 return Err($crate::FfiError::InvalidInputLength);
126 }
127
128 let mut retval = $wrapper::default();
129 (retval.0).$fieldname[..].copy_from_slice(&src[..$size]);
130 Ok(retval)
131 }
132 }
133
134 #[cfg(feature="alloc")]
135 impl TryFrom<$crate::macros::Vec<u8>> for $wrapper {
136 type Error = $crate::FfiError;
137
138 fn try_from(src: $crate::macros::Vec<u8>) -> ::core::result::Result<Self, Self::Error> {
139 Self::try_from(src.as_slice())
140 }
141 }
142
143 impl From<[u8; $size]> for $wrapper {
144 fn from($fieldname: [u8; $size]) -> Self {
145 Self($inner { $fieldname })
146 }
147 }
148
149 )*}
150}
151
152#[macro_export]
158macro_rules! derive_measurement_hex_from_as_ref {
159 ($mytype:ty) => {
160 $crate::derive_measurement_hex_from_as_ref!($mytype, [u8]);
161 };
162 ($mytype:ty, $asref:ty) => {
163 impl core::fmt::LowerHex for $mytype {
164 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
165 let data: &$asref = self.as_ref();
166 for d in data {
167 write!(f, "{:02x}", d)?;
168 }
169 Ok(())
170 }
171 }
172
173 impl core::fmt::UpperHex for $mytype {
174 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175 let data: &$asref = self.as_ref();
176 for d in data {
177 write!(f, "{:02X}", d)?;
178 }
179 Ok(())
180 }
181 }
182
183 impl hex::FromHex for $mytype {
184 type Error = hex::FromHexError;
185 fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
186 let bytes = <[u8; <$mytype>::SIZE]>::from_hex(hex)?;
187 Ok(bytes.into())
188 }
189 }
190 };
191}
192
193#[macro_export]
198macro_rules! impl_display_and_debug_for_measurement {
199 ($($wrapper:ident),*) => {$(
200 $crate::derive_measurement_hex_from_as_ref!($wrapper);
201 impl core::fmt::Debug for $wrapper {
202 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
203 write!(f, "{}({})", stringify!($wrapper), self)
204 }
205 }
206
207 impl core::fmt::Display for $wrapper {
208 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
209 write!(f, "{:x}", self)
210 }
211 }
212 )*}
213}
214
215#[macro_export]
220macro_rules! impl_display_for_bytestruct {
221 ($($wrapper:ident)*) => {$(
222 impl ::core::fmt::UpperHex for $wrapper {
223 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
224 let inner: &[u8] = self.as_ref();
225 mc_sgx_util::fmt_hex(inner, f)
226 }
227 }
228 impl ::core::fmt::Display for $wrapper {
229 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
230 write!(f, "{:#X}", self)
231 }
232 }
233 )*}
234}
235
236#[cfg(test)]
237mod test {
238 extern crate std;
239
240 use crate::FfiError;
241 use std::format;
242 use std::string::ToString;
243 use yare::parameterized;
244
245 const FIELD_SIZE: usize = 24;
246
247 #[derive(Debug, Default, Eq, Clone, Copy, PartialEq)]
248 struct Inner {
249 field: [u8; FIELD_SIZE],
250 }
251
252 #[derive(Debug, Default, Eq, Clone, PartialEq)]
253 #[repr(transparent)]
254 struct Outer(Inner);
255
256 impl_newtype_for_bytestruct! {
257 Outer, Inner, FIELD_SIZE, field;
258 }
259 impl_display_for_bytestruct!(Outer);
260
261 #[test]
262 fn outer_from_inner() {
263 let inner = Inner {
264 field: [4u8; Outer::SIZE],
265 };
266 let outer: Outer = inner.into();
267 assert_eq!(outer.0, inner);
268 }
269
270 #[parameterized(
271 correct_size = { FIELD_SIZE, Ok(Outer::default()) },
272 extra_large = { FIELD_SIZE + 1, Ok(Outer::default()) },
273 too_small = { FIELD_SIZE - 1, Err(FfiError::InvalidInputLength) },
274 )]
275 fn try_from(size: usize, result: Result<Outer, FfiError>) {
276 let buffer = [0; FIELD_SIZE * 2];
277 let slice = &buffer[..size];
278 assert_eq!(Outer::try_from(slice), result);
279
280 #[cfg(feature = "alloc")]
281 {
282 use alloc::vec;
283 let zero_vec = vec![0; size];
284 assert_eq!(Outer::try_from(zero_vec), result);
285 }
286 }
287
288 #[test]
289 fn from_array() {
290 let raw_array = [5u8; Outer::SIZE];
291 let outer: Outer = raw_array.into();
292 assert_eq!(outer.0.field, raw_array);
293 }
294
295 #[test]
296 fn as_ref() {
297 let raw_array = [9u8; Outer::SIZE];
298 let outer: Outer = raw_array.into();
299 assert_eq!(outer.as_ref(), raw_array);
300 }
301
302 #[test]
303 fn as_mut() {
304 let mut outer = Outer::default();
305 let replacement = [11u8; Outer::SIZE];
306 let mut_ref: &mut [u8] = outer.as_mut();
307 mut_ref.copy_from_slice(&replacement);
308 assert_eq!(outer.0.field, replacement);
309 }
310
311 #[test]
312 fn default() {
313 let outer = Outer::default();
314 assert_eq!(outer.0.field, [0u8; Outer::SIZE]);
315 }
316
317 #[test]
318 fn newtype_byte_array_display() {
319 let outer = Outer::from([
320 0xABu8, 0x00, 0xcd, 0x12, 0xfe, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0a,
321 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
322 ]);
323 assert_eq!(
324 outer.to_string(),
325 "0xAB00_CD12_FE01_0203_0405_0607_0809_0A0B_0C0D_0E0F_1011_1213"
326 );
327 }
328
329 #[derive(Debug, Clone, Copy, PartialEq)]
330 struct StructInner {
331 field: u32,
332 }
333
334 #[repr(transparent)]
335 struct StructOuter(StructInner);
336 impl_newtype! {
337 StructOuter, StructInner;
338 }
339
340 #[repr(transparent)]
341 struct PrimitiveOuter(u32);
342 impl_newtype! {
343 PrimitiveOuter, u32;
344 }
345
346 #[test]
347 fn newtype_for_struct() {
348 let inner = StructInner { field: 30 };
349 let outer: StructOuter = inner.into();
350 assert_eq!(outer.0, inner);
351 }
352
353 #[test]
354 fn display_newtype_for_struct() {
355 let inner = StructInner { field: 20 };
356 let outer: StructOuter = inner.into();
357 assert_eq!(outer.to_string(), "StructInner { field: 20 }");
358 }
359
360 #[test]
361 fn display_newtype_for_struct_alternate() {
362 let inner = StructInner { field: 20 };
363 let outer: StructOuter = inner.into();
364 let expected = r#"
365 StructInner {
366 field: 20,
367 }"#;
368 assert_eq!(format!("\n{outer:#}"), textwrap::dedent(expected));
369 }
370
371 #[test]
372 fn display_newtype_for_primitive() {
373 let inner = 42;
374 let outer: PrimitiveOuter = inner.into();
375 assert_eq!(outer.to_string(), "42");
376 }
377}