<commit_before>extern crate regex;

use colored::*;
use regex::RegexSet;
use nom::IResult;
use std::path::PathBuf;

/// Given a darcs boring file's contents, process it as a `RegexSet`. The second
/// argument is a file path, included so that we print nice errors.
pub fn darcs_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {

    let processed_vec: Vec<&str> = process_darcs_full(file, file_path);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    } else {
        eprintln!(
            "{}: failed to parse darcs boring file at {:?}, ignoring",
            "Warning".yellow(),
            file_path
        );
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty).expect("Error creating regex from empty vector")
    }

}

/// Given a `.gitignore` or `.ignore` file's contents, process it as a `RegexSet`. The second
/// argument is a file path, included so that we print nice errors.
pub fn file_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {
    let processed_vec: Vec<&str> = process_to_vector(file, file_path);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    } else {
        eprintln!(
            "{}: failed to parse .gitignore/.ignore at {:?}, ignoring",
            "Warning".yellow(),
            file_path
        );
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty).expect("Error creating regex from empty vector")
    }
}

fn process_to_vector<'a>(input: &'a str, file_path: &PathBuf) -> Vec<&'a str> {
    match process(input) {
        IResult::Done(_, result) => result,
        _ => {
            eprintln!(
                "{}: Failed to parse gitignore at: {}",
                "Error".red(),
                file_path.display()
            );
            Vec::new()
        }
    }
}

fn process_darcs_full<'a>(input: &'a str, file_path: &PathBuf) -> Vec<&'a str> {
    match process_darcs(input) {
        IResult::Done(_, result) => result,
        _ => {
            eprintln!(
                "{}: Failed to parse darcs boring file at: {}",
                "Error".red(),
                file_path.display()
            );
            Vec::new()
        }
    }
}

named!(process_darcs<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(darcs) >>
        (r)
    )
);

named!(process<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(options) >>
        (r)
    )
);

named!(darcs<&str, &str>,
    alt!(
        tag!("\n") |
        gitignore_comment |
        is_not!("\\#") |
        parse_backslash |
        parse_not_comment
    )
);

named!(line<&str, &str>,
    do_parse!(
        tag!("\n") >>
        ("$\n")
    )
);

named!(options<&str, &str>,
    alt!(
        line |
        gitignore_comment |
        is_not!("*?.#\n") |
        parse_asterix |
        parse_period |
        parse_questionmark |
        parse_not_comment
    )
);

named!(parse_not_comment<&str, &str>,
    do_parse!(
        is_not!("\n") >>
        ("#")
    )
);

named!(first_line<&str, &str>,
    do_parse!(
        tag!("#") >>
        is_not!("\n") >>
        tag!("\n") >>
        ("\n")
    )
);

named!(gitignore_comment<&str, &str>,
    do_parse!(
        tag!("\n#") >>
        is_not!("\n") >>
        ("\n")
    )
);

named!(parse_period<&str, &str>,
    do_parse!(
        tag!(".") >>
        ("\\.")
    )
);

named!(parse_backslash<&str, &str>,
    do_parse!(
        val: alt!(
            do_parse!(tag!("\\_") >> ("_")) |
            do_parse!(tag!("\\") >> ("\\"))
            ) >>
        (val)
    )
);

named!(parse_asterix<&str, &str>,
    do_parse!(
        tag!("*") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".*")
    )
);

named!(parse_questionmark<&str, &str>,
    do_parse!(
        tag!("?") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".")
    )
);
<commit_msg>bugfix<commit_after>extern crate regex;

use colored::*;
use regex::RegexSet;
use nom::IResult;
use std::path::PathBuf;

/// Given a darcs boring file's contents, process it as a `RegexSet`. The second
/// argument is a file path, included so that we print nice errors.
pub fn darcs_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {

    let processed_vec: Vec<&str> = process_darcs_full(file, file_path);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    } else {
        eprintln!(
            "{}: failed to parse darcs boring file at {:?}, ignoring",
            "Warning".yellow(),
            file_path
        );
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty).expect("Error creating regex from empty vector")
    }

}

/// Given a `.gitignore` or `.ignore` file's contents, process it as a `RegexSet`. The second
/// argument is a file path, included so that we print nice errors.
pub fn file_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {
    let processed_vec: Vec<&str> = process_to_vector(file, file_path);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    let maybe_set = RegexSet::new(lines.clone());
    if let Ok(s) = maybe_set {
        s
    } else {
        println!("{:?}", lines.collect::<Vec<&str>>());
        println!("{:?}", maybe_set);
        eprintln!(
            "{}: failed to parse .gitignore/.ignore at {:?}, ignoring",
            "Warning".yellow(),
            file_path
        );
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty).expect("Error creating regex from empty vector")
    }
}

fn process_to_vector<'a>(input: &'a str, file_path: &PathBuf) -> Vec<&'a str> {
    match process(input) {
        IResult::Done(_, result) => result,
        _ => {
            eprintln!(
                "{}: Failed to parse gitignore at: {}",
                "Error".red(),
                file_path.display()
            );
            Vec::new()
        }
    }
}

fn process_darcs_full<'a>(input: &'a str, file_path: &PathBuf) -> Vec<&'a str> {
    match process_darcs(input) {
        IResult::Done(_, result) => result,
        _ => {
            eprintln!(
                "{}: Failed to parse darcs boring file at: {}",
                "Error".red(),
                file_path.display()
            );
            Vec::new()
        }
    }
}

named!(process_darcs<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(darcs) >>
        (r)
    )
);

named!(process<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(options) >>
        (r)
    )
);

named!(darcs<&str, &str>,
    alt!(
        tag!("\n") |
        gitignore_comment |
        is_not!("\\#") |
        parse_backslash |
        parse_not_comment
    )
);

named!(line<&str, &str>,
    do_parse!(
        tag!("\n") >>
        ("$\n")
    )
);

named!(options<&str, &str>,
    alt!(
        line |
        gitignore_comment |
        is_not!("*?+.#\n") |
        parse_asterix |
        parse_period |
        parse_questionmark |
        parse_plus |
        parse_not_comment
    )
);

named!(parse_not_comment<&str, &str>,
    do_parse!(
        is_not!("\n") >>
        ("#")
    )
);

named!(first_line<&str, &str>,
    do_parse!(
        tag!("#") >>
        is_not!("\n") >>
        tag!("\n") >>
        ("\n")
    )
);

named!(gitignore_comment<&str, &str>,
    do_parse!(
        tag!("\n#") >>
        is_not!("\n") >>
        ("\n")
    )
);

named!(parse_plus<&str, &str>,
   do_parse!(
       tag!("+") >>
       ("\\+")
   )
);

named!(parse_period<&str, &str>,
    do_parse!(
        tag!(".") >>
        ("\\.")
    )
);

named!(parse_backslash<&str, &str>,
    do_parse!(
        val: alt!(
            do_parse!(tag!("\\_") >> ("_")) |
            do_parse!(tag!("\\") >> ("\\"))
            ) >>
        (val)
    )
);

named!(parse_asterix<&str, &str>,
    do_parse!(
        tag!("*") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".*")
    )
);

named!(parse_questionmark<&str, &str>,
    do_parse!(
        tag!("?") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".")
    )
);
<|endoftext|>


<commit_before>use core::cell::Cell;
use alarm::{Alarm, AlarmClient};

pub trait Timer {
    fn now(&self) -> u32;
    //fn cancel(&mut self, request: TimerRequest);
    fn oneshot(&self, interval: u32);
    fn repeat(&self, interval: u32);
}

pub trait TimerClient {
    fn fired(&self, now: u32);
}

pub struct SingleTimer<'a, Alrm: Alarm + 'a> {
    interval: Cell<u32>,
    when: Cell<u32>,
    repeat: Cell<bool>,
    alarm: &'a Alrm,
    client: Cell<Option<&'a TimerClient>>
}

unsafe impl<'a, A: Alarm + 'a> Sync for SingleTimer<'a, A> {}

impl<'a, Alrm: Alarm> SingleTimer<'a, Alrm> {
    pub const fn new(alarm: &'a Alrm) -> SingleTimer<'a, Alrm> {
        SingleTimer {
            interval: Cell::new(0),
            when: Cell::new(0),
            repeat: Cell::new(false),
            alarm: alarm,
            client: Cell::new(None)
        }
    }

    pub fn set_client(&self, client: &'a TimerClient) {
        self.client.set(Some(client));
    }
}

impl<'a, Alrm: Alarm> Timer for SingleTimer<'a, Alrm> {
    fn now(&self) -> u32 {
        self.alarm.now()
    }

    fn oneshot(&self, interval: u32) {
        let when = interval.wrapping_add(self.alarm.now());

        self.when.set(when);

        self.interval.set(interval);
        self.repeat.set(false);

        self.alarm.set_alarm(when);
    }

    fn repeat(&self, interval: u32) {
        let when = interval.wrapping_add(self.alarm.now());

        self.when.set(when);

        self.interval.set(interval);
        self.repeat.set(true);

        self.alarm.set_alarm(when);
    }
}

impl<'a, Alrm: Alarm> AlarmClient for SingleTimer<'a, Alrm> {
    fn fired(&self) {
        let now = self.now();
        let repeat = self.repeat.get();
        if repeat {
            let interval = self.interval.get();
            let when = interval.wrapping_add(now);

            self.when.set(when);

            self.alarm.set_alarm(when);
        } else {
            self.alarm.disable_alarm();
        }
        self.client.get().map(|client| client.fired(now) );
    }
}

<commit_msg>Virtualized alarm<commit_after>use core::cell::Cell;
use alarm::{Alarm, AlarmClient};

pub trait Timer {
    fn now(&self) -> u32;
    //fn cancel(&mut self, request: TimerRequest);
    fn oneshot(&self, interval: u32);
    fn repeat(&self, interval: u32);
}

pub trait TimerClient {
    fn fired(&self, now: u32);
}

pub struct SingleTimer<'a, Alrm: Alarm + 'a> {
    interval: Cell<u32>,
    when: Cell<u32>,
    repeat: Cell<bool>,
    alarm: &'a Alrm,
    client: Cell<Option<&'a TimerClient>>
}

unsafe impl<'a, A: Alarm + 'a> Sync for SingleTimer<'a, A> {}

impl<'a, Alrm: Alarm> SingleTimer<'a, Alrm> {
    pub const fn new(alarm: &'a Alrm) -> SingleTimer<'a, Alrm> {
        SingleTimer {
            interval: Cell::new(0),
            when: Cell::new(0),
            repeat: Cell::new(false),
            alarm: alarm,
            client: Cell::new(None)
        }
    }

    pub fn set_client(&self, client: &'a TimerClient) {
        self.client.set(Some(client));
    }
}

impl<'a, Alrm: Alarm> Timer for SingleTimer<'a, Alrm> {
    fn now(&self) -> u32 {
        self.alarm.now()
    }

    fn oneshot(&self, interval: u32) {
        let when = interval.wrapping_add(self.alarm.now());

        self.when.set(when);

        self.interval.set(interval);
        self.repeat.set(false);

        self.alarm.set_alarm(when);
    }

