Skip to content

Instantly share code, notes, and snippets.

@dckc
Created October 18, 2012 17:56
Show Gist options
  • Save dckc/3913762 to your computer and use it in GitHub Desktop.
Save dckc/3913762 to your computer and use it in GitHub Desktop.
sealing in rust
// 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
extern mod std;
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
}
}
}
}
#[cfg(test)]
mod sealing_tests {
#[test]
fn simple_sealing() {
let (s, u) = sealing::mkBrandPair(~"bob");
let sekret = 42;
match u.unseal(s.seal(sekret)) {
Some(_) => (),
None => fail
}
}
}
mod mint {
pub trait Purse {
pure fn getBalance() -> int;
pure fn sprout() -> Purse;
fn getDecr() -> @sealing::SealedBox<Decr>;
fn deposit(amt: int, src: Purse);
}
type Decr = @fn(amt: int);
struct PurseImpl {
mint: @MintImpl, // lexical scope would have been nicer...
balance_slot: @mut int,
decr: Decr
}
impl PurseImpl: Purse {
pure fn getBalance() -> int { *self.balance_slot }
pure fn sprout() -> @Purse {
self.mint.makePurse(0)
}
fn getDecr() -> @sealing::SealedBox<Decr> {
self.mint.sealer.seal(self.decr)
}
fn deposit(amount: int, src: Purse) {
assert amount > 0;
match self.mint.unsealer.unseal(src.getDecr()) {
Some(d) => d(amount),
None => fail
}
}
}
pub trait Mint {
pure fn makePurse(balance: int) -> @Purse;
}
struct MintImpl {
name: ~str,
sealer: @sealing::Sealer<Decr>,
unsealer: @sealing::Unsealer<Decr>
}
impl MintImpl: Mint {
pure fn makePurse(balance: int) -> @Purse {
assert balance >= 0;
let bslot: @mut int = @mut balance;
let decr = |amt: int| {
assert amt <= *bslot; // or use Result type?
*bslot -= amt
};
@PurseImpl {
mint: @copy self,
balance_slot: bslot,
decr: decr
} as @Purse
}
}
pub pure fn makeMint(name: ~str) -> @Mint {
let (sealer, unsealer) = sealing::mkBrandPair(copy name);
MintImpl {
name: name, sealer: sealer, unsealer: unsealer
} as @Mint
}
}
#[cfg(test)]
mod money_tests {
#[test]
fn ode() {
let carolMint = mint::makeMint(~"Carol");
let aliceMainPurse = carolMint.makePurse(1000);
assert aliceMainPurse.getBalance() == 1000;
let bobMainPurse = carolMint.makePurse(0);
assert bobMainPurse.getBalance() == 0;
bobMainPurse.deposit(10, aliceMainPurse);
assert bobMainPurse.getBalance() == 10;
assert aliceMainPurse.getBalance() == 990;
}
#[test]
fn illegal_balance() {
let carolMint = mint::makeMint(~"Carol");
let bad1 = carolMint.makePurse(-5);
match bad1.getBalance() {
_ => ()
}
}
}
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!")
}
}
@dckc
Copy link
Author

dckc commented Oct 18, 2012

rustc money.rs
money.rs:15:9: 15:29 error: cannot determine a type for this bounded type parameter: unconstrained type
money.rs:15 (sealer as @sealer, unsealer as @Unsealer)
^~~~~~~~~~~~~~~~~~~~
make: *** [money] Error 101

@dckc
Copy link
Author

dckc commented Oct 19, 2012

now I'm getting an Illegal instruction, though I haven't used any unsafe stuff:

rustc money.rs --test
./money

running 3 tests
make: *** [test] Illegal instruction (core dumped)

@amuxtux
Copy link

amuxtux commented Nov 14, 2012

i also have same problem. I am trying to pass a function pointer to my c code, so that c code give a callback.
when c code tries to execute the callback it gives illegal instruction error. Can any body post a simple example of passing function pointers to c code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment