Source

coffee-craft / money.rs

// http://dl.rust-lang.org/doc/0.4/tutorial.html#getting-started

// http://www.madmode.com/2011/11/capability-security-in-e-coffescript.html
// http://gitorious.org/repo-roscidus/e-core/blobs/fdf9643e419eea182b4d8d983f5b9955c7b73967/src/jsrc/org/erights/e/elib/sealing/SealedBox.java

use cmp::{Eq};

mod sealing {
    pub struct Brand {
        hint: ~str
    }
    impl @Brand: Eq {
        pure fn eq(other: &@Brand) -> bool { box::ptr_eq(self, *other) }
        pure fn ne(other: &@Brand) -> bool { !box::ptr_eq(self, *other) }
    }

    pub pure fn mkBrandPair<T>(hint: ~str) -> (@Sealer<T>, @Unsealer<T>) {
        let brand = @Brand{ hint: copy hint };
        let sealer = @SealerImpl{brand: brand};
        let unsealer = @UnsealerImpl{brand: brand};
        (sealer as @Sealer<T>, unsealer as @Unsealer<T>)
    }
    
    pub struct SealedBox<T: Copy> {
        priv contents: T,
        brand: @Brand
    }

    impl<T: Copy> SealedBox<T>: ToStr {
        pure fn to_str() -> ~str { ~"<sealed by " + self.brand.hint + ~">" }
    }

    pub trait Sealer<T: Copy> {
        pure fn seal(it: T) -> @SealedBox<T>;
        pure fn getBrand() -> @Brand;
    }

    pub impl<T: Copy> Sealer<T> : ToStr {
        pure fn to_str() -> ~str {
            ~"<sealer for " + self.getBrand().hint + ~">"
        }
    }


    struct SealerImpl { brand: @Brand }
    impl<T: Copy> SealerImpl: Sealer<T> {
        pure fn seal(it: T) -> @SealedBox<T> {
            @SealedBox{contents: it, brand: self.brand }
        }
        pure fn getBrand() -> @Brand { self.brand }
    }

    pub trait Unsealer<T: Copy> {
        fn unseal(box: @SealedBox<T>) -> Option<T>;  // todo: consider Result
    }

    struct UnsealerImpl { brand: @Brand }
    impl<T: Copy> UnsealerImpl: Unsealer<T> {
        fn unseal(box: @SealedBox<T>) -> Option<T> {
            if (self.brand == box.brand) { Some(box.contents) }
            else { 
                // TODO: throw new UnsealingException("" + this + " can't unseal " + box);
                None
            }
        }
    }

}

fn main() {
    let (s, u) = sealing::mkBrandPair(~"bob");
    let sekret = 42;
    match u.unseal(s.seal(sekret)) {
      Some(i) => io::println(~"seal, unseal: " + i.to_str()),
      None => io::println("lose!")
    }
}