Skip to content

Commit

Permalink
Add Display implementation for newtype wrappers (#301)
Browse files Browse the repository at this point in the history
Previously the newtype implementations didn't implement the `Display`
trait. Now the `Display` trait is implemented on any newtype that uses
one of `impl_newtype` or `impl_newtype_for_bytestruct`.

Renamed the internal macro `new_type_accessors_impls` to
`impl_newtype` for consistency.
  • Loading branch information
nick-mobilecoin authored Mar 22, 2023
2 parents 5921c23 + 6a993f4 commit 45d890a
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 46 deletions.
5 changes: 2 additions & 3 deletions core/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ rust-version = "1.62.1"

[features]
default = []
serde = [
"dep:serde"
]
serde = ["dep:serde"]
alloc = []

[dependencies]
Expand All @@ -34,4 +32,5 @@ getrandom = { version = "0.2", default-features = false, features = ["custom"] }

[dev-dependencies]
rand = "0.8.5"
textwrap = "0.16.0"
yare = "1.0.1"
12 changes: 6 additions & 6 deletions core/types/src/attestation_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! Attestation Key types
use crate::{
new_type_accessors_impls,
impl_newtype,
report::{ExtendedProductId, FamilyId},
ConfigId, FfiError,
};
Expand Down Expand Up @@ -49,15 +49,15 @@ impl TryFrom<u32> for Algorithm {
#[repr(transparent)]
pub struct Version(u16);

new_type_accessors_impls! {
impl_newtype! {
Version, u16;
}

#[derive(Debug, Default, Clone, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub struct Id(u16);

new_type_accessors_impls! {
impl_newtype! {
Id, u16;
}

Expand Down Expand Up @@ -145,7 +145,7 @@ impl AttestationKeyId {
}
}

new_type_accessors_impls! {
impl_newtype! {
AttestationKeyId, sgx_ql_att_key_id_t;
}

Expand All @@ -154,7 +154,7 @@ new_type_accessors_impls! {
#[repr(transparent)]
pub struct ServiceProviderId([u8; 16]);

new_type_accessors_impls! {
impl_newtype! {
ServiceProviderId, [u8; 16];
}

Expand All @@ -180,7 +180,7 @@ impl ExtendedAttestationKeyId {
}
}

new_type_accessors_impls! {
impl_newtype! {
ExtendedAttestationKeyId, sgx_att_key_id_ext_t;
}

Expand Down
8 changes: 4 additions & 4 deletions core/types/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

//! SGX Attributes types
use crate::new_type_accessors_impls;
use crate::impl_newtype;
use mc_sgx_core_sys_types::{sgx_attributes_t, sgx_misc_attribute_t, sgx_misc_select_t};

/// Attributes of the enclave
#[repr(transparent)]
#[derive(Default, Debug, Clone, Hash, PartialEq, Eq, Copy)]
pub struct Attributes(sgx_attributes_t);
new_type_accessors_impls! {
impl_newtype! {
Attributes, sgx_attributes_t;
}

Expand Down Expand Up @@ -40,7 +40,7 @@ impl Attributes {
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default)]
pub struct MiscellaneousSelect(sgx_misc_select_t);

new_type_accessors_impls! {
impl_newtype! {
MiscellaneousSelect, sgx_misc_select_t;
}

Expand All @@ -49,7 +49,7 @@ new_type_accessors_impls! {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct MiscellaneousAttribute(sgx_misc_attribute_t);

new_type_accessors_impls! {
impl_newtype! {
MiscellaneousAttribute, sgx_misc_attribute_t;
}

Expand Down
4 changes: 2 additions & 2 deletions core/types/src/config_id.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
// Copyright (c) 2022-2023 The MobileCoin Foundation
//! SGX Config ID
use crate::new_type_accessors_impls;
use crate::impl_newtype;
use mc_sgx_core_sys_types::{sgx_config_id_t, SGX_CONFIGID_SIZE};

/// Config ID
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub struct ConfigId(sgx_config_id_t);

new_type_accessors_impls! {
impl_newtype! {
ConfigId, sgx_config_id_t;
}

Expand Down
6 changes: 3 additions & 3 deletions core/types/src/key_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! SGX key request rust types
use crate::{
impl_newtype_for_bytestruct, new_type_accessors_impls, Attributes, ConfigSvn, CpuSvn, IsvSvn,
impl_newtype, impl_newtype_for_bytestruct, Attributes, ConfigSvn, CpuSvn, IsvSvn,
MiscellaneousSelect,
};
use bitflags::bitflags;
Expand Down Expand Up @@ -73,7 +73,7 @@ bitflags! {
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub struct KeyRequest(sgx_key_request_t);
new_type_accessors_impls! {
impl_newtype! {
KeyRequest, sgx_key_request_t;
}

Expand Down Expand Up @@ -189,7 +189,7 @@ impl KeyRequestBuilder {
#[derive(Default, Debug, Clone, Hash, PartialEq, Eq)]
pub struct Key128bit(sgx_key_128bit_t);

new_type_accessors_impls! {
impl_newtype! {
Key128bit, sgx_key_128bit_t;
}

Expand Down
116 changes: 110 additions & 6 deletions core/types/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub(crate) use alloc::vec::Vec;
/// an SgxWrapperType that don't depend on the contents of the inner
/// type.
#[macro_export]
macro_rules! new_type_accessors_impls {
macro_rules! newtype_accessors_impls {
($($wrapper:ident, $inner:ty;)*) => {$(
impl AsMut<$inner> for $wrapper {
fn as_mut(&mut self) -> &mut $inner {
Expand Down Expand Up @@ -42,6 +42,23 @@ macro_rules! new_type_accessors_impls {
)*}
}

/// Newtype wrapper for a primitive or struct type
#[macro_export]
macro_rules! impl_newtype {
($($wrapper:ident, $inner:ty;)*) => {$(
$crate::newtype_accessors_impls! {
$wrapper, $inner;
}

impl ::core::fmt::Display for $wrapper {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(&self.0, f)
}
}

)*}
}

/// This macro provides common byte-handling operations when the type being
/// wrapped is a struct containing a single fixed-size array of bytes.
///
Expand All @@ -50,7 +67,7 @@ macro_rules! new_type_accessors_impls {
macro_rules! impl_newtype_for_bytestruct {
($($wrapper:ident, $inner:ident, $size:ident, $fieldname:ident;)*) => {$(

$crate::new_type_accessors_impls! {
$crate::newtype_accessors_impls! {
$wrapper, $inner;
}

Expand All @@ -74,7 +91,7 @@ macro_rules! impl_newtype_for_bytestruct {
impl<'bytes> TryFrom<&'bytes [u8]> for $wrapper {
type Error = $crate::FfiError;

fn try_from(src: &[u8]) -> core::result::Result<Self, Self::Error> {
fn try_from(src: &[u8]) -> ::core::result::Result<Self, Self::Error> {
if src.len() < $size {
return Err($crate::FfiError::InvalidInputLength);
}
Expand All @@ -89,7 +106,7 @@ macro_rules! impl_newtype_for_bytestruct {
impl TryFrom<$crate::macros::Vec<u8>> for $wrapper {
type Error = $crate::FfiError;

fn try_from(src: $crate::macros::Vec<u8>) -> core::result::Result<Self, Self::Error> {
fn try_from(src: $crate::macros::Vec<u8>) -> ::core::result::Result<Self, Self::Error> {
Self::try_from(src.as_slice())
}
}
Expand All @@ -100,22 +117,48 @@ macro_rules! impl_newtype_for_bytestruct {
}
}

impl ::core::fmt::UpperHex for $wrapper {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let inner: &[u8] = self.as_ref();
let prefix = if f.alternate() { "0x" } else { "" };
let separators = ::core::iter::once(prefix).chain(::core::iter::repeat("_"));
let segments = separators.zip(inner.chunks(2));
for (separator, chunk) in segments {
write!(f, "{separator}")?;
for byte in chunk {
write!(f, "{:02X}", byte)?;
}
}
Ok(())
}
}

impl ::core::fmt::Display for $wrapper {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{:#X}", self)
}
}

)*}
}

#[cfg(test)]
mod test {
extern crate std;

use crate::FfiError;
use std::format;
use std::string::ToString;
use yare::parameterized;

const FIELD_SIZE: usize = 24;

#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Default, Debug, Clone, Copy, PartialEq)]
struct Inner {
field: [u8; FIELD_SIZE],
}

#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Default, Debug, Clone, PartialEq)]
#[repr(transparent)]
struct Outer(Inner);

Expand Down Expand Up @@ -178,4 +221,65 @@ mod test {
let outer = Outer::default();
assert_eq!(outer.0.field, [0u8; Outer::SIZE]);
}

#[test]
fn newtype_byte_array_display() {
let outer = Outer::from([
0xABu8, 0x00, 0xcd, 0x12, 0xfe, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0a,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
]);
assert_eq!(
outer.to_string(),
"0xAB00_CD12_FE01_0203_0405_0607_0809_0A0B_0C0D_0E0F_1011_1213"
);
}

#[derive(Debug, Clone, Copy, PartialEq)]
struct StructInner {
field: u32,
}

#[repr(transparent)]
struct StructOuter(StructInner);
impl_newtype! {
StructOuter, StructInner;
}

#[repr(transparent)]
struct PrimitiveOuter(u32);
impl_newtype! {
PrimitiveOuter, u32;
}

#[test]
fn newtype_for_struct() {
let inner = StructInner { field: 30 };
let outer: StructOuter = inner.into();
assert_eq!(outer.0, inner);
}

#[test]
fn display_newtype_for_struct() {
let inner = StructInner { field: 20 };
let outer: StructOuter = inner.into();
assert_eq!(outer.to_string(), "StructInner { field: 20 }");
}

#[test]
fn display_newtype_for_struct_alternate() {
let inner = StructInner { field: 20 };
let outer: StructOuter = inner.into();
let expected = r#"
StructInner {
field: 20,
}"#;
assert_eq!(format!("\n{outer:#}"), textwrap::dedent(expected));
}

#[test]
fn display_newtype_for_primitive() {
let inner = 42;
let outer: PrimitiveOuter = inner.into();
assert_eq!(outer.to_string(), "42");
}
}
12 changes: 6 additions & 6 deletions core/types/src/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
//! Quote types
use crate::{
attestation_key::QuoteSignatureKind, impl_newtype_for_bytestruct, new_type_accessors_impls,
report::Report, FfiError, IsvSvn, ReportBody, TargetInfo,
attestation_key::QuoteSignatureKind, impl_newtype, impl_newtype_for_bytestruct, report::Report,
FfiError, IsvSvn, ReportBody, TargetInfo,
};
use mc_sgx_core_sys_types::{
sgx_basename_t, sgx_epid_group_id_t, sgx_platform_info_t, sgx_qe_report_info_t,
Expand Down Expand Up @@ -32,7 +32,7 @@ impl QuotingEnclaveReportInfo {
}
}

new_type_accessors_impls! {
impl_newtype! {
QuotingEnclaveReportInfo, sgx_qe_report_info_t;
}

Expand All @@ -50,7 +50,7 @@ impl_newtype_for_bytestruct! {
#[repr(transparent)]
pub struct UpdateInfoBit(sgx_update_info_bit_t);

new_type_accessors_impls! {
impl_newtype! {
UpdateInfoBit, sgx_update_info_bit_t;
}

Expand All @@ -76,7 +76,7 @@ impl UpdateInfoBit {
#[repr(transparent)]
pub struct EpidGroupId(sgx_epid_group_id_t);

new_type_accessors_impls! {
impl_newtype! {
EpidGroupId, sgx_epid_group_id_t;
}

Expand Down Expand Up @@ -114,7 +114,7 @@ pub struct RawQuote<'a> {
#[repr(transparent)]
pub struct Version(u16);

new_type_accessors_impls! {
impl_newtype! {
Version, u16;
}

Expand Down
Loading

0 comments on commit 45d890a

Please sign in to comment.