    fn repeat(&self, interval: u32) {
        let when = interval.wrapping_add(self.alarm.now());

        self.when.set(when);

        self.interval.set(interval);
        self.repeat.set(true);

        self.alarm.set_alarm(when);
    }
}

impl<'a, Alrm: Alarm> AlarmClient for SingleTimer<'a, Alrm> {
    fn fired(&self) {
        let now = self.now();
        let repeat = self.repeat.get();
        if repeat {
            let interval = self.interval.get();
            let when = interval.wrapping_add(now);

            self.when.set(when);

            self.alarm.set_alarm(when);
        } else {
            self.alarm.disable_alarm();
        }
        self.client.get().map(|client| client.fired(now) );
    }
}

pub struct VirtualMuxAlarm<'a, Alrm: Alarm + 'a> {
    alarm: &'a MuxAlarm<'a, Alrm>,
    when: Cell<u32>,
    armed: Cell<bool>,
    next: Cell<Option<&'a VirtualMuxAlarm<'a, Alrm>>>,
    client: Cell<Option<&'a AlarmClient>>
}

impl<'a, Alrm: Alarm> VirtualMuxAlarm<'a, Alrm> {
    pub fn new(mux_alarm: &'a MuxAlarm<'a, Alrm>) -> VirtualMuxAlarm<'a, Alrm> {
        VirtualMuxAlarm {
            alarm: mux_alarm,
            when: Cell::new(0),
            armed: Cell::new(false),
            next: Cell::new(None),
            client: Cell::new(None)
        }
    }

    pub unsafe fn set_client(&'a self, client: &'a AlarmClient) {
        self.next.set(self.alarm.virtual_alarms.get());
        self.alarm.virtual_alarms.set(Some(self));
        self.when.set(0);
        self.armed.set(false);
        self.client.set(Some(client));
    }
}

impl<'a, Alrm: Alarm> Alarm for VirtualMuxAlarm<'a, Alrm> {
    fn now(&self) -> u32 {
        self.alarm.alarm.now()
    }

    fn set_alarm(&self, when: u32) {
        let enabled = self.alarm.enabled.get();
        self.alarm.enabled.set(enabled + 1);
        if enabled == 0 {
            self.alarm.alarm.set_alarm(when);
        }
        self.armed.set(true);
    }

    fn get_alarm(&self) -> u32 {
        self.when.get()
    }

    fn disable_alarm(&self) {
        if !self.armed.get() {
            return;
        }

        self.armed.set(false);

        let enabled = self.alarm.enabled.get() - 1;
        self.alarm.enabled.set(enabled);
        if enabled == 0 {
            self.alarm.alarm.disable_alarm();
        }
    }
}

pub struct MuxAlarm<'a, Alrm: Alarm + 'a> {
    virtual_alarms: Cell<Option<&'a VirtualMuxAlarm<'a, Alrm>>>,
    enabled: Cell<usize>,
    prev: Cell<u32>,
    alarm: &'a Alrm
}

impl<'a, Alrm: Alarm> MuxAlarm<'a, Alrm> {
    pub fn new(alarm: &'a Alrm) -> MuxAlarm<'a, Alrm> {
        MuxAlarm {
            virtual_alarms: Cell::new(None),
            enabled: Cell::new(0),
            prev: Cell::new(0),
            alarm: alarm
        }
    }
}

impl <'a, Alrm: Alarm> AlarmClient for VirtualMuxAlarm<'a, Alrm> {
    fn fired(&self) {
        self.client.get().map(|client| client.fired() );
    }
}

fn in_between(cur: u32, now: u32, prev: u32) -> bool {
    if now >= prev {
        cur <= now && cur >= prev
    } else {
        cur <= prev && cur >= now
    }
}

impl <'a, Alrm: Alarm> AlarmClient for MuxAlarm<'a, Alrm> {
    fn fired(&self) {
        let now = self.alarm.now();
        let mut next = None;
        let mut min_distance : u32 = u32::max_value();
        // We know at least one of the virtual_alarms is armed
        let mut ocur = self.virtual_alarms.get();
        loop {
            match ocur {
                None => break,
                Some(cur) => {
                    let should_fire = in_between(cur.when.get(),
                                                 now, self.prev.get());
                    if cur.armed.get() && should_fire {
                        cur.armed.set(false);
                        cur.fired();
                    } else {
                        let distance = cur.when.get().wrapping_sub(now);
                        if cur.armed.get() && distance < min_distance {
                            min_distance = distance;
                            next = Some(cur);
                        }
                    }
                    ocur = cur.next.get();
                }
            }
        }
        self.prev.set(now);
        match next {
            None => {
                self.alarm.disable_alarm();
            },
            Some(valrm) => {
                self.alarm.set_alarm(valrm.when.get());
            }
        }
    }
}

<|endoftext|>


<commit_before>extern crate hyper;
extern crate tungsten;

use std::thread;
use std::io::Read;
use hyper::status::StatusCode;
use hyper::client::Client;
use tungsten::server::Tungsten;
use tungsten::request::Request;
use tungsten::response::Response;
use tungsten::router::HttpMethods;

fn serve() {
  let _ = thread::Builder::new().name(String::from("test-server")).spawn(move || {
    let mut app = Tungsten::new();
    app.get("/".to_string(), |req: Request, res: Response| {
        res.send(b"Hello World!");
    });
    app.get("/some/random/path".to_string(), |req: Request, res: Response| {
        res.send(b"You are at /some/random/path");
    });
    app.listen("0.0.0.0:4040");
  });
}

#[test]
fn test_hello_world() {
    serve();
    let client = Client::new();
    let mut res = client.get("http://0.0.0.0:4040").send().unwrap();
    let mut body = String::new();
    let _ = res.read_to_string(&mut body);

    assert_eq!(res.status, StatusCode::Ok);
    assert_eq!(body, "Hello World!");
}

#[test]
fn test_some_path() {
    let client = Client::new();
    let mut res = client.get("http://0.0.0.0:4040/some/random/path").send().unwrap();
    let mut body = String::new();
    let _ = res.read_to_string(&mut body);

    assert_eq!(res.status, StatusCode::Ok);
    assert_eq!(body, "You are at /some/random/path");
}
<commit_msg>tests can now run in any order (#22)<commit_after>extern crate hyper;
extern crate tungsten;

use std::thread;
use std::sync::{Once, ONCE_INIT};
use std::io::Read;
use hyper::status::StatusCode;
use hyper::client::Client;
use hyper::client::response::Response as HyperResponse;
use tungsten::server::Tungsten;
use tungsten::request::Request;
use tungsten::response::Response;
use tungsten::router::HttpMethods;

static TEST_INIT: Once = ONCE_INIT;

struct TestContext {
    req_client: Client
}

impl TestContext {
    fn new() ->  TestContext {
        let ctx = TestContext {
            req_client: Client::new()
        };
        TEST_INIT.call_once(|| {
            let _ = thread::spawn(move || {
                let mut app = Tungsten::new();
                app.get("/".to_string(), |req: Request, res: Response| {
                    res.send(b"Hello World!");
                });
                app.get("/some/random/path".to_string(), |req: Request, res: Response| {
                    res.send(b"You are at /some/random/path");
                });
                app.listen("0.0.0.0:4040");
            });
            loop {
                if ctx.req_client.get("http://0.0.0.0:4040").send().is_ok() {
                    break;
                }
            }
        });
        ctx
    }

    fn request(&self, url: &str) -> HyperResponse {
        self.req_client.get(url).send().unwrap()
    }

    fn body_from_response(&self, res: &mut HyperResponse) -> String {
        let mut body = String::new();
        let _ = res.read_to_string(&mut body);
        body
    }
}

#[test]
fn test_hello_world() {
    let ctx = TestContext::new();
    let mut res = ctx.request("http://0.0.0.0:4040");
    let body = ctx.body_from_response(&mut res);

    assert_eq!(res.status, StatusCode::Ok);
    assert_eq!(body, "Hello World!");
}

#[test]
fn test_some_path() {
    let ctx = TestContext::new();
    let mut res = ctx.request("http://0.0.0.0:4040/some/random/path");
    let body = ctx.body_from_response(&mut res);

    assert_eq!(res.status, StatusCode::Ok);
    assert_eq!(body, "You are at /some/random/path");
}
<|endoftext|>


<commit_before>use lisp::lex::{tokenize, parse_form};
use lisp::types::*;
use lisp::env::*;

pub fn eval(ast: RLType, env: &Env) -> RLResult {
    match ast {
        RLType::Symbol(ref name) => env.borrow().lookup(name),
        RLType::List(tokens) => eval_list(tokens, env),
        _ => Ok(ast),
    }
}

// Evaluates the list
// if the first element is a function or keyword, it executes that, otherwise returns
// the list itself
fn eval_list(mut tokens: Vec<RLType>, env: &Env) -> RLResult {
    // empty list -> no action
    if tokens.is_empty() {
        return Ok(RLType::List(tokens));
    }

    let first = tokens.remove(0);

    match first {
        RLType::Symbol(name) => {

            if let Ok(value) = eval_core(&name, &mut tokens, env) {
                return Ok(value);
            }

            eval_proc(&name, tokens, env)
        },
        _ => {
            tokens.insert(0, first);
            Ok(RLType::List(tokens))
        },
    }
}

fn eval_core(keyword: &str, args: &mut Vec<RLType>, env: &Env) -> RLResult {
    match keyword {
        "do" => eval_do(args, env),
        "if" => eval_if(args, env),
        "def!" => eval_def(args, env),
        "lambda" => eval_create_lambda(args, env),
        // "quote" => eval_quote(args),
        _ => error(format!("Not a keyword: {}", keyword)),
    }
}

fn eval_proc(name: &str, tokens: Vec<RLType>, env: &Env) -> RLResult {
    // TODO: this borrow blocks recursion
    // test with: (def! fibo ( lambda (n) (if (< n 2) n (+ (fibo (- n 1)) (fibo (- n 2))))))
    match env.borrow().lookup(name) {
        Ok(RLType::Proc(func)) => {
            // eager eval: each of the arguments is evaluated before calling
            let mut args: Vec<RLType> = Vec::new();
            for arg in tokens {
                match eval(arg, env) {
                    Ok(value) => args.push(value),
                    Err(e) => return Err(e),
                }
            }
            func(args)
        },
        Ok(RLType::Lambda(lambda)) => {
            // TODO: refactor argument evaluation
            let mut args: Vec<RLType> = Vec::new();
            for arg in tokens {
                match eval(arg, env) {
                    Ok(value) => args.push(value),
                    Err(e) => return Err(e),
                }
            }
            eval_exec_lambda(lambda, &mut args)
        },
        _ => error(format!("Unknown symbol: {}", name))
    }
}

fn eval_exec_lambda(l: RLClosure, args: &mut Vec<RLType>) -> RLResult {
    if l.bindings.len() != args.len() {
        return error(format!("Invalid number of arguments for lambda: {}", args.len()));
    }

    // bind the args to the environment
    for i in 0..l.bindings.len() {
        l.env.borrow_mut().insert(l.bindings[i].clone(), args.remove(0));
    }

    // executes the lambda
    eval(*l.ast, &l.env)
}

// lambda keyword
// usage: lambda (params) (body)
// returns a closure, params should be symbols
fn eval_create_lambda( args: &mut Vec<RLType>, outer: &Env) -> RLResult {

    if args.len() > 2 || args.len() < 1 {
        return error(format!(
            "Invalid number of parameters for lambda: {}",
            args.len()))
    }

    let mut params: Vec<String> = Vec::new();

    // extract parameters if present
    if args.len() == 2 {
        if let RLType::List(values) = args.remove(0) {
            for value in values {
                match value {
                    RLType::Symbol(ref name) => params.push(name.to_owned()),
                    _ => return error(format!("Parameter is not a symbol: {}", value)),
                }
            }
        }
    }

    let lambda_env = Environment::new_with_outer(outer);
    let lambda = RLClosure {
        env: lambda_env,
        ast: Box::new(args.remove(0)),
        bindings: params
    };

    Ok(RLType::Lambda(lambda))
}

// Implementation for def
// usage: (def! name value ...)
fn eval_def(args: &mut Vec<RLType>, env: &Env) -> RLResult {
    // Check for a symbol as first argument
    if let RLType::Symbol(name) = args.remove(0) {
        match eval(args.remove(0), env) {
            Ok(value) => {
                env.borrow_mut().insert(name, value);
                Ok(RLType::Nil)
            },
            Err(e) => Err(e),
        }
    } else {
        error(format!("def!: key is not a symbol"))
    }
}

fn eval_do(args: &mut Vec<RLType>, env: &Env) -> RLResult {
    while args.len() > 1 {
        let term = args.remove(0);
        let _ = eval(term, env);
    }
    // eval and return last element
    eval(args.remove(0), env)
}

// Implementation for quote
// usage: (quote value ...)
// fn eval_quote(args: &mut Vec<RLType>) -> RLResult {
//     unimplemented!()
// }

// Implementation for if
// usage: (if test eval_if_true [eval_if_false])
fn eval_if(args: &mut Vec<RLType>, env: &Env) -> RLResult {
    let has_else = if args.len() == 3 {
        true
    } else {
        false
    };
    let condition = args.remove(0);

    match eval(condition, env) {
        Ok(RLType::True) => eval(args.remove(0), env),
        Ok(RLType::False) if has_else => eval(args.remove(1), env),
        Ok(_) => Ok(RLType::Nil),
        Err(e) => Err(e),
    }
}

// Parses the input &str and evals, for use in the REPL
pub fn parse_and_eval(input: &str, env: &Env) -> RLResult {
    let mut tokens = tokenize(input);
    let tree = parse_form(&mut tokens);

    match tree {
        Ok(cell) => eval(cell, env),
        Err(_) => Ok(RLType::Symbol("parse error.".to_string())),
    }
}

// TODO: move tests in separate file
#[test]
fn eval_returns_pi() {
    let t = RLType::Symbol("pi".to_string());
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => 0.0,
    };

    assert_eq!(res, 3.14159265);
}

#[test]
fn eval_sum() {
    let args = vec![RLType::Symbol("+".to_string()), RLType::Number(2.0), RLType::Number(1.0)];

    let t = RLType::List(args);
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => 0.0,
    };

