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

Update fold #64

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions alohomora/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions alohomora/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ itertools = "0.12.1"
[dev-dependencies]
tokio = "1.37.0"
tokio-test = "0.4.0"
static_assertions = "1.1.0"

[dependencies.rocket_dyn_templates]
git = "https://github.com/KinanBab/Rocket.git"
Expand Down
30 changes: 0 additions & 30 deletions alohomora/src/bbox/bbox_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::bbox::obfuscated_pointer::ObPtr;

// Privacy Container type.
pin_project! {
#[derive(Debug, PartialEq)]
pub struct BBox<T, P: Policy> {
#[pin]
fb: ObPtr<T>,
Expand Down Expand Up @@ -189,35 +188,6 @@ impl<T> BBox<T, AnyPolicy> {
}
}

// NoPolicy can be discarded, logged, etc
impl<T> BBox<T, NoPolicy> {
pub fn discard_box(self) -> T {
self.fb.mov()
}
}

// Same but for RefPolicy<NoPolicy>
impl<'a, T> BBox<&'a T, RefPolicy<'a, NoPolicy>> {
pub fn discard_box(self) -> &'a T {
self.fb.mov()
}
}

// Transpose
impl<T, E, P: Policy> BBox<Result<T, E>, P> {
pub fn transpose(self) -> Result<BBox<T, P>, E> {
let (t, p) = self.consume();
Ok(BBox::new(t?, p))
}
}

impl<T, P: Policy> BBox<Option<T>, P> {
pub fn transpose(self) -> Option<BBox<T, P>> {
let (t, p) = self.consume();
Some(BBox::new(t?, p))
}
}

impl<'a, T: Future + Unpin, P: Policy + Clone> Future for BBox<T, P> {
type Output = BBox<T::Output, P>;

Expand Down
9 changes: 7 additions & 2 deletions alohomora/src/bbox/obfuscated_pointer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use std::future::Future;
use std::pin::Pin;
use std::task::Poll;
use std::boxed::Box;
use std::fmt::Debug;
use std::marker::PhantomData;

// Secret to XOR with.
const secret: usize = 2238711266;

#[derive(Debug)]
pub struct ObPtr<T> {
ptr: usize,
_marker: PhantomData<T>
Expand Down Expand Up @@ -54,7 +54,7 @@ impl<T> Drop for ObPtr<T> {
}
}

// Cloneable if whats underneath is cloneable.
// Cloneable if what's underneath is cloneable.
impl<T: Clone> Clone for ObPtr<T> {
fn clone(&self) -> Self {
unsafe {
Expand All @@ -69,6 +69,11 @@ impl<T: PartialEq> PartialEq for ObPtr<T> {
self.get() == other.get()
}
}
impl<T: Debug> Debug for ObPtr<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
self.get().fmt(f)
}
}

// Can poll on futures inside ObPtr.
impl<'a, T: Future + Unpin> Future for ObPtr<T> {
Expand Down
12 changes: 2 additions & 10 deletions alohomora/src/fold.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use itertools::Itertools;
use crate::AlohomoraType;
use crate::bbox::BBox;
use crate::bbox::{BBox};
use crate::policy::{AnyPolicy, NoPolicy, OptionPolicy, Policy};

