Created
October 18, 2012 17:56
-
-
Save dckc/3913762 to your computer and use it in GitHub Desktop.
sealing in rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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!") | |
} | |
} |
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)
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
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