    assert_eq!(res, 3.0);

    let args = vec![RLType::Symbol("+".to_string()),
                    RLType::Number(3.0),
                    RLType::Number(2.0),
                    RLType::Number(1.0)];

    let t = RLType::List(args);
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => 0.0,
    };

    assert_eq!(res, 6.0);
}

#[test]
fn eval_sub() {
    let args = vec![RLType::Symbol("-".to_string()),
                    RLType::Number(3.0),
                    RLType::Number(2.0),
                    RLType::Number(1.0)];

    let t = RLType::List(args);
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => -10.0,
    };

    assert_eq!(res, 0.0);
}
<commit_msg>fixed function calling and list creation<commit_after>use lisp::lex::{tokenize, parse_form};
use lisp::types::*;
use lisp::env::*;

pub fn eval(ast: RLType, env: &Env) -> RLResult {
    match ast {
        RLType::Symbol(ref name) => env.borrow().lookup(name),
        RLType::List(tokens) => eval_list(tokens, env),
        _ => Ok(ast),
    }
}

// Evaluates the list
// if the first element is a function or keyword, it executes that, otherwise returns
// the list itself
fn eval_list(mut tokens: Vec<RLType>, env: &Env) -> RLResult {
    // empty list -> no action
    if tokens.is_empty() {
        return Ok(RLType::List(tokens));
    }

    let mut first = tokens.remove(0);

    if !first.is_atom() {
        first = match eval(first, env) {
            Ok(v) => v,
            Err(e) => return Err(e),
        }
    }

    match first {
        RLType::Symbol(name) => {
            if let Ok(value) = eval_core(&name, &mut tokens, env) {
                return Ok(value);
            }
            eval_proc(&name, tokens, env)
        },
        RLType::Lambda(lambda) => {
            match make_atomic(tokens, env) {
                Ok(RLType::List(ref mut args)) => eval_exec_lambda(lambda, args),
                Ok(v) => error(format!("args are not a list: {}", v)),
                Err(e) => Err(e),
            }
        }
        _ => {
            //TODO: use a keyword for making lists!
            tokens.insert(0, first);

            match make_atomic(tokens, env) {
                Ok(RLType::List(elements)) => Ok(RLType::List(elements)),
                Ok(v) => error(format!("list eval error: {}", v)),
                Err(e) => Err(e),
            }
        },
    }
}

fn eval_core(keyword: &str, args: &mut Vec<RLType>, env: &Env) -> RLResult {
    match keyword {
        "do" => eval_do(args, env),
        "if" => eval_if(args, env),
        "def!" => eval_def(args, env),
        "lambda" => eval_create_lambda(args, env),
        // "quote" => eval_quote(args),
        _ => error(format!("Not a keyword: {}", keyword)),
    }
}

fn eval_proc(name: &str, tokens: Vec<RLType>, env: &Env) -> RLResult {
    // TODO: this borrow blocks recursion
    // test with: (def! fibo ( lambda (n) (if (<= n 2) n (+ (fibo (- n 1)) (fibo (- n 2))))))
    let executable = env.borrow().lookup(name);

    match executable {
        Ok(RLType::Proc(func)) => {
            match make_atomic(tokens, env) {
                Ok(RLType::List(args)) => func(args),
                Ok(v) => error(format!("args are not a list: {}", v)),
                Err(e) => Err(e),
            }
        },
        Ok(RLType::Lambda(lambda)) => {
            match make_atomic(tokens, env) {
                Ok(RLType::List(ref mut args)) => eval_exec_lambda(lambda, args),
                Ok(v) => error(format!("args are not a list: {}", v)),
                Err(e) => Err(e),
            }
        },
        _ => error(format!("Not a function: {}", name))
    }
}

fn eval_exec_lambda(l: RLClosure, args: &mut Vec<RLType>) -> RLResult {
    if l.bindings.len() != args.len() {
        return error(format!("Invalid number of arguments for lambda: {}", args.len()));
    }

    // bind the args to the environment
    for i in 0..l.bindings.len() {
        l.env.borrow_mut().insert(l.bindings[i].clone(), args.remove(0));
    }

    // executes the lambda
    eval(*l.ast, &l.env)
}

// lambda keyword
// usage: lambda (params) (body)
// returns a closure, params should be symbols
fn eval_create_lambda( args: &mut Vec<RLType>, outer: &Env) -> RLResult {

    if args.len() > 2 || args.len() < 1 {
        return error(format!(
            "Invalid number of parameters for lambda: {}",
            args.len()))
    }

    let mut params: Vec<String> = Vec::new();

    // extract parameters if present
    if args.len() == 2 {
        if let RLType::List(values) = args.remove(0) {
            for value in values {
                match value {
                    RLType::Symbol(ref name) => params.push(name.to_owned()),
                    _ => return error(format!("Parameter is not a symbol: {}", value)),
                }
            }
        }
    }

    let lambda_env = Environment::new_with_outer(outer);
    let lambda = RLClosure {
        env: lambda_env,
        ast: Box::new(args.remove(0)),
        bindings: params
    };

    Ok(RLType::Lambda(lambda))
}

// Implementation for def
// usage: (def! name value ...)
fn eval_def(args: &mut Vec<RLType>, env: &Env) -> RLResult {
    // Check for a symbol as first argument
    if let RLType::Symbol(name) = args.remove(0) {
        match eval(args.remove(0), env) {
            Ok(value) => {
                env.borrow_mut().insert(name, value);
                Ok(RLType::Nil)
            },
            Err(e) => Err(e),
        }
    } else {
        error(format!("def!: key is not a symbol"))
    }
}

fn eval_do(args: &mut Vec<RLType>, env: &Env) -> RLResult {
    while args.len() > 1 {
        let term = args.remove(0);
        let _ = eval(term, env);
    }
    // eval and return last element
    eval(args.remove(0), env)
}

// Implementation for quote
// usage: (quote value ...)
// fn eval_quote(args: &mut Vec<RLType>) -> RLResult {
//     unimplemented!()
// }

// Implementation for if
// usage: (if test eval_if_true [eval_if_false])
fn eval_if(args: &mut Vec<RLType>, env: &Env) -> RLResult {
    let has_else = if args.len() == 3 {
        true
    } else {
        false
    };
    let condition = args.remove(0);

    match eval(condition, env) {
        Ok(RLType::True) => eval(args.remove(0), env),
        Ok(RLType::False) if has_else => eval(args.remove(1), env),
        Ok(_) => Ok(RLType::Nil),
        Err(e) => Err(e),
    }
}

// Parses the input &str and evals, for use in the REPL
pub fn parse_and_eval(input: &str, env: &Env) -> RLResult {
    let mut tokens = tokenize(input);
    let tree = parse_form(&mut tokens);

    match tree {
        Ok(cell) => eval(cell, env),
        Err(_) => Ok(RLType::Symbol("parse error.".to_string())),
    }
}

// evaluates a vector of values so that they are all atomic
fn make_atomic(tokens: Vec<RLType>, env: &Env) -> RLResult {
    let mut args: Vec<RLType> = Vec::new();
    for arg in tokens {
        match eval(arg, env) {
            Ok(value) => args.push(value),
            Err(e) => return Err(e),
        }
    }
    Ok(RLType::List(args))
}

// TODO: move tests in separate file
#[test]
fn eval_returns_pi() {
    let t = RLType::Symbol("pi".to_string());
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => 0.0,
    };

    assert_eq!(res, 3.14159265);
}

#[test]
fn eval_sum() {
    let args = vec![RLType::Symbol("+".to_string()), RLType::Number(2.0), RLType::Number(1.0)];

    let t = RLType::List(args);
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => 0.0,
    };

    assert_eq!(res, 3.0);

    let args = vec![RLType::Symbol("+".to_string()),
                    RLType::Number(3.0),
                    RLType::Number(2.0),
                    RLType::Number(1.0)];

    let t = RLType::List(args);
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => 0.0,
    };

    assert_eq!(res, 6.0);
}

#[test]
fn eval_sub() {
    let args = vec![RLType::Symbol("-".to_string()),
                    RLType::Number(3.0),
                    RLType::Number(2.0),
                    RLType::Number(1.0)];

    let t = RLType::List(args);
    let mut env = Environment::default();

    let res = match eval(t, &mut env) {
        RLType::Number(n) => n,
        _ => -10.0,
    };

    assert_eq!(res, 0.0);
}
<|endoftext|>


<commit_before>use std::mem;
use std::cell::RefCell;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::ops::{Index, IndexMut};
use std::collections::LinkedList;
use std::ptr;

use super::page::*;

/// A pool represents a fixed number of ref-counted objects.
/// The pool treats all given space as an unallocated
/// pool of objects. Each object is prefixed with a header.
/// The header is formatted as follows:
/// * V1
///   - [0..2] ref_count: u16
///
pub struct Pool {
    buffer: *mut u8,
    buffer_size: usize,
    capacity: usize,

    tail: AtomicUsize, // One past the end index

    // Cached values
    slot_size: usize,
    header_size: usize,

    free_list: RefCell<LinkedList<PageIndex>>,
}

struct SlotHeader {
    ref_count: AtomicUsize,
}

/// Public interface
impl Pool {
    pub fn new(buf: &mut [u8]) -> Pool {
        let ptr: *mut u8 = buf.as_mut_ptr();
        let header_size = mem::size_of::<SlotHeader>();
        let slot_size = mem::size_of::<Page>() + header_size;
        Pool {
            buffer: ptr,
            buffer_size: buf.len(),
            tail: AtomicUsize::new(0),
            slot_size: slot_size,
            capacity: buf.len() / slot_size,
            header_size: header_size,
            free_list: RefCell::new(LinkedList::new()),
        }
    }

