Python-style function decorators for Rust
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
tests
.gitignore
.travis.yml
Cargo.toml
README.md

README.md

rust-adorn

Build Status

Python-style function decorators for Rust

Example usage:

#![feature(plugin, custom_attribute)]
#![plugin(adorn)]

#[adorn(bar)]
fn foo(a: &mut u8, b: &mut u8, (c, _): (u8, u8)) {
    assert!(c == 4);
    *a = c;
    *b = c;
}


fn bar<F>(f: F, a: &mut u8, b: &mut u8, (c, d): (u8, u8)) where F: Fn(&mut u8, &mut u8, (u8, u8)) {
    assert!(c == 0 && d == 0);
    f(a, b, (4, 0));
    *b = 100;
}

fn main() {
    let mut x = 0;
    let mut y = 1;
    foo(&mut x, &mut y, (0, 0));
    assert!(x == 4 && y == 100);
}

In this case, foo will become:

fn foo(a: &mut u8, b: &mut u8, (c, d): (u8, u8)) {
    fn foo_inner(a: &mut u8, b: &mut u8, (c, _): (u8, u8)) {
        assert!(c == 4);
        *a = c;
        *b = c;
    }
    bar(foo_inner, a, b, (c, d))
}

In other words, calling foo() will actually call bar() wrapped around foo().

There is a #[make_decorator] attribute to act as sugar for creating decorators. For example,

#[make_decorator(f)]
fn bar(a: &mut u8, b: &mut u8, (c, d): (u8, u8)) {
    assert!(c == 0 && d == 0);
    f(a, b, (4, 0)); // `f` was declared in the `make_decorator` annotation
    *b = 100;
}

desugars to

fn bar<F>(f: F, a: &mut u8, b: &mut u8, (c, d): (u8, u8)) where F: Fn(&mut u8, &mut u8, (u8, u8)) {
    assert!(c == 0 && d == 0);
    f(a, b, (4, 0));
    *b = 100;
}

I intend to add support for decorating impl items and default trait methods too. Also passing arguments to the decorator; though rustc's current metaitem support limits us to strings (varargs are possible though).