Skip to content

Commit

Permalink
#37; removed the SIZE type parameter - MEC itself is sufficient - goo…
Browse files Browse the repository at this point in the history
…d; all tests passed
  • Loading branch information
root committed Feb 23, 2024
1 parent f7be875 commit 29212ed
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 61 deletions.
6 changes: 6 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ macro_rules! impl_choose_int {

impl<$($prev_args,)* $arg> $crate::traits::ChooseMinimallyRepresentableUInt for $crate::prelude::typenum::uint::UInt<$prev_num, $arg> {
type Output = $out;
const MIN: Self::Output = Self::Output::MIN;
const ONE: Self::Output = 1;

fn cast_unsigned_to_self_type<T: $crate::prelude::typenum::uint::Unsigned>(_: $crate::traits::__private::SealedToken) -> Self::Output {
<T as $crate::prelude::typenum::uint::Unsigned>::USIZE as Self::Output
}
}

impl_choose_int!{
Expand Down
2 changes: 1 addition & 1 deletion src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod common;
// pub mod common;
pub mod error;
pub mod secret;
pub mod secret_sync;
Expand Down
18 changes: 9 additions & 9 deletions src/runtime/error.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
use crate::runtime::traits::MinimallyRepresentableUInt;
use crate::traits::ChooseMinimallyRepresentableUInt;

#[derive(Debug)]
#[non_exhaustive]
pub enum ExposeSecretError<SIZE: MinimallyRepresentableUInt> {
ExposeMoreThanMaximallyAllow(ExposeMoreThanMaximallyAllowError<SIZE>),
pub enum ExposeSecretError<MEC: ChooseMinimallyRepresentableUInt> {
ExposeMoreThanMaximallyAllow(ExposeMoreThanMaximallyAllowError<MEC>),
}

#[derive(Debug)]
pub struct ExposeMoreThanMaximallyAllowError<SIZE: MinimallyRepresentableUInt> {
pub mec: SIZE::Type,
pub ec: SIZE::Type,
pub struct ExposeMoreThanMaximallyAllowError<MEC: ChooseMinimallyRepresentableUInt> {
pub mec: <MEC as ChooseMinimallyRepresentableUInt>::Output,
pub ec: <MEC as ChooseMinimallyRepresentableUInt>::Output,
}

impl<SIZE: MinimallyRepresentableUInt> core::fmt::Display
for ExposeMoreThanMaximallyAllowError<SIZE>
impl<MEC: ChooseMinimallyRepresentableUInt> core::fmt::Display
for ExposeMoreThanMaximallyAllowError<MEC>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "`Secret` is exposed more than what it is maximally allowed to; it is exposed for {} times and it is only allowed to be exposed for {} times", self.ec, self.mec)
}
}

impl<SIZE: MinimallyRepresentableUInt> core::fmt::Display for ExposeSecretError<SIZE> {
impl<MEC: ChooseMinimallyRepresentableUInt> core::fmt::Display for ExposeSecretError<MEC> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::ExposeMoreThanMaximallyAllow(err) => err.fmt(f),
Expand Down
70 changes: 28 additions & 42 deletions src/runtime/secret.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
use core::{
cell::UnsafeCell,
cell::Cell,
marker::PhantomData,
ops::{Deref, Drop},
};

use crate::{
runtime::{common::DefaultMinimallyRepresentableUInt, error, traits},
traits::__private,
runtime::{error, traits},
traits::{ChooseMinimallyRepresentableUInt, __private},
};
use typenum::{IsLessOrEqual, True, Unsigned};
use typenum::Unsigned;
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

pub struct RTSecret<
#[cfg(feature = "zeroize")] T: Zeroize,
#[cfg(not(feature = "zeroize"))] T,
MEC: Unsigned,
SIZE: traits::MinimallyRepresentableUInt = DefaultMinimallyRepresentableUInt,
>(
T,
UnsafeCell<<SIZE as traits::MinimallyRepresentableUInt>::Type>,
PhantomData<MEC>,
);
MEC: ChooseMinimallyRepresentableUInt + Unsigned,
>(T, Cell<<MEC as ChooseMinimallyRepresentableUInt>::Output>);

pub struct RTExposedSecret<'brand, T>(T, PhantomData<fn(&'brand ()) -> &'brand ()>);

Expand All @@ -35,39 +30,31 @@ impl<'brand, T> Deref for RTExposedSecret<'brand, &'brand T> {
impl<
#[cfg(feature = "zeroize")] T: Zeroize,
#[cfg(not(feature = "zeroize"))] T,
MEC: Unsigned,
SIZE: traits::MinimallyRepresentableUInt,
> RTSecret<T, MEC, SIZE>
MEC: ChooseMinimallyRepresentableUInt + Unsigned,
> RTSecret<T, MEC>
{
pub const fn new(t: T) -> Self
where
MEC: IsLessOrEqual<SIZE::UIntMaxValueAsType, Output = True>,
{
Self(t, UnsafeCell::new(SIZE::MIN), PhantomData)
pub const fn new(t: T) -> Self {
Self(t, Cell::new(<MEC as ChooseMinimallyRepresentableUInt>::MIN))
}

pub fn new_with(f: impl FnOnce() -> T) -> Self
where
MEC: IsLessOrEqual<SIZE::UIntMaxValueAsType, Output = True>,
{
Self(f(), UnsafeCell::new(SIZE::MIN), PhantomData)
pub fn new_with(f: impl FnOnce() -> T) -> Self {
Self(
f(),
Cell::new(<MEC as ChooseMinimallyRepresentableUInt>::MIN),
)
}

pub fn exposure_count(&self) -> &SIZE::Type {
// SAFETY: The function only returns a shared reference (&usize) to the exposure count.
// It does not allow mutable access to the exposure count directly.
// This means that while external code can observe the exposure count, it cannot modify it directly.
unsafe { &*self.1.get() }
pub fn exposure_count(&self) -> <MEC as ChooseMinimallyRepresentableUInt>::Output {
self.1.get()
}
}

impl<
'secret,
#[cfg(feature = "zeroize")] T: Zeroize,
#[cfg(not(feature = "zeroize"))] T,
MEC: Unsigned,
SIZE: traits::MinimallyRepresentableUInt,
> traits::RTExposeSecret<'secret, &'secret T, SIZE> for RTSecret<T, MEC, SIZE>
MEC: ChooseMinimallyRepresentableUInt + Unsigned,
> traits::RTExposeSecret<'secret, &'secret T, MEC> for RTSecret<T, MEC>
{
type Exposed<'brand> = RTExposedSecret<'brand, &'brand T>
where
Expand All @@ -88,30 +75,29 @@ impl<
fn try_expose_secret<ReturnType, ClosureType>(
&self,
scope: ClosureType,
) -> Result<ReturnType, error::ExposeSecretError<SIZE>>
) -> Result<ReturnType, error::ExposeSecretError<MEC>>
where
for<'brand> ClosureType: FnOnce(RTExposedSecret<'brand, &'brand T>) -> ReturnType,
{
// SAFETY: All tuple fields of `RTSecret` are private, there are no setter to them.
// `RTSecret` is also not `Sync` so it is not possible to have multithreading race condition.
let ec_mut = unsafe { &mut *self.1.get() };
let mec = SIZE::cast_unsigned_to_self_type::<MEC>(__private::SealedToken {});
let ec_mut = unsafe { &mut *self.1.as_ptr() };
let mec = MEC::cast_unsigned_to_self_type::<MEC>(__private::SealedToken {});
if *ec_mut >= mec {
return Err(error::ExposeSecretError::ExposeMoreThanMaximallyAllow(
error::ExposeMoreThanMaximallyAllowError { mec, ec: *ec_mut },
));
};
*ec_mut += SIZE::ONE;
*ec_mut += MEC::ONE;
Ok(scope(RTExposedSecret(&self.0, PhantomData)))
}
}

impl<
#[cfg(feature = "zeroize")] T: Zeroize,
#[cfg(not(feature = "zeroize"))] T,
MEC: Unsigned,
SIZE: traits::MinimallyRepresentableUInt,
> Drop for RTSecret<T, MEC, SIZE>
MEC: ChooseMinimallyRepresentableUInt + Unsigned,
> Drop for RTSecret<T, MEC>
{
fn drop(&mut self) {
#[cfg(feature = "zeroize")]
Expand All @@ -129,8 +115,8 @@ mod tests {
expected = "`RTSecret` has already been exposed for 255 times, the maximum number it is allowed to be exposed for is 255 times."
)]
fn test_usize_max_expose_secret() {
use typenum::{U255, U8};
let mut secret_one = RTSecret::<isize, U255, U8>::new(69);
use typenum::U255;
let mut secret_one = RTSecret::<isize, U255>::new(69);
*secret_one.1.get_mut() = u8::MAX - 6;

for _ in 0..=5 {
Expand All @@ -139,7 +125,7 @@ mod tests {
});
}

assert_eq!(secret_one.exposure_count(), &u8::MAX);
assert_eq!(secret_one.exposure_count(), u8::MAX);

let _ = secret_one.expose_secret(|exposed_secret| {
assert_eq!(*exposed_secret, 69);
Expand Down
6 changes: 3 additions & 3 deletions src/runtime/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use core::{

pub use crate::runtime::error;

use crate::traits::__private;
use crate::traits::{ChooseMinimallyRepresentableUInt, __private};
use typenum::Unsigned;

pub trait RTExposeSecret<'secret, T, SIZE: MinimallyRepresentableUInt> {
pub trait RTExposeSecret<'secret, T, MEC: ChooseMinimallyRepresentableUInt> {
type Exposed<'brand>
where
'secret: 'brand;
Expand All @@ -21,7 +21,7 @@ pub trait RTExposeSecret<'secret, T, SIZE: MinimallyRepresentableUInt> {
fn try_expose_secret<ReturnType, ClosureType>(
&self,
scope: ClosureType,
) -> Result<ReturnType, error::ExposeSecretError<SIZE>>
) -> Result<ReturnType, error::ExposeSecretError<MEC>>
where
for<'brand> ClosureType: FnOnce(Self::Exposed<'brand>) -> ReturnType;
}
Expand Down
23 changes: 19 additions & 4 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::macros::impl_choose_int;
use core::{
cmp::PartialOrd,
fmt::{Debug, Display},
hash::Hash,
ops::{Add, AddAssign},
};
use typenum::{IsLessOrEqual, Sum, True, Unsigned, U1};
Expand Down Expand Up @@ -159,16 +160,30 @@ mod debug_secret {
);
}

pub trait ChooseMinimallyRepresentableUInt: __private::SealedTrait {
type Output: AddAssign
+ PartialOrd
+ Debug
+ Display
+ Copy
+ Eq
+ Ord
+ PartialOrd
+ Clone
+ Hash
+ Default;
const MIN: Self::Output;
const ONE: Self::Output;

fn cast_unsigned_to_self_type<T: Unsigned>(_: __private::SealedToken) -> Self::Output;
}

pub(crate) mod __private {

pub struct SealedToken {}
pub trait SealedTrait {}
}

pub trait ChooseMinimallyRepresentableUInt: __private::SealedTrait {
type Output: AddAssign + PartialOrd + Debug + Display + Copy;
}

impl_choose_int! {
B00 => u8;
B01 => u8;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ error[E0603]: module `__private` is private
note: the module `__private` is defined here
--> src/runtime/traits.rs
|
| use crate::traits::__private;
| ^^^^^^^^^^^^^^^^^^^^^^^^
| use crate::traits::{ChooseMinimallyRepresentableUInt, __private};
| ^^^^^^^^^

error[E0277]: the trait bound `A: typenum::sealed::Sealed` is not satisfied
--> trybuild_tests/runtime/cannot_impl_minimally_representable_uints.rs:11:23
Expand Down

0 comments on commit 29212ed

Please sign in to comment.