    /// Remove all objects from the pool
    /// and zero the memory
    pub unsafe fn clear(&mut self) {
        let mut i = self.buffer.clone();
        let end = self.buffer.clone().offset(self.buffer_size as isize);
        while i != end {
            *i = 0u8;
            i = i.offset(1);
        }
    }

    /// Fast copy a slot's contents to a new slot and return
    /// a pointer to the new slot
    pub fn alloc_with_contents_of(&self, other: PageIndex) -> Result<PageIndex, &'static str> {
        let index = try!(self.claim_free_index());
        unsafe {
            let from = self.raw_contents_for(other);
            let to = self.raw_contents_for(index);
            ptr::copy_nonoverlapping(from, to, mem::size_of::<Page>());
        }
        Ok(index)
    }

    /// Try to allocate a new item from the pool.
    /// A mutable reference to the item is returned on success
    pub fn alloc(&self) -> Result<PageIndex, &'static str> {
        let index = try!(self.internal_alloc());
        Ok(index)
    }

    // Increase the ref count for the cell at the given index
    pub fn retain(&self, index: PageIndex) {
        let h = self.header_for(index);
        h.ref_count.fetch_add(1, Ordering::SeqCst);
    }

    // Decrease the ref count for the cell at the given index
    // return true iff the cell is now considered free
    pub fn release(&self, index: PageIndex) -> bool {
        let mut is_free = false;
        { // Make the borrow checker happy
            let h = self.header_for(index);
            let old = h.ref_count.fetch_sub(1, Ordering::SeqCst);
            if old == 1 {
                // TODO: check the correctness of this
                is_free = true;
            }
        }
        if is_free {
            self.free_list.borrow_mut().push_back(index);
        }
        is_free
    }

    /// Returns the number of live items. O(1) running time.
    pub fn live_count(&self) -> usize {
        self.tail.load(Ordering::SeqCst) - self.free_list.borrow().len()
    }
}

/// Internal Functions
impl Pool {
    // Returns an item from the free list, or
    // tries to allocate a new one from the buffer
    fn claim_free_index(&self) -> Result<PageIndex, &'static str> {
        let index = match self.free_list.borrow_mut().pop_front() {
            Some(i) => i,
            None => try!(self.push_back_alloc()),
        };
        self.retain(index);
        Ok(index)
    }

    // Internal alloc that does not create an Arc but still claims a slot
    fn internal_alloc(&self) -> Result<PageIndex, &'static str> {
        let index = try!(self.claim_free_index());
        Ok(index)
    }

    // Pushes the end of the used space in the buffer back
    // returns the previous index
    fn push_back_alloc(&self) -> Result<PageIndex, &'static str> {
        let old_tail = self.tail.fetch_add(1, Ordering::SeqCst);
        if old_tail >= self.capacity {
            Err("OOM")
        } else {
            Ok(old_tail)
        }
    }

    fn header_for<'a>(&'a self, i: PageIndex) -> &'a mut SlotHeader {
        unsafe {
            let ptr = self.buffer.clone()
                .offset((i * self.slot_size) as isize);
            mem::transmute(ptr)
        }
    }

    fn raw_contents_for<'a>(&'a self, i: PageIndex) -> *mut u8 {
        unsafe {
            self.buffer.clone()
                .offset((i * self.slot_size) as isize)
                .offset(self.header_size as isize)
        }
    }
}

impl Index<PageIndex> for Pool {
    type Output = Page;

    fn index<'a>(&'a self, i: usize) -> &'a Page {
        unsafe {
            let ptr = self.buffer.clone()
                .offset((i * self.slot_size) as isize)
                .offset(self.header_size as isize);
            mem::transmute(ptr)
        }
    }
}

impl IndexMut<PageIndex> for Pool {
    fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Page {
        unsafe {
            let ptr = self.buffer.clone()
                .offset((i * self.slot_size) as isize)
                .offset(self.header_size as isize);
            mem::transmute(ptr)
        }
    }
}

/// Tests
#[test]
fn release_frees() {
       let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
       let p = Pool::new(&mut buf[..]);

       // Use internal_alloc so that the Arc doesn't drop
       // the reference immediately
       assert!(p.internal_alloc().is_ok());
       assert!(p.internal_alloc().is_ok());

       assert_eq!(2, p.live_count());

       p.release(0);
       assert_eq!(1, p.live_count());
       assert_eq!(1, p.free_list.borrow().len());
       assert_eq!(0, *p.free_list.borrow().front().unwrap());

       p.release(1);
       assert_eq!(0, p.live_count());
       assert_eq!(2, p.free_list.borrow().len());
}

#[test]
fn alloc_after_free_recycles() {
       let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
       let p = Pool::new(&mut buf[..]);
       assert!(p.internal_alloc().is_ok());
       assert_eq!(1, p.live_count());
       assert_eq!(1, p.tail.load(Ordering::Relaxed));

       p.release(0);
       assert_eq!(0, p.live_count());
       assert_eq!(1, p.free_list.borrow().len());

       assert!(p.internal_alloc().is_ok());
       assert_eq!(1, p.tail.load(Ordering::Relaxed)); // Tail shouldn't move
       assert_eq!(1, p.live_count());
       assert_eq!(0, p.free_list.borrow().len());
}

#[test]
fn construction() {
    let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
    let p = Pool::new(&mut buf[..]);

    assert_eq!(5*0x1000, p.buffer_size);
    assert_eq!(mem::size_of::<usize>(), p.header_size);

    let expected_size = mem::size_of::<usize>() + mem::size_of::<Page>();
    assert_eq!(expected_size, p.slot_size);
    assert_eq!(5*0x1000/expected_size, p.capacity); // expected_size should be 8+4096=4104
    assert_eq!(4, p.capacity);
}

#[test]
fn free_list_alloc_works() {
    let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
    let mut p = Pool::new(&mut buf[..]);
    let forty_two = [42u8; 4096];
    {
        let int1 = p.alloc().unwrap();
        p[int1] = forty_two;
        // Check payload
        assert_eq!(forty_two[..], buf[8..4104]);
        // Check ref_count
        assert_eq!([1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8][..], buf[0..8]);
        assert_eq!(1, p.live_count());
    }
}

#[test]
fn check_oom_error() {
    let mut buf: [u8; 1] = [0; 1];
    let p = Pool::new(&mut buf[..]);
    assert_eq!(Err("OOM"), p.alloc());
}

#[test]
fn multiple_allocations_work() {
    let mut buf: [u8; 12*0x1000] = [0; 12*0x1000];
    let p = Pool::new(&mut buf[..]);
    for _ in 0..10 {
        let _ = p.alloc().unwrap();
   }
   assert_eq!(10, p.live_count());
   let expected_ref_count = [1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8];
   for i in 0..10 {
       let start = 4104*i;
       // Check ref_count
       assert_eq!(expected_ref_count[..], buf[start..start+8]);
    }
}
<commit_msg>Added zeroing memory after alloc<commit_after>use std::mem;
use std::cell::RefCell;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::ops::{Index, IndexMut};
use std::collections::LinkedList;
use std::ptr;

use super::page::*;

/// A pool represents a fixed number of ref-counted objects.
/// The pool treats all given space as an unallocated
/// pool of objects. Each object is prefixed with a header.
/// The header is formatted as follows:
/// * V1
///   - [0..2] ref_count: u16
///
pub struct Pool {
    buffer: *mut u8,
    buffer_size: usize,
    capacity: usize,

    tail: AtomicUsize, // One past the end index

    // Cached values
    slot_size: usize,
    header_size: usize,

    free_list: RefCell<LinkedList<PageIndex>>,
}

struct SlotHeader {
    ref_count: AtomicUsize,
}

/// Public interface
impl Pool {
    pub fn new(buf: &mut [u8]) -> Pool {
        let ptr: *mut u8 = buf.as_mut_ptr();
        let header_size = mem::size_of::<SlotHeader>();
        let slot_size = mem::size_of::<Page>() + header_size;
        Pool {
            buffer: ptr,
            buffer_size: buf.len(),
            tail: AtomicUsize::new(0),
            slot_size: slot_size,
            capacity: buf.len() / slot_size,
            header_size: header_size,
            free_list: RefCell::new(LinkedList::new()),
        }
    }

    /// Remove all objects from the pool
    /// and zero the memory
    pub unsafe fn clear(&mut self) {
        let mut i = self.buffer.clone();
        let end = self.buffer.clone().offset(self.buffer_size as isize);
        while i != end {
            *i = 0u8;
            i = i.offset(1);
        }
    }

    /// Fast copy a slot's contents to a new slot and return
    /// a pointer to the new slot
    pub fn alloc_with_contents_of(&self, other: PageIndex) -> Result<PageIndex, &'static str> {
        let index = try!(self.claim_free_index());
        unsafe {
            let from = self.raw_contents_for(other);
            let to = self.raw_contents_for(index);
            ptr::copy_nonoverlapping(from, to, mem::size_of::<Page>());
        }
        Ok(index)
    }

    /// Try to allocate a new item from the pool.
    /// A mutable reference to the item is returned on success
    pub fn alloc(&self) -> Result<PageIndex, &'static str> {
        let index = try!(self.claim_free_index());
        self.zero_page(index);
        Ok(index)
    }

    // Increase the ref count for the cell at the given index
    pub fn retain(&self, index: PageIndex) {
        let h = self.header_for(index);
        h.ref_count.fetch_add(1, Ordering::SeqCst);
    }

    // Decrease the ref count for the cell at the given index
    // return true iff the cell is now considered free
    pub fn release(&self, index: PageIndex) -> bool {
        let mut is_free = false;
        { // Make the borrow checker happy
            let h = self.header_for(index);
            let old = h.ref_count.fetch_sub(1, Ordering::SeqCst);
            if old == 1 {
                // TODO: check the correctness of this
                is_free = true;
            }
        }
        if is_free {
            self.free_list.borrow_mut().push_back(index);
        }
        is_free
    }

    /// Returns the number of live items. O(1) running time.
    pub fn live_count(&self) -> usize {
        self.tail.load(Ordering::SeqCst) - self.free_list.borrow().len()
    }
}

/// Internal Functions
impl Pool {
    // Returns an item from the free list, or
    // tries to allocate a new one from the buffer
    fn claim_free_index(&self) -> Result<PageIndex, &'static str> {
        let index = match self.free_list.borrow_mut().pop_front() {
            Some(i) => i,
            None => try!(self.push_back_alloc()),
        };
        self.retain(index);
        Ok(index)
    }

    // Pushes the end of the used space in the buffer back
    // returns the previous index
    fn push_back_alloc(&self) -> Result<PageIndex, &'static str> {
        let old_tail = self.tail.fetch_add(1, Ordering::SeqCst);
        if old_tail >= self.capacity {
            Err("OOM")
        } else {
            Ok(old_tail)
        }
    }

    fn header_for<'a>(&'a self, i: PageIndex) -> &'a mut SlotHeader {
        unsafe {
            let ptr = self.buffer.clone()
                .offset((i * self.slot_size) as isize);
            mem::transmute(ptr)
        }
    }

    fn raw_contents_for<'a>(&'a self, i: PageIndex) -> *mut u8 {
        unsafe {
            self.buffer.clone()
                .offset((i * self.slot_size) as isize)
                .offset(self.header_size as isize)
        }
    }

    fn zero_page(&self, page_index: PageIndex) {
        unsafe {
            let mut i = self.raw_contents_for(page_index);
            let end = i.clone().offset(mem::size_of::<Page>() as isize);
            while i != end {
                *i = 0u8;
                i = i.offset(1);
            }
        }
    }
}