pub fn fold<S: AlohomoraType>(s: S) -> Result<BBox<S::Out, AnyPolicy>, ()> {
Expand Down Expand Up @@ -88,14 +88,6 @@ optimized_tup_fold!([T1, P1], [T2, P2], [T3, P3], [T4, P4], [T5, P5], [T6, P6]);
optimized_tup_fold!([T1, P1], [T2, P2], [T3, P3], [T4, P4], [T5, P5], [T6, P6], [T7, P7]);
optimized_tup_fold!([T1, P1], [T2, P2], [T3, P3], [T4, P4], [T5, P5], [T6, P6], [T7, P7], [T8, P8]);

// Fold bbox from outside vector to inside vector.
impl<T, P: Policy + Clone> From<BBox<Vec<T>, P>> for Vec<BBox<T, P>> {
fn from(x: BBox<Vec<T>, P>) -> Vec<BBox<T, P>> {
let (t, p) = x.consume();
t.into_iter().map(|t| BBox::new(t, p.clone())).collect()
}
}

// Fold bbox from inside vector to the outside. Same as generic fold(...) but preserves policy type.
impl<T, P: Policy + Clone> From<Vec<BBox<T, P>>> for BBox<Vec<T>, OptionPolicy<P>> {
fn from(v: Vec<BBox<T, P>>) -> BBox<Vec<T>, OptionPolicy<P>> {
Expand Down Expand Up @@ -270,7 +262,7 @@ mod tests {
assert_eq!(bbox.clone().discard_box(), vec![10, 20, 30]);

// inverse fold for vector.
let vec: Vec<BBox<i32, TestPolicy<ACLPolicy>>> = Vec::from(bbox);
let vec: Vec<BBox<i32, TestPolicy<ACLPolicy>>> = bbox.fold_in();
assert_eq!(vec[0].policy().policy().owners, HashSet::from_iter([40]));
assert_eq!(vec[1].policy().policy().owners, HashSet::from_iter([40]));
assert_eq!(vec[2].policy().policy().owners, HashSet::from_iter([40]));
Expand Down
169 changes: 169 additions & 0 deletions alohomora/src/fold_in/impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
use crate::policy::Policy;
use crate::bbox::BBox;

use crate::fold_in::{FoldInAllowed, RuntimeFoldIn};


// Fold PCon from outside vector to inside vector.
impl<T, P: Policy + FoldInAllowed + Clone> BBox<Vec<T>, P> {
pub fn fold_in(self) -> Vec<BBox<T, P>> {
if !self.policy().can_fold_in() {
panic!("fold_in called on policy with folding disallowed");
}
let (t, p) = self.consume();
t.into_iter().map(|t| BBox::new(t, p.clone())).collect()
}
}

impl<T, E, P: Policy + FoldInAllowed + Clone> BBox<Result<T, E>, P> {
pub fn fold_in(self) -> Result<BBox<T, P>, E> {
if !self.policy().can_fold_in() {
panic!("fold_in called on policy with folding disallowed");
}
let (t, p) = self.consume();
Ok(BBox::new(t?, p))
}
}

impl<T, P: Policy + FoldInAllowed + Clone> BBox<Option<T>, P> {
pub fn fold_in(self) -> Option<BBox<T, P>> {
if !self.policy().can_fold_in() {
panic!("fold_in called on policy with folding disallowed");
}
let (t, p) = self.consume();
Some(BBox::new(t?, p))
}
}

// Unit tests.
#[cfg(test)]
mod tests {
use crate::policy::{AnyPolicy, NoPolicy, Policy, RefPolicy, PolicyAnd, PolicyOr, OptionPolicy, Reason};
use crate::bbox::BBox;
use crate::context::UnprotectedContext;
use crate::fold_in::{FoldInAllowed, RuntimeFoldIn};

#[derive(Clone, Debug, PartialEq, Eq)]
struct NoFoldPolicy {}

impl !FoldInAllowed for NoFoldPolicy{}

impl Policy for NoFoldPolicy {
fn name(&self) -> String {
String::from("NoFoldPolicy")
}
fn check(&self, _context: &UnprotectedContext, _reason: Reason) -> bool {
true
}
fn join(&self, _other: AnyPolicy) -> Result<AnyPolicy, ()> {
Ok(AnyPolicy::new(self.clone()))
}
fn join_logic(&self, _other: Self) -> Result<Self, ()> {
Ok(NoFoldPolicy {})
}
}

/// These tests ensure that we can fold in on foldable policies, including ones hiding
/// behind refs, options, etc.
#[test]
fn test_fold_in_allowed() {
let pcon: BBox<Option<u64>, NoPolicy> = BBox::new(Some(10u64), NoPolicy {});
assert_eq!(true, pcon.policy().can_fold_in());
let opt: Option<BBox<u64, NoPolicy>> = pcon.fold_in();
assert_eq!(opt.clone().unwrap(), BBox::new(10u64, NoPolicy {}));
assert_eq!(opt.unwrap().discard_box(), 10u64);

let pcon: BBox<Result<u64, ()>, NoPolicy> = BBox::new(Ok(10u64), NoPolicy {});
assert_eq!(true, pcon.policy().can_fold_in());
let res: Result<BBox<u64, NoPolicy>, ()> = pcon.fold_in();
assert_eq!(res.clone().unwrap(), BBox::new(10u64, NoPolicy {}));
assert_eq!(res.unwrap().discard_box(), 10u64);

let pcon: BBox<Vec<u64>, NoPolicy> = BBox::new(vec![10u64, 20u64], NoPolicy {});
assert_eq!(true, pcon.policy().can_fold_in());
let vec: Vec<BBox<u64, NoPolicy>> = pcon.fold_in();
assert_eq!(&vec[0], &BBox::new(10u64, NoPolicy {}));
assert_eq!(&vec[1], &BBox::new(20u64, NoPolicy {}));
assert_eq!(vec.len(), 2);
}

#[test]
fn test_fold_in_allowed_any_policy() {
let pcon: BBox<Vec<u64>, NoPolicy> = BBox::new(vec![10u64, 11u64, 12u64], NoPolicy {} );
let pcon = pcon.into_any_policy();
assert_eq!(true, pcon.policy().can_fold_in());
let vec: Vec<BBox<u64, AnyPolicy>> = pcon.fold_in();
assert_eq!(vec.len(), 3);
assert_eq!(vec[0].clone().specialize_policy().unwrap(), BBox::new(10u64, NoPolicy {}));
assert_eq!(vec[1].clone().specialize_policy().unwrap(), BBox::new(11u64, NoPolicy {}));
assert_eq!(vec[2].clone().specialize_policy().unwrap(), BBox::new(12u64, NoPolicy {}));
}

#[test]
fn test_fold_in_allowed_any_policy_complex() {
let policy = AnyPolicy::new(NoPolicy {});
let refpolicy = RefPolicy::new(&policy);
let pcon: BBox<Vec<u64>, RefPolicy<AnyPolicy>> = BBox::new(vec![10u64, 11u64, 12u64], refpolicy);

assert_eq!(true, pcon.policy().can_fold_in());
let vec: Vec<BBox<u64, RefPolicy<AnyPolicy>>> = pcon.fold_in();
assert_eq!(vec.len(), 3);
assert_eq!(vec[0].clone().to_owned_policy().specialize_policy().unwrap(), BBox::new(10u64, NoPolicy {}));
assert_eq!(vec[1].clone().to_owned_policy().specialize_policy().unwrap(), BBox::new(11u64, NoPolicy {}));
assert_eq!(vec[2].clone().to_owned_policy().specialize_policy().unwrap(), BBox::new(12u64, NoPolicy {}));
}

#[test]
#[should_panic]
fn test_fold_in_not_allowed_any_policy() {
let pcon: BBox<Vec<u64>, NoFoldPolicy> = BBox::new(vec![10u64], NoFoldPolicy { });
let pcon = pcon.into_any_policy();
let _vec_of_pcon: Vec<BBox<u64, AnyPolicy>> = pcon.fold_in(); // correctly panics
}

#[test]
#[should_panic]
fn test_fold_in_not_allowed_any_policy_complex() {
let policy =
AnyPolicy::new(PolicyAnd::new(NoFoldPolicy {}, NoFoldPolicy {}));
let refpolicy= RefPolicy::new(&policy);

let pcon: BBox<Vec<u64>, _> = BBox::new(vec![10u64], refpolicy);
let _vec_of_pcon: Vec<BBox<u64, _>> = pcon.fold_in(); // correctly panics
}

#[test]
fn test_ref_policy_yes_foldin() {
let policy = NoPolicy {};
let pcon = BBox::new(Some(1064), RefPolicy::new(&policy));
assert_eq!(pcon.policy().can_fold_in(), true);
let opt = pcon.fold_in();
assert_eq!(BBox::new(1064, RefPolicy::new(&policy)), opt.unwrap());
}

#[test]
fn test_and_policy_yes_foldin() {
let pcon_of_vec: BBox<Vec<u64>, PolicyAnd<NoPolicy, NoPolicy>> = BBox::new(vec![10u64, 11u64, 12u64], PolicyAnd::new(NoPolicy {}, NoPolicy {}));
assert_eq!(pcon_of_vec.policy().can_fold_in(), true);
let vec_of_pcon: Vec<BBox<u64, _>> = pcon_of_vec.fold_in();
assert_eq!(vec_of_pcon.len(), 3);
}

#[test]
fn test_or_policy_yes_foldin() {
let pcon_of_vec: BBox<Vec<u64>, PolicyOr<NoPolicy, NoPolicy>> = BBox::new(vec![10u64, 11u64, 12u64], PolicyOr::new(NoPolicy {}, NoPolicy {}));
assert_eq!(pcon_of_vec.policy().can_fold_in(), true);
let vec_of_pcon: Vec<BBox<u64, _>> = pcon_of_vec.fold_in();
assert_eq!(vec_of_pcon.len(), 3);
}


#[test]
fn test_option_policy_yes_foldin() {
let pcon_of_vec: BBox<Vec<u64>, OptionPolicy<NoPolicy>> = BBox::new(vec![10u64, 11u64, 12u64], OptionPolicy::Policy(NoPolicy {}));
assert_eq!(pcon_of_vec.policy().can_fold_in(), true);
let vec_of_pcon: Vec<BBox<u64, _>> = pcon_of_vec.fold_in();
assert_eq!(vec_of_pcon.len(), 3);
}

}
5 changes: 5 additions & 0 deletions alohomora/src/fold_in/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod impls;
mod traits;

pub use impls::*;
pub use traits::*;
Loading