Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Display implementation for newtype wrappers #301

Merged
merged 2 commits into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
nick-mobilecoin marked this conversation as resolved.
Show resolved Hide resolved
($($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