impl Index<PageIndex> for Pool {
    type Output = Page;

    fn index<'a>(&'a self, i: usize) -> &'a Page {
        unsafe {
            let ptr = self.buffer.clone()
                .offset((i * self.slot_size) as isize)
                .offset(self.header_size as isize);
            mem::transmute(ptr)
        }
    }
}

impl IndexMut<PageIndex> for Pool {
    fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut Page {
        unsafe {
            let ptr = self.buffer.clone()
                .offset((i * self.slot_size) as isize)
                .offset(self.header_size as isize);
            mem::transmute(ptr)
        }
    }
}

/// Tests
#[test]
fn release_frees() {
       let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
       let p = Pool::new(&mut buf[..]);

       // Use claim_free_index so that the Arc doesn't drop
       // the reference immediately
       assert!(p.claim_free_index().is_ok());
       assert!(p.claim_free_index().is_ok());

       assert_eq!(2, p.live_count());

       p.release(0);
       assert_eq!(1, p.live_count());
       assert_eq!(1, p.free_list.borrow().len());
       assert_eq!(0, *p.free_list.borrow().front().unwrap());

       p.release(1);
       assert_eq!(0, p.live_count());
       assert_eq!(2, p.free_list.borrow().len());
}

#[test]
fn alloc_after_free_recycles() {
       let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
       let p = Pool::new(&mut buf[..]);
       assert!(p.claim_free_index().is_ok());
       assert_eq!(1, p.live_count());
       assert_eq!(1, p.tail.load(Ordering::Relaxed));

       p.release(0);
       assert_eq!(0, p.live_count());
       assert_eq!(1, p.free_list.borrow().len());

       assert!(p.claim_free_index().is_ok());
       assert_eq!(1, p.tail.load(Ordering::Relaxed)); // Tail shouldn't move
       assert_eq!(1, p.live_count());
       assert_eq!(0, p.free_list.borrow().len());
}

#[test]
fn construction() {
    let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
    let p = Pool::new(&mut buf[..]);

    assert_eq!(5*0x1000, p.buffer_size);
    assert_eq!(mem::size_of::<usize>(), p.header_size);

    let expected_size = mem::size_of::<usize>() + mem::size_of::<Page>();
    assert_eq!(expected_size, p.slot_size);
    assert_eq!(5*0x1000/expected_size, p.capacity); // expected_size should be 8+4096=4104
    assert_eq!(4, p.capacity);
}

#[test]
fn free_list_alloc_works() {
    let mut buf: [u8; 5*0x1000] = [0; 5*0x1000];
    let mut p = Pool::new(&mut buf[..]);
    let forty_two = [42u8; 4096];
    {
        let int1 = p.alloc().unwrap();
        p[int1] = forty_two;
        // Check payload
        assert_eq!(forty_two[..], buf[8..4104]);
        // Check ref_count
        assert_eq!([1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8][..], buf[0..8]);
        assert_eq!(1, p.live_count());
    }
}

#[test]
fn check_oom_error() {
    let mut buf: [u8; 1] = [0; 1];
    let p = Pool::new(&mut buf[..]);
    assert_eq!(Err("OOM"), p.alloc());
}

#[test]
fn multiple_allocations_work() {
    let mut buf: [u8; 12*0x1000] = [0; 12*0x1000];
    let p = Pool::new(&mut buf[..]);
    for _ in 0..10 {
        let _ = p.alloc().unwrap();
   }
   assert_eq!(10, p.live_count());
   let expected_ref_count = [1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8];
   for i in 0..10 {
       let start = 4104*i;
       // Check ref_count
       assert_eq!(expected_ref_count[..], buf[start..start+8]);
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ptr;
use std::mem::size_of;
use std::c_str::CString;
use libc::{
  c_char,
  c_uint,
  size_t,
  malloc,
  free,
  c_void
};
use native::{
  memcached_create,
  memcached_set,
  memcached_get,
  memcached_st,
  memcached_return_t,
  memcached_server_add,
};

pub mod native;

pub struct Client {
  cl: *mut memcached_st
}

pub struct Server<'a> {
  host: &'a str,
  port: uint,
}

impl<'a> Server<'a> {
  pub fn new<'a>(host: &'a str, port: uint) -> Server<'a> {
    Server { host: host, port: port }
  }
}

impl Client {
  pub fn new() -> Client {
    Client{ cl: unsafe { memcached_create(ptr::mut_null()) } }
  }

  pub fn add_server(&self, server: &Server) {
    unsafe { memcached_server_add(self.cl, server.host.to_c_str().unwrap(), server.port as u16) };
  }

  pub fn set(&self, key: &str, value: &str, expire: int) {
    let key_c = key.to_c_str();
    let value_c = value.to_c_str();
    unsafe {
      memcached_set(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_c.clone().unwrap(), value_c.len() as u64, expire as i64, 0);
    }
  }

  pub fn get(&self, key: &str) -> CString {
    let key_c = key.to_c_str();
    unsafe {
      let value_length = malloc(size_of::<size_t>() as size_t) as *mut size_t;
      let error = malloc(size_of::<memcached_return_t>() as size_t) as *mut memcached_return_t;
      let flags = malloc(size_of::<c_uint>() as size_t) as *mut c_uint;
      let value = memcached_get(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_length, flags, error);
      free(value_length as *mut c_void);
      free(error as *mut c_void);
      free(flags as *mut c_void);
      CString::new(value as *const c_char, false)
    }
  }

  pub fn get_str(&self, key: &str) -> String {
    self.get(key).as_str().unwrap().into_string()
  }
}

#[test]
fn test() {
  let cl = Client::new();
  let server = Server::new("127.0.0.1", 11211);
  cl.add_server(&server);
  cl.set("hoge", "fuga", 10);
  assert!(cl.get_str("hoge").as_slice() == "fuga");
}
<commit_msg>Fix the compiler warning.<commit_after>extern crate libc;

use std::ptr;
use std::mem::size_of;
use std::c_str::CString;
use libc::{
  c_char,
  c_uint,
  size_t,
  malloc,
  free,
  c_void
};
use native::{
  memcached_create,
  memcached_set,
  memcached_get,
  memcached_st,
  memcached_return_t,
  memcached_server_add,
};

pub mod native;

pub struct Client {
  cl: *mut memcached_st
}

pub struct Server<'a> {
  host: &'a str,
  port: uint,
}

impl<'a> Server<'a> {
  pub fn new<'a>(host: &'a str, port: uint) -> Server<'a> {
    Server { host: host, port: port }
  }
}

impl Client {
  pub fn new() -> Client {
    Client{ cl: unsafe { memcached_create(ptr::null_mut()) } }
  }

  pub fn add_server(&self, server: &Server) {
    unsafe { memcached_server_add(self.cl, server.host.to_c_str().unwrap(), server.port as u16) };
  }

  pub fn set(&self, key: &str, value: &str, expire: int) {
    let key_c = key.to_c_str();
    let value_c = value.to_c_str();
    unsafe {
      memcached_set(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_c.clone().unwrap(), value_c.len() as u64, expire as i64, 0);
    }
  }

  pub fn get(&self, key: &str) -> CString {
    let key_c = key.to_c_str();
    unsafe {
      let value_length = malloc(size_of::<size_t>() as size_t) as *mut size_t;
      let error = malloc(size_of::<memcached_return_t>() as size_t) as *mut memcached_return_t;
      let flags = malloc(size_of::<c_uint>() as size_t) as *mut c_uint;
      let value = memcached_get(self.cl, key_c.clone().unwrap(), key_c.len() as u64, value_length, flags, error);
      free(value_length as *mut c_void);
      free(error as *mut c_void);
      free(flags as *mut c_void);
      CString::new(value as *const c_char, false)
    }
  }

  pub fn get_str(&self, key: &str) -> String {
    self.get(key).as_str().unwrap().into_string()
  }
}

#[test]
fn test() {
  let cl = Client::new();
  let server = Server::new("127.0.0.1", 11211);
  cl.add_server(&server);
  cl.set("hoge", "fuga", 10);
  assert!(cl.get_str("hoge").as_slice() == "fuga");
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate libc;
#[macro_use] extern crate log;
extern crate regex;

extern crate argparse;
extern crate quire;
#[macro_use] extern crate lithos;

use std::env;
use std::rc::Rc;
use std::process::exit;
use std::path::{Path, PathBuf};
use std::io::{stderr, Write};
use std::default::Default;
use std::collections::BTreeMap;

use regex::Regex;
use quire::parse_config;
use argparse::{ArgumentParser, Parse, List};
use rustc_serialize::json;
use libc::funcs::posix88::unistd::getpid;

use lithos::setup::clean_child;
use lithos::master_config::{MasterConfig, create_master_dirs};
use lithos::tree_config::TreeConfig;
use lithos::container_config::ContainerKind::{Command};
use lithos::child_config::ChildConfig;
use lithos::container::{Command};
use lithos::monitor::{Monitor, Executor};
use lithos::signal;

struct Child<'a> {
    name: Rc<String>,
    master_file: PathBuf,
    master_config: &'a MasterConfig,
    child_config_serialized: String,
    root_binary: PathBuf,
    args: Vec<String>,
}

impl<'a> Executor for Child<'a> {
    fn command(&self) -> Command
    {
        let mut cmd = Command::new((*self.name).clone(), &self.root_binary);
        cmd.keep_sigmask();

        // Name is first here, so it's easily visible in ps
        cmd.arg("--name");
        cmd.arg(&self.name[..]);

        cmd.arg("--master");
        cmd.arg(&self.master_file.to_str().unwrap()[..]);
        cmd.arg("--config");
        cmd.arg(&self.child_config_serialized[..]);
        cmd.set_env("TERM".to_string(),
                    env::var("TERM").unwrap_or("dumb".to_string()));
        if let Ok(x) = env::var("RUST_LOG") {
            cmd.set_env("RUST_LOG".to_string(), x);
        }
        if let Ok(x) = env::var("RUST_BACKTRACE") {
            cmd.set_env("RUST_BACKTRACE".to_string(), x);
        }
        cmd.args(&self.args);
        cmd.container();
        return cmd;
    }
    fn finish(&self) -> bool {
        clean_child(&*self.name, self.master_config);
        return false;  // Do not restart
    }
}

fn run(master_cfg: &Path, tree_name: String,
    command_name: String, args: Vec<String>)
    -> Result<(), String>
{
    let master: MasterConfig = try!(parse_config(&master_cfg,
        &*MasterConfig::validator(), Default::default())
        .map_err(|e| format!("Error reading master config: {}", e)));
    try!(create_master_dirs(&master));

    if !Regex::new(r"^[\w-]+$").unwrap().is_match(&tree_name) {
        return Err(format!("Wrong tree name: {}", tree_name));
    }
    if !Regex::new(r"^[\w-]+$").unwrap().is_match(&command_name) {
        return Err(format!("Wrong command name: {}", command_name));
    }

    let tree: TreeConfig = try!(parse_config(
        &master.config_dir.join(tree_name.clone() + ".yaml"),
        &*TreeConfig::validator(), Default::default())
        .map_err(|e| format!("Error reading tree config: {}", e)));

    debug!("Children config {:?}", tree.config_file);
    let tree_children: BTreeMap<String, ChildConfig>;
    tree_children = try!(parse_config(&tree.config_file,
        &*ChildConfig::mapping_validator(), Default::default())
        .map_err(|e| format!("Error reading children config: {}", e)));
    let child_cfg = try!(tree_children.get(&command_name)
        .ok_or(format!("Command {:?} not found", command_name)));

    if child_cfg.kind != Command {
        return Err(format!("The target container is: {:?}", child_cfg.kind));
    }

    let name = Rc::new(format!("{}/cmd.{}.{}", tree_name,
        command_name, unsafe { getpid() }));
    info!("[{}] Running command with args {:?}", name, args);
    let mut mon = Monitor::new((*name).clone());
    let timeo = 0;
    let mut args = args;
    args.insert(0, "--".to_string());
    mon.add(name.clone(), Box::new(Child {
        name: name,
        master_file: PathBuf::from(master_cfg),
        master_config: &master,
        child_config_serialized: json::encode(&child_cfg).unwrap(),
        root_binary: env::current_exe().unwrap()
                     .parent().unwrap().join("lithos_knot"),
        args: args,
    }), timeo, None);
    mon.run();

    return Ok(());
}

fn main() {

    signal::block_all();

    let mut master_config = PathBuf::from("/etc/lithos.yaml");
    let mut command_name = "".to_string();
    let mut tree_name = "".to_string();
    let mut args = vec!();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Runs tree of processes");
        ap.refer(&mut master_config)
          .add_option(&["--master"], Parse,
            "Name of the master configuration file (default /etc/lithos.yaml)")
          .metavar("FILE");
        ap.refer(&mut tree_name)
          .add_argument("subtree", Parse,
            "Name of the tree to run command for")
          .required();
        ap.refer(&mut command_name)
          .add_argument("name", Parse,
            "Name of the command to run")
          .required();
        ap.refer(&mut args)
          .add_argument("argument", List,
            "Arguments for the command");
        ap.stop_on_first_argument(true);
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }
    match run(&master_config, tree_name, command_name, args) {
        Ok(()) => {
            exit(0);
        }
        Err(e) => {
            write!(&mut stderr(), "Fatal error: {}\n", e).unwrap();
            exit(1);
        }
    }
}
<commit_msg>Implement logging in lithos_cmd like in lithos_tree<commit_after>extern crate rustc_serialize;
extern crate libc;
#[macro_use] extern crate log;
extern crate regex;

extern crate argparse;
extern crate quire;
#[macro_use] extern crate lithos;

use std::env;
use std::rc::Rc;
use std::process::exit;
use std::path::{Path, PathBuf};
use std::io::{stderr, Write};
use std::default::Default;
use std::collections::BTreeMap;

use regex::Regex;
use quire::parse_config;
use argparse::{ArgumentParser, Parse, List, StoreTrue, Store};
use rustc_serialize::json;
use libc::funcs::posix88::unistd::getpid;

use lithos::setup::{clean_child, init_logging};
use lithos::master_config::{MasterConfig, create_master_dirs};
use lithos::tree_config::TreeConfig;
use lithos::container_config::ContainerKind::{Command};
use lithos::child_config::ChildConfig;
use lithos::container::{Command};
use lithos::monitor::{Monitor, Executor};
use lithos::signal;

struct Child<'a> {
    name: Rc<String>,
    master_file: PathBuf,
    master_config: &'a MasterConfig,
    child_config_serialized: String,
    root_binary: PathBuf,
    args: Vec<String>,
}

impl<'a> Executor for Child<'a> {
    fn command(&self) -> Command
    {
        let mut cmd = Command::new((*self.name).clone(), &self.root_binary);
        cmd.keep_sigmask();

        // Name is first here, so it's easily visible in ps
        cmd.arg("--name");
        cmd.arg(&self.name[..]);

        cmd.arg("--master");
        cmd.arg(&self.master_file.to_str().unwrap()[..]);
        cmd.arg("--config");
        cmd.arg(&self.child_config_serialized[..]);
        cmd.set_env("TERM".to_string(),
                    env::var("TERM").unwrap_or("dumb".to_string()));
        if let Ok(x) = env::var("RUST_LOG") {
            cmd.set_env("RUST_LOG".to_string(), x);
        }
        if let Ok(x) = env::var("RUST_BACKTRACE") {
            cmd.set_env("RUST_BACKTRACE".to_string(), x);
        }
        cmd.args(&self.args);
        cmd.container();
        return cmd;
    }
    fn finish(&self) -> bool {
        clean_child(&*self.name, self.master_config);
        return false;  // Do not restart
    }
}

fn run(master_cfg: &Path, tree_name: String,
    command_name: String, args: Vec<String>,
    log_stderr: bool, log_level: log::LogLevel)
    -> Result<(), String>
{
    let master: MasterConfig = try!(parse_config(&master_cfg,
        &*MasterConfig::validator(), Default::default())
        .map_err(|e| format!("Error reading master config: {}", e)));
    try!(create_master_dirs(&master));

    if !Regex::new(r"^[\w-]+$").unwrap().is_match(&tree_name) {
        return Err(format!("Wrong tree name: {}", tree_name));
    }
    if !Regex::new(r"^[\w-]+$").unwrap().is_match(&command_name) {
        return Err(format!("Wrong command name: {}", command_name));
    }

    let tree: TreeConfig = try!(parse_config(
        &master.config_dir.join(tree_name.clone() + ".yaml"),
        &*TreeConfig::validator(), Default::default())
        .map_err(|e| format!("Error reading tree config: {}", e)));

    let mut log_file;
    if let Some(ref fname) = tree.log_file {
        log_file = master.default_log_dir.join(fname);
    } else {
        log_file = master.default_log_dir.join(format!("{}.log", tree_name));
    }
    try!(init_logging(&log_file, log_level, log_stderr));

    debug!("Children config {:?}", tree.config_file);
    let tree_children: BTreeMap<String, ChildConfig>;
    tree_children = try!(parse_config(&tree.config_file,
        &*ChildConfig::mapping_validator(), Default::default())
        .map_err(|e| format!("Error reading children config: {}", e)));
    let child_cfg = try!(tree_children.get(&command_name)
        .ok_or(format!("Command {:?} not found", command_name)));

    if child_cfg.kind != Command {
        return Err(format!("The target container is: {:?}", child_cfg.kind));
    }

    let name = Rc::new(format!("{}/cmd.{}.{}", tree_name,
        command_name, unsafe { getpid() }));
    info!("[{}] Running command with args {:?}", name, args);
    let mut mon = Monitor::new((*name).clone());
    let timeo = 0;
    let mut args = args;
    args.insert(0, "--".to_string());
    mon.add(name.clone(), Box::new(Child {
        name: name,
        master_file: PathBuf::from(master_cfg),
        master_config: &master,
        child_config_serialized: json::encode(&child_cfg).unwrap(),
        root_binary: env::current_exe().unwrap()
                     .parent().unwrap().join("lithos_knot"),
        args: args,
    }), timeo, None);
    mon.run();

    return Ok(());
}

fn main() {

    signal::block_all();

    let mut master_config = PathBuf::from("/etc/lithos.yaml");
    let mut command_name = "".to_string();
    let mut tree_name = "".to_string();
    let mut args = vec!();
    let mut log_stderr: bool = false;
    let mut log_level: log::LogLevel = log::LogLevel::Warn;
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Runs tree of processes");
        ap.refer(&mut master_config)
          .add_option(&["--master"], Parse,
            "Name of the master configuration file (default /etc/lithos.yaml)")
          .metavar("FILE");
        ap.refer(&mut log_stderr)
          .add_option(&["--log-stderr"], StoreTrue,
            "Print debugging info to stderr");
        ap.refer(&mut log_level)
          .add_option(&["--log-level"], Store,
            "Set log level (default info for now)");
        ap.refer(&mut tree_name)
          .add_argument("subtree", Parse,
            "Name of the tree to run command for")
          .required();
        ap.refer(&mut command_name)
          .add_argument("name", Parse,
            "Name of the command to run")
          .required();
        ap.refer(&mut args)
          .add_argument("argument", List,
            "Arguments for the command");
        ap.stop_on_first_argument(true);
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                exit(x);
            }
        }
    }
    match run(&master_config, tree_name, command_name, args,
              log_stderr, log_level)
    {
        Ok(()) => {
            exit(0);
        }
        Err(e) => {
            write!(&mut stderr(), "Fatal error: {}\n", e).unwrap();
            exit(1);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(convert)]
#![feature(buf_stream)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate yak_client;
extern crate capnp;

use std::net::{TcpListener, TcpStream, Ipv4Addr};
use std::thread;
use std::io::{self,Read,Write,BufStream,BufRead};
use std::str::FromStr;
use std::fmt;
use std::collections::HashMap;

use capnp::serialize_packed;
use capnp::{MessageBuilder, MessageReader, MallocMessageBuilder, ReaderOptions};

use yak_client::yak_capnp::*;

#[derive(Debug)]
enum ServerError {
  CapnpError(capnp::Error),
  CapnpNotInSchema(capnp::NotInSchema),
  IoError(std::io::Error)
}

pub fn main() {
  env_logger::init().unwrap();

  let mut a = std::env::args().skip(1);
  let local : String = a.next().unwrap();
  let next : Option<String> = a.next();

  let listener = TcpListener::bind(local.as_str()).unwrap();
  info!("listening started on {}, ready to accept", local);
  for stream in listener.incoming() {
    let next = next.clone();
    thread::spawn(move || {
	let mut sock = &stream.unwrap();
	let peer = sock.peer_addr().unwrap();
	info!("Accept stream from {:?}", peer);
        let mut strm = BufStream::new(sock);
        process_requests(peer, strm).unwrap()
      });
  }
}

fn process_requests<Id: fmt::Display, S: Read + Write>(id: Id, mut strm: BufStream<S>) -> Result<(), ServerError> {
  let mut store = HashMap::new();
  loop {
    debug!("{}: Waiting for message", id);
    let len = try!(strm.fill_buf()).len();
    if len == 0 {
        debug!("{}: End of client stream", id);
        return Ok(())
    }
    let message_reader = try!(serialize_packed::read_message(&mut strm, ReaderOptions::new()));
    let msg = try!(message_reader.get_root::<client_request::Reader>());
    debug!("{}: Read message", id);

    let mut message = MallocMessageBuilder::new_default();
    {
      let mut response = message.init_root::<client_response::Builder>();
      match try!(msg.which()) {
        client_request::Truncate(v) => truncate(&id, &mut store, v, response),
          client_request::Read(v) => read(&id, &mut store, try!(v), response),
          client_request::Write(v) => write(&id, &mut store, try!(v), response),
      };
    }

    try!(serialize_packed::write_message(&mut strm, &mut message));
    try!(strm.flush())
  }
}

fn truncate<Id: fmt::Display>(id: &Id, store: &mut HashMap<Vec<u8>, Vec<Vec<u8>>>, v: (), mut response: client_response::Builder) -> Result<(), ServerError> {
  info!("{}: truncate:{:?}", id, v);
  store.clear();
  response.set_ok(());
  Ok(())
}

fn read<Id: fmt::Display>(id: &Id, store: &mut HashMap<Vec<u8>, Vec<Vec<u8>>>, req: read_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let key = try!(req.get_key()).into();
  let val = store.get(key).map(|x| x.clone()).unwrap_or(vec![]);
  info!("{}: read:{:?}: -> {:?}", id, key, val);

  let mut data = response.init_ok_data(val.len() as u32);
  for i in 0..val.len() {
    let mut datum = data.borrow().get(i as u32);
    datum.set_value(&val[i])
  }
  Ok(())
}

fn write<Id: fmt::Display>(id: &Id, store: &mut HashMap<Vec<u8>, Vec<Vec<u8>>>, v: write_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let key = try!(v.get_key()).into();
  let val = try!(v.get_value()).into();
  info!("{}: write:{:?} -> {:?}", id, key, val);

  let entry = store.entry(key).or_insert(vec![]);
  entry.push(val);
  response.set_ok(());
  Ok(())
}

impl From<capnp::Error> for ServerError {
  fn from(err: capnp::Error) -> ServerError {
    ServerError::CapnpError(err)
  }
}

impl From<capnp::NotInSchema> for ServerError {
  fn from(err: capnp::NotInSchema) -> ServerError {
    ServerError::CapnpNotInSchema(err)
  }
}

impl From<io::Error> for ServerError {
  fn from(err: io::Error) -> ServerError {
    ServerError::IoError(err)
  }
}
<commit_msg>Newtype wrapper around the store.<commit_after>#![feature(convert)]
#![feature(buf_stream)]
#[macro_use] extern crate log;
extern crate env_logger;
extern crate yak_client;
extern crate capnp;

use std::net::{TcpListener, TcpStream, Ipv4Addr};
use std::thread;
use std::io::{self,Read,Write,BufStream,BufRead};
use std::str::FromStr;
use std::fmt;
use std::collections::HashMap;

use capnp::serialize_packed;
use capnp::{MessageBuilder, MessageReader, MallocMessageBuilder, ReaderOptions};

use yak_client::yak_capnp::*;

type Key = Vec<u8>;
type Values = Vec<Vec<u8>>;
struct Store (HashMap<Key, Values>);

#[derive(Debug)]
enum ServerError {
  CapnpError(capnp::Error),
  CapnpNotInSchema(capnp::NotInSchema),
  IoError(std::io::Error)
}

pub fn main() {
  env_logger::init().unwrap();

  let mut a = std::env::args().skip(1);
  let local : String = a.next().unwrap();
  let next : Option<String> = a.next();

  let listener = TcpListener::bind(local.as_str()).unwrap();
  info!("listening started on {}, ready to accept", local);
  for stream in listener.incoming() {
    let next = next.clone();
    thread::spawn(move || {
	let mut sock = &stream.unwrap();
	let peer = sock.peer_addr().unwrap();
	info!("Accept stream from {:?}", peer);
        let mut strm = BufStream::new(sock);
        process_requests(peer, strm).unwrap()
      });
  }
}

fn process_requests<Id: fmt::Display, S: Read + Write>(id: Id, mut strm: BufStream<S>) -> Result<(), ServerError> {
  let mut store = Store(HashMap::new());
  loop {
    debug!("{}: Waiting for message", id);
    let len = try!(strm.fill_buf()).len();
    if len == 0 {
        debug!("{}: End of client stream", id);
        return Ok(())
    }
    let message_reader = try!(serialize_packed::read_message(&mut strm, ReaderOptions::new()));
    let msg = try!(message_reader.get_root::<client_request::Reader>());
    debug!("{}: Read message", id);

    let mut message = MallocMessageBuilder::new_default();
    {
      let mut response = message.init_root::<client_response::Builder>();
      match try!(msg.which()) {
        client_request::Truncate(v) => truncate(&id, &mut store, v, response),
          client_request::Read(v) => read(&id, &mut store, try!(v), response),
          client_request::Write(v) => write(&id, &mut store, try!(v), response),
      };
    }

    try!(serialize_packed::write_message(&mut strm, &mut message));
    try!(strm.flush())
  }
}

fn truncate<Id: fmt::Display>(id: &Id, store: &mut Store, v: (), mut response: client_response::Builder) -> Result<(), ServerError> {
  let Store(ref mut map) = *store;
  info!("{}: truncate:{:?}", id, v);
  map.clear();
  response.set_ok(());
  Ok(())
}

fn read<Id: fmt::Display>(id: &Id, store: &mut Store, req: read_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let Store(ref mut map) = *store;
  let key = try!(req.get_key()).into();
  let val = map.get(key).map(|x| x.clone()).unwrap_or(vec![]);
  info!("{}: read:{:?}: -> {:?}", id, key, val);

  let mut data = response.init_ok_data(val.len() as u32);
  for i in 0..val.len() {
    let mut datum = data.borrow().get(i as u32);
    datum.set_value(&val[i])
  }
  Ok(())
}

fn write<Id: fmt::Display>(id: &Id, store: &mut Store, v: write_request::Reader, mut response: client_response::Builder) -> Result<(), ServerError> {
  let Store(ref mut map) = *store;
  let key = try!(v.get_key()).into();
  let val = try!(v.get_value()).into();
  info!("{}: write:{:?} -> {:?}", id, key, val);

  let entry = map.entry(key).or_insert(vec![]);
  entry.push(val);
  response.set_ok(());
  Ok(())
}

impl From<capnp::Error> for ServerError {
  fn from(err: capnp::Error) -> ServerError {
    ServerError::CapnpError(err)
  }
}

impl From<capnp::NotInSchema> for ServerError {
  fn from(err: capnp::NotInSchema) -> ServerError {
    ServerError::CapnpNotInSchema(err)
  }
}

impl From<io::Error> for ServerError {
  fn from(err: io::Error) -> ServerError {
    ServerError::IoError(err)
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fmt;
use std::io::Write;

use syn;

use crate::bindgen::cargo::cargo_metadata::Dependency;
use crate::bindgen::config::Config;
use crate::bindgen::writer::SourceWriter;

#[derive(PartialEq, Eq)]
enum DefineKey<'a> {
    Boolean(&'a str),
    Named(&'a str, &'a str),
}

impl<'a> DefineKey<'a> {
    fn load(key: &str) -> DefineKey {
        // TODO: dirty parser
        if !key.contains('=') {
            return DefineKey::Boolean(key);
        }

        let mut splits = key.trim().split('=');

        let name = match splits.next() {
            Some(n) => n.trim(),
            None => return DefineKey::Boolean(key),
        };

        let value = match splits.next() {
            Some(v) => v.trim(),
            None => return DefineKey::Boolean(key),
        };

        if splits.next().is_some() {
            return DefineKey::Boolean(key);
        }

        DefineKey::Named(name, value)
    }
}

#[derive(Debug, Clone)]
pub enum Cfg {
    Boolean(String),
    Named(String, String),
    Any(Vec<Cfg>),
    All(Vec<Cfg>),
    Not(Box<Cfg>),
}

impl fmt::Display for Cfg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Cfg::Boolean(key) => write!(f, "{}", key),
            Cfg::Named(key, value) => write!(f, "{} = {:?}", key, value),
            Cfg::Any(cfgs) => {
                write!(f, "any(")?;
                for (index, cfg) in cfgs.iter().enumerate() {
                    if index > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", cfg)?;
                }
                write!(f, ")")
            }
            Cfg::All(cfgs) => {
                write!(f, "all(")?;
                for (index, cfg) in cfgs.iter().enumerate() {
                    if index > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", cfg)?;
                }
                write!(f, ")")
            }
            Cfg::Not(cfg) => write!(f, "not({})", cfg),
        }
    }
}

impl Cfg {
    pub fn join(cfgs: &[Cfg]) -> Option<Cfg> {
        if cfgs.is_empty() {
            None
        } else {
            Some(Cfg::All(cfgs.to_owned()))
        }
    }

    pub fn append(parent: Option<&Cfg>, child: Option<Cfg>) -> Option<Cfg> {
        match (parent, child) {
            (None, None) => None,
            (None, Some(child)) => Some(child),
            (Some(parent), None) => Some(parent.clone()),
            (Some(parent), Some(child)) => Some(Cfg::All(vec![parent.clone(), child])),
        }
    }

    pub fn load(attrs: &[syn::Attribute]) -> Option<Cfg> {
        let mut configs = Vec::new();

        for attr in attrs {
            if let Ok(syn::Meta::List(syn::MetaList { path, nested, .. })) = attr.parse_meta() {
                if !path.is_ident("cfg") || nested.len() != 1 {
                    continue;
                }

                if let Some(config) = Cfg::load_single(nested.first().unwrap()) {
                    configs.push(config);
                }
            }
        }

        match configs.len() {
            0 => None,
            1 => Some(configs.pop().unwrap()),
            _ => Some(Cfg::All(configs)),
        }
    }

    pub fn load_metadata(dependency: &Dependency) -> Option<Cfg> {
        match &dependency.target {
            Some(target) => match syn::parse_str::<syn::Meta>(target) {
                Ok(target) => {
                    // Parsing succeeded using the #[cfg] syntax
                    if let syn::Meta::List(syn::MetaList { path, nested, .. }) = target {
                        if !path.is_ident("cfg") || nested.len() != 1 {
                            return None;
                        }
                        Cfg::load_single(nested.first().unwrap())
                    } else {
                        None
                    }
                }
                Err(_) =>
                // Parsing failed using #[cfg], this may be a literal target name
                {
                    Cfg::load_single(&syn::NestedMeta::Lit(syn::Lit::Str(syn::LitStr::new(
                        target,
                        proc_macro2::Span::call_site(),
                    ))))
                }
            },
            None => None,
        }
    }

    fn load_single(item: &syn::NestedMeta) -> Option<Cfg> {
        Some(match *item {
            syn::NestedMeta::Meta(syn::Meta::Path(ref path)) => {
                Cfg::Boolean(format!("{}", path.segments.first().unwrap().ident))
            }
            syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
                ref path,
                ref lit,
                ..
            })) => match *lit {
                syn::Lit::Str(ref value) => Cfg::Named(
                    format!("{}", path.segments.first().unwrap().ident),
                    value.value(),
                ),
                _ => return None,
            },
            syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList {
                ref path,
                ref nested,
                ..
            })) => {
                if path.is_ident("any") {
                    Cfg::Any(Cfg::load_list(nested.iter())?)
                } else if path.is_ident("all") {
                    Cfg::All(Cfg::load_list(nested.iter())?)
                } else if path.is_ident("not") {
                    if nested.len() != 1 {
                        return None;
                    }

                    Cfg::Not(Box::new(Cfg::load_single(&nested[0])?))
                } else {
                    return None;
                }
            }
            _ => return None,
        })
    }

    fn load_list<'a, I: Iterator<Item = &'a syn::NestedMeta>>(attrs: I) -> Option<Vec<Cfg>> {
        let mut configs = Vec::new();

        for attr in attrs {
            configs.push(Cfg::load_single(attr)?);
        }

        if configs.is_empty() {
            None
        } else {
            Some(configs)
        }
    }
}

pub trait ToCondition: Sized {
    fn to_condition(&self, config: &Config) -> Option<Condition>;
}

impl<'a> ToCondition for Option<Cfg> {
    fn to_condition(&self, config: &Config) -> Option<Condition> {
        self.as_ref()?.to_condition(config)
    }
}

impl<'a> ToCondition for Cfg {
    fn to_condition(&self, config: &Config) -> Option<Condition> {
        match *self {
            Cfg::Boolean(ref cfg_name) => {
                let define = config
                    .defines
                    .iter()
                    .find(|(key, ..)| DefineKey::Boolean(&cfg_name) == DefineKey::load(key));
                if let Some((_, define)) = define {
                    Some(Condition::Define(define.to_owned()))
                } else {
                    warn!(
                        "Missing `[defines]` entry for `{}` in cbindgen config.",
                        self,
                    );
                    None
                }
            }
            Cfg::Named(ref cfg_name, ref cfg_value) => {
                let define = config.defines.iter().find(|(key, ..)| {
                    DefineKey::Named(&cfg_name, &cfg_value) == DefineKey::load(key)
                });
                if let Some((_, define)) = define {
                    Some(Condition::Define(define.to_owned()))
                } else {
                    warn!(
                        "Missing `[defines]` entry for `{}` in cbindgen config.",
                        self,
                    );
                    None
                }
            }
            Cfg::Any(ref children) => {
                let conditions: Vec<_> = children
                    .iter()
                    .filter_map(|x| x.to_condition(config))
                    .collect();
                match conditions.len() {
                    0 => None,
                    1 => conditions.into_iter().next(),
                    _ => Some(Condition::Any(conditions)),
                }
            }
            Cfg::All(ref children) => {
                let cfgs: Vec<_> = children
                    .iter()
                    .filter_map(|x| x.to_condition(config))
                    .collect();
                match cfgs.len() {
                    0 => None,
                    1 => cfgs.into_iter().next(),
                    _ => Some(Condition::All(cfgs)),
                }
            }
            Cfg::Not(ref child) => child
                .to_condition(config)
                .map(|cfg| Condition::Not(Box::new(cfg))),
        }
    }
}

#[derive(Debug, Clone)]
pub enum Condition {
    Define(String),
    Any(Vec<Condition>),
    All(Vec<Condition>),
    Not(Box<Condition>),
}

impl Condition {
    fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
        match *self {
            Condition::Define(ref define) => {
                out.write("defined(");
                write!(out, "{}", define);
                out.write(")");
            }
            Condition::Any(ref conditions) => {
                out.write("(");
                for (i, condition) in conditions.iter().enumerate() {
                    if i != 0 {
                        out.write(" || ");
                    }
                    condition.write(config, out);
                }
                out.write(")");
            }
            Condition::All(ref conditions) => {
                out.write("(");
                for (i, condition) in conditions.iter().enumerate() {
                    if i != 0 {
                        out.write(" && ");
                    }
                    condition.write(config, out);
                }
                out.write(")");
            }
            Condition::Not(ref condition) => {
                out.write("!");
                condition.write(config, out);
            }
        }
    }
}

pub trait ConditionWrite {
    fn write_before<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>);
    fn write_after<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>);
}

impl ConditionWrite for Option<Condition> {
    fn write_before<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
        if let Some(ref cfg) = *self {
            out.push_set_spaces(0);
            out.write("#if ");
            cfg.write(config, out);
            out.pop_set_spaces();
            out.new_line();
        }
    }

    fn write_after<F: Write>(&self, _config: &Config, out: &mut SourceWriter<F>) {
        if self.is_some() {
            out.new_line();
            out.push_set_spaces(0);
            out.write("#endif");
            out.pop_set_spaces();
        }
    }
}
<commit_msg>ir: Minor cleanup to the cfg code.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fmt;
use std::io::Write;

use syn;

use crate::bindgen::cargo::cargo_metadata::Dependency;
use crate::bindgen::config::Config;
use crate::bindgen::writer::SourceWriter;

#[derive(PartialEq, Eq)]
enum DefineKey<'a> {
    Boolean(&'a str),
    Named(&'a str, &'a str),
}

impl<'a> DefineKey<'a> {
    fn load(key: &str) -> DefineKey {
        // TODO: dirty parser
        if !key.contains('=') {
            return DefineKey::Boolean(key);
        }

        let mut splits = key.trim().split('=');

        let name = match splits.next() {
            Some(n) => n.trim(),
            None => return DefineKey::Boolean(key),
        };

        let value = match splits.next() {
            Some(v) => v.trim(),
            None => return DefineKey::Boolean(key),
        };

        if splits.next().is_some() {
            return DefineKey::Boolean(key);
        }

        DefineKey::Named(name, value)
    }
}

#[derive(Debug, Clone)]
pub enum Cfg {
    Boolean(String),
    Named(String, String),
    Any(Vec<Cfg>),
    All(Vec<Cfg>),
    Not(Box<Cfg>),
}

impl fmt::Display for Cfg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Cfg::Boolean(key) => write!(f, "{}", key),
            Cfg::Named(key, value) => write!(f, "{} = {:?}", key, value),
            Cfg::Any(cfgs) => {
                write!(f, "any(")?;
                for (index, cfg) in cfgs.iter().enumerate() {
                    if index > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", cfg)?;
                }
                write!(f, ")")
            }
            Cfg::All(cfgs) => {
                write!(f, "all(")?;
                for (index, cfg) in cfgs.iter().enumerate() {
                    if index > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{}", cfg)?;
                }
                write!(f, ")")
            }
            Cfg::Not(cfg) => write!(f, "not({})", cfg),
        }
    }
}

impl Cfg {
    pub fn join(cfgs: &[Cfg]) -> Option<Cfg> {
        if cfgs.is_empty() {
            None
        } else {
            Some(Cfg::All(cfgs.to_owned()))
        }
    }

    pub fn append(parent: Option<&Cfg>, child: Option<Cfg>) -> Option<Cfg> {
        match (parent, child) {
            (None, None) => None,
            (None, Some(child)) => Some(child),
            (Some(parent), None) => Some(parent.clone()),
            (Some(parent), Some(child)) => Some(Cfg::All(vec![parent.clone(), child])),
        }
    }

    pub fn load(attrs: &[syn::Attribute]) -> Option<Cfg> {
        let mut configs = Vec::new();

        for attr in attrs {
            if let Ok(syn::Meta::List(syn::MetaList { path, nested, .. })) = attr.parse_meta() {
                if !path.is_ident("cfg") || nested.len() != 1 {
                    continue;
                }

                if let Some(config) = Cfg::load_single(nested.first().unwrap()) {
                    configs.push(config);
                }
            }
        }

        match configs.len() {
            0 => None,
            1 => Some(configs.pop().unwrap()),
            _ => Some(Cfg::All(configs)),
        }
    }

    pub fn load_metadata(dependency: &Dependency) -> Option<Cfg> {
        let target = dependency.target.as_ref()?;
        match syn::parse_str::<syn::Meta>(target) {
            Ok(target) => {
                // Parsing succeeded using the #[cfg] syntax
                if let syn::Meta::List(syn::MetaList { path, nested, .. }) = target {
                    if !path.is_ident("cfg") || nested.len() != 1 {
                        return None;
                    }
                    Cfg::load_single(nested.first().unwrap())
                } else {
                    None
                }
            }
            Err(_) => {
                // Parsing failed using #[cfg], this may be a literal target
                // name
                Cfg::load_single(&syn::NestedMeta::Lit(syn::Lit::Str(syn::LitStr::new(
                    target,
                    proc_macro2::Span::call_site(),
                ))))
            }
        }
    }

    fn load_single(item: &syn::NestedMeta) -> Option<Cfg> {
        Some(match *item {
            syn::NestedMeta::Meta(syn::Meta::Path(ref path)) => {
                Cfg::Boolean(format!("{}", path.segments.first().unwrap().ident))
            }
            syn::NestedMeta::Meta(syn::Meta::NameValue(syn::MetaNameValue {
                ref path,
                ref lit,
                ..
            })) => match *lit {
                syn::Lit::Str(ref value) => Cfg::Named(
                    format!("{}", path.segments.first().unwrap().ident),
                    value.value(),
                ),
                _ => return None,
            },
            syn::NestedMeta::Meta(syn::Meta::List(syn::MetaList {
                ref path,
                ref nested,
                ..
            })) => {
                if path.is_ident("any") {
                    Cfg::Any(Cfg::load_list(nested.iter())?)
                } else if path.is_ident("all") {
                    Cfg::All(Cfg::load_list(nested.iter())?)
                } else if path.is_ident("not") {
                    if nested.len() != 1 {
                        return None;
                    }

                    Cfg::Not(Box::new(Cfg::load_single(&nested[0])?))
                } else {
                    return None;
                }
            }
            _ => return None,
        })
    }

    fn load_list<'a, I: Iterator<Item = &'a syn::NestedMeta>>(attrs: I) -> Option<Vec<Cfg>> {
        let mut configs = Vec::new();

        for attr in attrs {
            configs.push(Cfg::load_single(attr)?);
        }

        if configs.is_empty() {
            None
        } else {
            Some(configs)
        }
    }
}

pub trait ToCondition: Sized {
    fn to_condition(&self, config: &Config) -> Option<Condition>;
}

impl<'a> ToCondition for Option<Cfg> {
    fn to_condition(&self, config: &Config) -> Option<Condition> {
        self.as_ref()?.to_condition(config)
    }
}

impl<'a> ToCondition for Cfg {
    fn to_condition(&self, config: &Config) -> Option<Condition> {
        match *self {
            Cfg::Boolean(ref cfg_name) => {
                let define = config
                    .defines
                    .iter()
                    .find(|(key, ..)| DefineKey::Boolean(&cfg_name) == DefineKey::load(key));
                if let Some((_, define)) = define {
                    Some(Condition::Define(define.to_owned()))
                } else {
                    warn!(
                        "Missing `[defines]` entry for `{}` in cbindgen config.",
                        self,
                    );
                    None
                }
            }
            Cfg::Named(ref cfg_name, ref cfg_value) => {
                let define = config.defines.iter().find(|(key, ..)| {
                    DefineKey::Named(&cfg_name, &cfg_value) == DefineKey::load(key)
                });
                if let Some((_, define)) = define {
                    Some(Condition::Define(define.to_owned()))
                } else {
                    warn!(
                        "Missing `[defines]` entry for `{}` in cbindgen config.",
                        self,
                    );
                    None
                }
            }
            Cfg::Any(ref children) => {
                let conditions: Vec<_> = children
                    .iter()
                    .filter_map(|x| x.to_condition(config))
                    .collect();
                match conditions.len() {
                    0 => None,
                    1 => conditions.into_iter().next(),
                    _ => Some(Condition::Any(conditions)),
                }
            }
            Cfg::All(ref children) => {
                let cfgs: Vec<_> = children
                    .iter()
                    .filter_map(|x| x.to_condition(config))
                    .collect();
                match cfgs.len() {
                    0 => None,
                    1 => cfgs.into_iter().next(),
                    _ => Some(Condition::All(cfgs)),
                }
            }
            Cfg::Not(ref child) => child
                .to_condition(config)
                .map(|cfg| Condition::Not(Box::new(cfg))),
        }
    }
}

#[derive(Debug, Clone)]
pub enum Condition {
    Define(String),
    Any(Vec<Condition>),
    All(Vec<Condition>),
    Not(Box<Condition>),
}

impl Condition {
    fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
        match *self {
            Condition::Define(ref define) => {
                out.write("defined(");
                write!(out, "{}", define);
                out.write(")");
            }
            Condition::Any(ref conditions) => {
                out.write("(");
                for (i, condition) in conditions.iter().enumerate() {
                    if i != 0 {
                        out.write(" || ");
                    }
                    condition.write(config, out);
                }
                out.write(")");
            }
            Condition::All(ref conditions) => {
                out.write("(");
                for (i, condition) in conditions.iter().enumerate() {
                    if i != 0 {
                        out.write(" && ");
                    }
                    condition.write(config, out);
                }
                out.write(")");
            }
            Condition::Not(ref condition) => {
                out.write("!");
                condition.write(config, out);
            }
        }
    }
}

pub trait ConditionWrite {
    fn write_before<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>);
    fn write_after<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>);
}

impl ConditionWrite for Option<Condition> {
    fn write_before<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
        if let Some(ref cfg) = *self {
            out.push_set_spaces(0);
            out.write("#if ");
            cfg.write(config, out);
            out.pop_set_spaces();
            out.new_line();
        }
    }

    fn write_after<F: Write>(&self, _config: &Config, out: &mut SourceWriter<F>) {
        if self.is_some() {
            out.new_line();
            out.push_set_spaces(0);
            out.write("#endif");
            out.pop_set_spaces();
        }
    }
}
<|endoftext|>