<commit_before>#![allow(dead_code)]
use std::intrinsics::get_tydesc;

struct Zero;
struct Succ<T: NonNeg>;
struct Pred<T: NonPos>;

trait Peano {}
trait NonZero: Peano {}
trait NonNeg: Peano {}
trait NonPos: Peano {}
trait Pos: Peano + NonZero + NonNeg {}
trait Neg: Peano + NonZero + NonPos {}

impl Peano for Zero {}
impl NonNeg for Zero {}
impl NonPos for Zero {}

impl<T: NonNeg> Peano for Succ<T> {}
impl<T: NonNeg> NonNeg for Succ<T> {}
impl<T: NonNeg> NonZero for Succ<T> {}
impl<T: NonNeg> Pos for Succ<T> {}

impl<T: NonPos> Peano for Pred<T> {}
impl<T: NonPos> NonPos for Pred<T> {}
impl<T: NonPos> NonZero for Pred<T> {}
impl<T: NonPos> Neg for Pred<T> {}

trait AddPeano<Rhs> {
    type Result;
}

/// Adding things to zero (e.g. 0 + 3)
impl<Rhs: Peano> AddPeano<Rhs> for Zero {
    type Result = Rhs;
}

/// Adding positive numbers (e.g. 1 + 2)
impl<T: NonNeg + AddPeano<Succ<Rhs>>, Rhs: NonNeg> AddPeano<Succ<Rhs>> for Succ<T> {
    type Result = Succ<<T as AddPeano<Succ<Rhs>>>::Result>;
}
/// Adding zero to positive numbers (e.g. 3 + 0)
impl<T: NonNeg> AddPeano<Zero> for Succ<T> {
    type Result = Succ<T>;
}
/// Adding negative numbers to positive numbers (e.g. 2 + -3)
impl<T: NonNeg + AddPeano<Rhs>, Rhs: NonPos> AddPeano<Pred<Rhs>> for Succ<T> {
    type Result = <T as AddPeano<Rhs>>::Result;
}

/// Adding negative numbers (e.g. -1 + -2)
impl<T: NonPos + AddPeano<Pred<Rhs>>, Rhs: NonPos> AddPeano<Pred<Rhs>> for Pred<T> {
    type Result = Pred<<T as AddPeano<Pred<Rhs>>>::Result>;
}
/// Adding zero to negative numbers (e.g. -3 + 0)
impl<T: NonPos> AddPeano<Zero> for Pred<T> {
    type Result = Pred<T>;
}
/// Adding positive numbers to negative numbers (e.g. -2 + 3)
impl<T: NonPos + AddPeano<Rhs>, Rhs: NonNeg> AddPeano<Succ<Rhs>> for Pred<T> {
    type Result = <T as AddPeano<Rhs>>::Result;
}

fn print_type<T>() {
    let type_name = unsafe { (*get_tydesc::<T>()).name };
    println!("{}", type_name);
}

#[test]
fn count() {
    type One = Succ<Zero>;
    type Two = Succ<One>;
    type Three = Succ<Two>;

    type NegOne = Pred<Zero>;
    type NegTwo = Pred<NegOne>;
    type NegThree = Pred<NegTwo>;

    print!("      1 = ");
    print_type::<One>();

    print!("     -1 = ");
    print_type::<NegOne>();

    print!(" 0 +  2 = ");
    print_type::<<Zero as AddPeano<Two>>::Result>();
    print!(" 2 +  0 = ");
    print_type::<<Two as AddPeano<Zero>>::Result>();

    print!(" 1 +  2 = ");
    print_type::<<One as AddPeano<Two>>::Result>();
    print!(" 2 +  1 = ");
    print_type::<<Two as AddPeano<One>>::Result>();

    print!(" 1 + -1 = ");
    print_type::<<One as AddPeano<NegOne>>::Result>();
    print!(" 1 + -2 = ");
    print_type::<<One as AddPeano<NegTwo>>::Result>();
    print!(" 2 + -1 = ");
    print_type::<<Two as AddPeano<NegOne>>::Result>();

    print!("-2 +  0 = ");
    print_type::<<NegTwo as AddPeano<Zero>>::Result>();

    print!("-1 + -2 = ");
    print_type::<<NegOne as AddPeano<NegTwo>>::Result>();
    print!("-2 + -1 = ");
    print_type::<<NegTwo as AddPeano<NegOne>>::Result>();

    print!("-1 +  1 = ");
    print_type::<<NegOne as AddPeano<One>>::Result>();
    print!("-1 +  2 = ");
    print_type::<<NegOne as AddPeano<Two>>::Result>();
    print!("-2 +  1 = ");
    print_type::<<NegTwo as AddPeano<One>>::Result>();
}
<commit_msg>Add subtraction and negation for Peano -- at full group status now.<commit_after>#![allow(dead_code)]
use std::intrinsics::get_tydesc;

struct Zero;
struct Succ<T: NonNeg>;
struct Pred<T: NonPos>;

type One = Succ<Zero>;

trait Peano {}
trait NonZero: Peano {}
trait NonNeg: Peano {}
trait NonPos: Peano {}
trait Pos: Peano + NonZero + NonNeg {}
trait Neg: Peano + NonZero + NonPos {}

impl Peano for Zero {}
impl NonNeg for Zero {}
impl NonPos for Zero {}

impl<T: NonNeg> Peano for Succ<T> {}
impl<T: NonNeg> NonNeg for Succ<T> {}
impl<T: NonNeg> NonZero for Succ<T> {}
impl<T: NonNeg> Pos for Succ<T> {}

impl<T: NonPos> Peano for Pred<T> {}
impl<T: NonPos> NonPos for Pred<T> {}
impl<T: NonPos> NonZero for Pred<T> {}
impl<T: NonPos> Neg for Pred<T> {}

trait AddPeano<Rhs> {
    type Result;
}

/// Adding things to zero (e.g. 0 + 3)
impl<Rhs: Peano> AddPeano<Rhs> for Zero {
    type Result = Rhs;
}

/// Adding positive numbers (e.g. 1 + 2)
impl<T: NonNeg + AddPeano<Succ<Rhs>>, Rhs: NonNeg> AddPeano<Succ<Rhs>> for Succ<T> {
    type Result = Succ<<T as AddPeano<Succ<Rhs>>>::Result>;
}
/// Adding zero to positive numbers (e.g. 3 + 0)
impl<T: NonNeg> AddPeano<Zero> for Succ<T> {
    type Result = Succ<T>;
}
/// Adding negative numbers to positive numbers (e.g. 2 + -3)
impl<T: NonNeg + AddPeano<Rhs>, Rhs: NonPos> AddPeano<Pred<Rhs>> for Succ<T> {
    type Result = <T as AddPeano<Rhs>>::Result;
}

/// Adding negative numbers (e.g. -1 + -2)
impl<T: NonPos + AddPeano<Pred<Rhs>>, Rhs: NonPos> AddPeano<Pred<Rhs>> for Pred<T> {
    type Result = Pred<<T as AddPeano<Pred<Rhs>>>::Result>;
}
/// Adding zero to negative numbers (e.g. -3 + 0)
impl<T: NonPos> AddPeano<Zero> for Pred<T> {
    type Result = Pred<T>;
}
/// Adding positive numbers to negative numbers (e.g. -2 + 3)
impl<T: NonPos + AddPeano<Rhs>, Rhs: NonNeg> AddPeano<Succ<Rhs>> for Pred<T> {
    type Result = <T as AddPeano<Rhs>>::Result;
}

trait Negate {
    type Result;
}
impl Negate for Zero {
    type Result = Zero;
}
impl<T: NonNeg + Negate> Negate for Succ<T> {
    type Result = Pred<<T as Negate>::Result>;
}
impl<T: NonPos + Negate> Negate for Pred<T> {
    type Result = Succ<<T as Negate>::Result>;
}

trait SubPeano<Rhs> {
    type Result;
}

/// Subtracting from zero
impl<Rhs: Peano + Negate> SubPeano<Rhs> for Zero {
    type Result = <Rhs as Negate>::Result;
}

/// Subtracting positive numbers from positive numbers (e.g. 3 - 4)
impl<T: NonNeg + SubPeano<Rhs>, Rhs: NonNeg> SubPeano<Succ<Rhs>> for Succ<T> {
    type Result = <T as SubPeano<Rhs>>::Result;
}
/// Subtracting zero from positive numbers (e.g. 3 - 0)
impl<T: NonNeg> SubPeano<Zero> for Succ<T> {
    type Result = Succ<T>;
}
/// Subtracting negative numbers from positive numbers (e.g. 3 - -4)
impl<T: NonNeg + SubPeano<Rhs>, Rhs: NonPos> SubPeano<Pred<Rhs>> for Succ<T> {
    type Result = Succ<Succ<<T as SubPeano<Rhs>>::Result>>;
}

/// Subtracting positive numbers from negative numbers (e.g. -3 - 4)
impl<T: NonPos + SubPeano<Rhs>, Rhs: NonNeg> SubPeano<Succ<Rhs>> for Pred<T> {
    type Result = Pred<Pred<<T as SubPeano<Rhs>>::Result>>;
}
/// Subtracting zero from negative numbers (e.g. -3 - 0)
impl<T: NonPos> SubPeano<Zero> for Pred<T> {
    type Result = Pred<T>;
}
/// Subtracting negative numbers from negative numbers (e.g. -3 - -4)
impl<T: NonPos + SubPeano<Rhs>, Rhs: NonPos> SubPeano<Pred<Rhs>> for Pred<T> {
    type Result = <T as SubPeano<Rhs>>::Result;
}

// trait MulPeano<Rhs> {
//     type Result;
// }

// /// Multiplying zero by things (e.g. 0 * 7)
// impl<Rhs: Peano> MulPeano<Rhs> for Zero {
//     type Result = Zero;
// }

// /// Multiplying non-negative integers (e.g. 1 * 8)
// impl<T, Rhs> MulPeano<Rhs> for Succ<T>
//     where T: NonNeg + MulPeano<Rhs>, Rhs: AddPeano<<T as MulPeano<Rhs>>::Result> {
//         type Result = <Rhs as AddPeano<<T as MulPeano<Rhs>>::Result>>::Result;
// }

// /// Multiplying non-positive integers (e.g. -1 * -8)
// impl<T, Rhs> MulPeano<Rhs> for Succ<T>
//     where T: NonPos + MulPeano<Rhs>, Rhs: AddPeano<<T as MulPeano<Rhs>>::Result> {
//         type Result = <Rhs as AddPeano<<T as MulPeano<Rhs>>::Result>>::Result;
// }

fn print_type<T>() {
    let type_name = unsafe { (*get_tydesc::<T>()).name };
    println!("{}", type_name);
}

#[test]
fn count() {
    type One = Succ<Zero>;
    type Two = Succ<One>;
    type Three = Succ<Two>;

    type NegOne = Pred<Zero>;
    type NegTwo = Pred<NegOne>;
    type NegThree = Pred<NegTwo>;

    println!("\nA couple numbers:");
    print!("      0 = ");
    print_type::<Zero>();
    print!("      1 = ");
    print_type::<One>();
    print!("      2 = ");
    print_type::<Two>();

    print!("     -1 = ");
    print_type::<NegOne>();
    print!("     -2 = ");
    print_type::<NegTwo>();

    println!("\nAddition:");

    print!(" 0 +  0 = ");
    print_type::<<Zero as AddPeano<Zero>>::Result>();
    print!(" 0 +  2 = ");
    print_type::<<Zero as AddPeano<Two>>::Result>();
    print!(" 2 +  0 = ");
    print_type::<<Two as AddPeano<Zero>>::Result>();

    print!(" 1 +  2 = ");
    print_type::<<One as AddPeano<Two>>::Result>();
    print!(" 2 +  1 = ");
    print_type::<<Two as AddPeano<One>>::Result>();

    print!(" 1 + -1 = ");
    print_type::<<One as AddPeano<NegOne>>::Result>();
    print!(" 1 + -2 = ");
    print_type::<<One as AddPeano<NegTwo>>::Result>();
    print!(" 2 + -1 = ");
    print_type::<<Two as AddPeano<NegOne>>::Result>();

    print!("-2 +  0 = ");
    print_type::<<NegTwo as AddPeano<Zero>>::Result>();

    print!("-1 + -2 = ");
    print_type::<<NegOne as AddPeano<NegTwo>>::Result>();
    print!("-2 + -1 = ");
    print_type::<<NegTwo as AddPeano<NegOne>>::Result>();

    print!("-1 +  1 = ");
    print_type::<<NegOne as AddPeano<One>>::Result>();
    print!("-1 +  2 = ");
    print_type::<<NegOne as AddPeano<Two>>::Result>();
    print!("-2 +  1 = ");
    print_type::<<NegTwo as AddPeano<One>>::Result>();

    println!("\nNegation:");
    print!("     -0 = ");
    print_type::<<Zero as Negate>::Result>();
    print!("     -2 = ");
    print_type::<<Two as Negate>::Result>();
    print!("    --2 = ");
    print_type::<<NegTwo as Negate>::Result>();

    println!("\nSubtraction:");
    print!(" 0 -  0 = ");
    print_type::<<Zero as SubPeano<Zero>>::Result>();
    print!(" 2 -  0 = ");
    print_type::<<Two as SubPeano<Zero>>::Result>();
    print!(" 0 -  2 = ");
    print_type::<<Zero as SubPeano<Two>>::Result>();
    print!(" 3 -  2 = ");
    print_type::<<Three as SubPeano<Two>>::Result>();
    print!(" 2 -  3 = ");
    print_type::<<Two as SubPeano<Three>>::Result>();
    print!(" 1 - -2 = ");
    print_type::<<One as SubPeano<NegTwo>>::Result>();

    print!("-3 - -2 = ");
    print_type::<<NegThree as SubPeano<NegTwo>>::Result>();
    print!("-2 - -3 = ");
    print_type::<<NegTwo as SubPeano<NegThree>>::Result>();
    print!("-1 -  2 = ");
    print_type::<<NegOne as SubPeano<Two>>::Result>();

    // println!("\nMultiplication:");
    // print!(" 3 *  0 = ");
    // print_type::<<Three as MulPeano<Zero>>::Result>();
    // print!(" 0 *  3 = ");
    // print_type::<<Zero as MulPeano<Three>>::Result>();
    // print!(" 2 *  2 = ");
    // print_type::<<Two as MulPeano<Two>>::Result>();

}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::result;
use log;

#[derive(Debug)]
pub struct JobRequireVariablePair {
    pub id: i32,
    pub fk_job: i32,
    pub fk_variable_pair: i32,
}

pub fn table_create_job_require_variable_pair(conn: &Connection) {
    let load_table = conn.execute(
        "CREATE TABLE JOB_REQUIRE_VALUE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER NOT NULL,
                  fk_variable_pair INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable_pair) REFERENCES VARIABLE_PAIR(id) ON UPDATE CASCADE
                  )",
        &[],
    );
    if load_table.is_err() {
        error!(
            "table_create_job_require_variable_pair Failed {:?}",
            load_table
        );
        return;
    }
    load_table.unwrap();
}

pub fn insert_job_require_variable_pair(
    conn: &Connection,
    job: &i32,
    variable_pair: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariablePair {
        id: 0,
        fk_job: *job,
        fk_variable_pair: *variable_pair,
    };
    let variable_pair_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VALUE (fk_job, fk_variable_pair)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable_pair],
    );
    if variable_pair_instance.is_err() {
        return Err("Insert failed");
    }
    variable_pair_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable_pair(conn: &Connection) -> Vec<JobRequireVariablePair> {
    let mut stmt = conn.prepare(
        "SELECT id, fk_job, fk_variable_pair  FROM JOB_REQUIRE_VALUE",
    ).unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariablePair {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable_pair: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariablePair>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_pair_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable_pair FROM JOB_REQUIRE_VALUE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariablePair {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable_pair: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found variable_pair {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_pair_by_all(
    conn: &Connection,
    job: &i32,
    variable_pair: &i32,
) -> Result<i32, &'static str> {
    let mut output = 0;
    let mut stmt = conn.prepare("SELECT JOB_REQUIRE_VALUE.id, JOB_REQUIRE_VALUE.fk_job, JOB_REQUIRE_VALUE.fk_variable_pair  FROM JOB_REQUIRE_VALUE WHERE JOB_REQUIRE_VALUE.fk_job = ?1 AND JOB_REQUIRE_VALUE.fk_variable_pair = ?2").unwrap();
    let variable_pair_iter = stmt.query_map(&[job, variable_pair], |row| {
        JobRequireVariablePair {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable_pair: row.get(2),
        }
    });
    if variable_pair_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = variable_pair_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<commit_msg>Remoive unused 'use'<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct JobRequireVariablePair {
    pub id: i32,
    pub fk_job: i32,
    pub fk_variable_pair: i32,
}

pub fn table_create_job_require_variable_pair(conn: &Connection) {
    let load_table = conn.execute(
        "CREATE TABLE JOB_REQUIRE_VALUE (
                  id            INTEGER PRIMARY KEY ASC,
                  fk_job           INTEGER NOT NULL,
                  fk_variable_pair INTEGER NOT NULL,
                  FOREIGN KEY(fk_job) REFERENCES JOB(id) ON UPDATE CASCADE
                  FOREIGN KEY(fk_variable_pair) REFERENCES VARIABLE_PAIR(id) ON UPDATE CASCADE
                  )",
        &[],
    );
    if load_table.is_err() {
        error!(
            "table_create_job_require_variable_pair Failed {:?}",
            load_table
        );
        return;
    }
    load_table.unwrap();
}

pub fn insert_job_require_variable_pair(
    conn: &Connection,
    job: &i32,
    variable_pair: &i32,
) -> Result<i32, &'static str> {
    let me = JobRequireVariablePair {
        id: 0,
        fk_job: *job,
        fk_variable_pair: *variable_pair,
    };
    let variable_pair_instance = conn.execute(
        "INSERT INTO JOB_REQUIRE_VALUE (fk_job, fk_variable_pair)
                  VALUES (?1, ?2)",
        &[&me.fk_job, &me.fk_variable_pair],
    );
    if variable_pair_instance.is_err() {
        return Err("Insert failed");
    }
    variable_pair_instance.unwrap();
    return Ok(0);
}

pub fn list_job_require_variable_pair(conn: &Connection) -> Vec<JobRequireVariablePair> {
    let mut stmt = conn.prepare(
        "SELECT id, fk_job, fk_variable_pair  FROM JOB_REQUIRE_VALUE",
    ).unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| {
        JobRequireVariablePair {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable_pair: row.get(2),
        }
    });
    let mut items = Vec::<JobRequireVariablePair>::new();
    if wraped_fs_file_iter.is_err() {
        return items;

    }
    let fs_file_iter = wraped_fs_file_iter.unwrap();
    for person in fs_file_iter {

        items.push(person.unwrap());
    }
    return items;
}

pub fn job_require_variable_pair_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, fk_job, fk_variable_pair FROM JOB_REQUIRE_VALUE")
        .unwrap();
    let person_iter = stmt.query_map(&[], |row| {
        JobRequireVariablePair {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable_pair: row.get(2),
        }
    }).unwrap();

    for person in person_iter {
        info!("Found variable_pair {:?}", person.unwrap());
    }
}

pub fn pk_job_require_variable_pair_by_all(
    conn: &Connection,
    job: &i32,
    variable_pair: &i32,
) -> Result<i32, &'static str> {
    let mut output = 0;
    let mut stmt = conn.prepare("SELECT JOB_REQUIRE_VALUE.id, JOB_REQUIRE_VALUE.fk_job, JOB_REQUIRE_VALUE.fk_variable_pair  FROM JOB_REQUIRE_VALUE WHERE JOB_REQUIRE_VALUE.fk_job = ?1 AND JOB_REQUIRE_VALUE.fk_variable_pair = ?2").unwrap();
    let variable_pair_iter = stmt.query_map(&[job, variable_pair], |row| {
        JobRequireVariablePair {
            id: row.get(0),
            fk_job: row.get(1),
            fk_variable_pair: row.get(2),
        }
    });
    if variable_pair_iter.is_err() {
        return Err("Insert failed dfdf");
    }
    let result = variable_pair_iter.unwrap();
    let mut found = 0;
    let mut items = Vec::<i32>::new();
    for person in result {
        let bill = person.unwrap();
        output = bill.id;
        found = 1;
    }
    if found != 0 {
        return Ok(output);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>// TODO:
//
// - Better error reporting

extern crate libc;

use std::collections::HashMap;
use std::ops::BitOr;

pub struct EvLoop<Ctx> {
    fds: HashMap<libc::c_int, Handler<Ctx>>,
}

enum Handler<Ctx> {
    Timer { cb: Box<Fn(&mut EvLoopController, &mut Ctx) -> ()> },
    Signal { cb: Box<Fn(&mut EvLoopController, &mut Ctx) -> ()> },
    Fd { evs: FdEv, cb: Box<Fn(FdEv, &mut EvLoopController, &mut Ctx) -> ()> },
}

/// File descriptor events. Use bitwise or to combine.
pub struct FdEv(libc::c_short);

pub const READ_EV: FdEv = FdEv(libc::POLLIN);
pub const WRITE_EV: FdEv = FdEv(libc::POLLOUT);
pub const ERR_EV: FdEv = FdEv(libc::POLLERR);
pub const HUP_EV: FdEv = FdEv(libc::POLLHUP);

impl BitOr for FdEv {
    type Output = FdEv;

    fn bitor(self, rhs: FdEv) -> FdEv {
        FdEv(self.0 | rhs.0)
    }
}

pub struct TimerRef(libc::c_int);
pub struct SignalRef(libc::c_int);

extern "C" {
    fn timerfd_create(
        clockid: libc::c_int,
        flags: libc::c_int
        ) -> libc::c_int;

    fn timerfd_settime(
        fd: libc::c_int,
        flags: libc::c_int,
        new_value: *const itimerspec,
        old_value: *mut itimerspec
        ) -> libc::c_int;

    // fn timerfd_gettime(
    //     fd: libc::c_int,
    //     curr_value: *mut libc::itimerspec
    //     ) -> libc::c_int;
}

// Can't find itimerspec in libc
#[repr(C)]
pub struct itimerspec {
    it_interval: libc::timespec,
    it_value: libc::timespec,
}

pub struct EvLoopController<'a> {
    stop_ref: &'a mut bool,
    remove_self: &'a mut bool,
}

impl<'a> EvLoopController<'a> {
    pub fn stop(&mut self) {
        *self.stop_ref = true;
    }

    pub fn remove_self(&mut self) {
        *self.remove_self = true;
    }
}

fn mk_timespec(millis: i64) -> libc::timespec {
    let secs: i64 = millis / 1000;
    let nanos: i64 = (millis % 1000) * 1000000;
    libc::timespec { tv_sec: secs, tv_nsec: nanos }
}

impl<Ctx> EvLoop<Ctx> {
    pub fn new() -> EvLoop<Ctx> {
        EvLoop { fds: HashMap::new() }
    }

    /// Register a non-blocking socket. Use the same fd for unregister.
    pub fn add_fd(&mut self, fd: libc::c_int, evs: FdEv, cb: Box<Fn(FdEv, &mut EvLoopController, &mut Ctx) -> ()>) {
        self.fds.insert(fd, Handler::Fd { evs: evs, cb: cb });
    }

    pub fn remove_fd(&mut self, fd: libc::c_int) {
        self.fds.remove(&fd);
    }

    /// `timeout` and `period` in milliseconds. `timeout` must be non-zero for this to work. If
    /// `period` is non-zero, timer expires repeatedly after the initial timeout.
    pub fn add_timer(&mut self, timeout: i64, period: i64, cb: Box<Fn(&mut EvLoopController, &mut Ctx) -> ()>) -> TimerRef {
        let fd = unsafe { timerfd_create(libc::CLOCK_MONOTONIC, libc::EFD_NONBLOCK) };
        assert!(fd != -1);

        let timeout_spec = mk_timespec(timeout);
        let period_spec = mk_timespec(period);
        let timerspec = itimerspec { it_interval: period_spec, it_value: timeout_spec };

        assert!(unsafe { timerfd_settime(fd, 0, &timerspec, std::ptr::null_mut()) } != -1);
        self.fds.insert(fd, Handler::Timer { cb: cb });
        TimerRef(fd)
    }

    pub fn remove_timer(&mut self, timer_ref: TimerRef) {
        assert!(unsafe { libc::close(timer_ref.0) } != -1);
        self.fds.remove(&timer_ref.0);
    }

    pub fn add_signal(&mut self, sigs: &libc::sigset_t, cb: Box<Fn(&mut EvLoopController, &mut Ctx) -> ()>) -> SignalRef {
        // Block the signals we handle using signalfd() so they don't cause signal handlers to run
        assert!(unsafe { libc::sigprocmask(libc::SIG_BLOCK, sigs as *const libc::sigset_t, std::ptr::null_mut()) } != -1);
        let fd = unsafe { libc::signalfd(-1, sigs, libc::EFD_NONBLOCK) };
        assert!(fd != -1);
        self.fds.insert(fd, Handler::Signal { cb: cb });
        SignalRef(fd)
    }

    pub fn remove_signal(&mut self, signal_ref: SignalRef) {
        self.fds.remove(&signal_ref.0);
    }

    pub fn run(&mut self, mut ctx: Ctx) -> Ctx {
        let mut stop = false;
        while !stop {
            let mut fds: Vec<libc::pollfd> = Vec::with_capacity(self.fds.len());

            for (fd, handler) in self.fds.iter() {
                match handler {
                    &Handler::Timer{ .. } | &Handler::Signal{ .. } => {
                        fds.push(libc::pollfd { fd: *fd, events: libc::POLLIN, revents: 0 });
                    }
                    &Handler::Fd{ ref evs, .. } => {
                        fds.push(libc::pollfd { fd: *fd, events: evs.0, revents: 0 });
                    }
                }
            }

            assert!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as u64, -1) } != -1);

            for pollfd in fds {
                if pollfd.revents != 0 {

                    let mut remove_fd = false;
                    {
                        let mut controller = EvLoopController { stop_ref: &mut stop, remove_self: &mut remove_fd };

                        match self.fds.get(&pollfd.fd).unwrap() {
                            &Handler::Timer{ ref cb } | &Handler::Signal{ ref cb } => {
                                cb(&mut controller, &mut ctx);
                            }
                            &Handler::Fd{ ref cb, .. } => {
                                cb(FdEv(pollfd.revents), &mut controller, &mut ctx);
                            }
                        }
                    }

                    if remove_fd {
                        self.fds.remove(&pollfd.fd);
                    }
                }
            }
        }
        ctx
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    use std::rc::Rc;

    #[test]
    fn it_works() {
        let it_worked: Rc<RefCell<bool>> = Rc::new(RefCell::new(false));

        let mut ev_loop = EvLoop::new();
        {
            let it_worked_clone = it_worked.clone();
            ev_loop.add_timer(100, 100, Box::new(move |ctrl, _| {
                *it_worked_clone.borrow_mut() = true;
                ctrl.stop();
            }));
        }
        ev_loop.run(());

        assert!(*(*it_worked).borrow());
    }

    #[test]
    fn it_works_2() {
        struct Ctx {
            cb1: bool,
            cb2: bool,
            cb3: bool,
        }

        let mut ev_loop: EvLoop<Ctx> = EvLoop::new();

        ev_loop.add_timer(100, 100, Box::new(move |ctrl, ctx| {
            assert!(ctx.cb1 == false);
            ctx.cb1 = true;
            ctrl.remove_self();
        }));

        ev_loop.add_timer(100, 100, Box::new(move |ctrl, ctx| {
            assert!(ctx.cb2 == false);
            ctx.cb2 = true;
            ctrl.remove_self();
        }));

        {
            let fd = unsafe { timerfd_create(libc::CLOCK_MONOTONIC, libc::EFD_NONBLOCK) };
            assert!(fd != -1);

            let timeout_spec = mk_timespec(300);
            let period_spec = mk_timespec(300);
            let timerspec = itimerspec { it_interval: period_spec, it_value: timeout_spec };

            assert!(unsafe { timerfd_settime(fd, 0, &timerspec, std::ptr::null_mut()) } != -1);
            ev_loop.add_fd(fd, READ_EV, Box::new(move |_, ctrl, ctx| {
                assert!(ctx.cb3 == false);
                ctx.cb3 = true;
                ctrl.remove_self();
                ctrl.stop();
            }));
        }

        let ctx = ev_loop.run(Ctx { cb1: false, cb2: false, cb3: false });

        assert!(ctx.cb1);
        assert!(ctx.cb2);
        assert!(ctx.cb3);
    }
}
<commit_msg>Timer event handler: read the fd and pass contents to the cb<commit_after>// TODO:
//
// - Better error reporting

extern crate libc;

use std::collections::HashMap;
use std::ops::BitOr;

pub struct EvLoop<Ctx> {
    fds: HashMap<libc::c_int, Handler<Ctx>>,
}

enum Handler<Ctx> {
    Timer { cb: Box<Fn(&mut EvLoopController, &mut Ctx, u64) -> ()> },
    Signal { cb: Box<Fn(&mut EvLoopController, &mut Ctx) -> ()> },
    Fd { evs: FdEv, cb: Box<Fn(FdEv, &mut EvLoopController, &mut Ctx) -> ()> },
}

/// File descriptor events. Use bitwise or to combine.
pub struct FdEv(libc::c_short);

pub const READ_EV: FdEv = FdEv(libc::POLLIN);
pub const WRITE_EV: FdEv = FdEv(libc::POLLOUT);
pub const ERR_EV: FdEv = FdEv(libc::POLLERR);
pub const HUP_EV: FdEv = FdEv(libc::POLLHUP);

impl BitOr for FdEv {
    type Output = FdEv;

    fn bitor(self, rhs: FdEv) -> FdEv {
        FdEv(self.0 | rhs.0)
    }
}

pub struct TimerRef(libc::c_int);
pub struct SignalRef(libc::c_int);

extern "C" {
    fn timerfd_create(
        clockid: libc::c_int,
        flags: libc::c_int
        ) -> libc::c_int;

    fn timerfd_settime(
        fd: libc::c_int,
        flags: libc::c_int,
        new_value: *const itimerspec,
        old_value: *mut itimerspec
        ) -> libc::c_int;

    // fn timerfd_gettime(
    //     fd: libc::c_int,
    //     curr_value: *mut libc::itimerspec
    //     ) -> libc::c_int;
}

// Can't find itimerspec in libc
#[repr(C)]
pub struct itimerspec {
    it_interval: libc::timespec,
    it_value: libc::timespec,
}

pub struct EvLoopController<'a> {
    stop_ref: &'a mut bool,
    remove_self: &'a mut bool,
}

impl<'a> EvLoopController<'a> {
    pub fn stop(&mut self) {
        *self.stop_ref = true;
    }

    pub fn remove_self(&mut self) {
        *self.remove_self = true;
    }
}

fn mk_timespec(millis: i64) -> libc::timespec {
    let secs: i64 = millis / 1000;
    let nanos: i64 = (millis % 1000) * 1000000;
    libc::timespec { tv_sec: secs, tv_nsec: nanos }
}

impl<Ctx> EvLoop<Ctx> {
    pub fn new() -> EvLoop<Ctx> {
        EvLoop { fds: HashMap::new() }
    }

    /// Register a non-blocking socket. Use the same fd for unregister.
    pub fn add_fd(&mut self, fd: libc::c_int, evs: FdEv, cb: Box<Fn(FdEv, &mut EvLoopController, &mut Ctx) -> ()>) {
        self.fds.insert(fd, Handler::Fd { evs: evs, cb: cb });
    }

    pub fn remove_fd(&mut self, fd: libc::c_int) {
        self.fds.remove(&fd);
    }

    /// `timeout` and `period` in milliseconds. `timeout` must be non-zero for this to work. If
    /// `period` is non-zero, timer expires repeatedly after the initial timeout.
    pub fn add_timer(&mut self, timeout: i64, period: i64, cb: Box<Fn(&mut EvLoopController, &mut Ctx, u64) -> ()>) -> TimerRef {
        let fd = unsafe { timerfd_create(libc::CLOCK_MONOTONIC, libc::EFD_NONBLOCK) };
        assert!(fd != -1);

        let timeout_spec = mk_timespec(timeout);
        let period_spec = mk_timespec(period);
        let timerspec = itimerspec { it_interval: period_spec, it_value: timeout_spec };

        assert!(unsafe { timerfd_settime(fd, 0, &timerspec, std::ptr::null_mut()) } != -1);
        self.fds.insert(fd, Handler::Timer { cb: cb });
        TimerRef(fd)
    }

    pub fn remove_timer(&mut self, timer_ref: TimerRef) {
        assert!(unsafe { libc::close(timer_ref.0) } != -1);
        self.fds.remove(&timer_ref.0);
    }

    pub fn add_signal(&mut self, sigs: &libc::sigset_t, cb: Box<Fn(&mut EvLoopController, &mut Ctx) -> ()>) -> SignalRef {
        // Block the signals we handle using signalfd() so they don't cause signal handlers to run
        assert!(unsafe { libc::sigprocmask(libc::SIG_BLOCK, sigs as *const libc::sigset_t, std::ptr::null_mut()) } != -1);
        let fd = unsafe { libc::signalfd(-1, sigs, libc::EFD_NONBLOCK) };
        assert!(fd != -1);
        self.fds.insert(fd, Handler::Signal { cb: cb });
        SignalRef(fd)
    }

    pub fn remove_signal(&mut self, signal_ref: SignalRef) {
        self.fds.remove(&signal_ref.0);
    }

    pub fn run(&mut self, mut ctx: Ctx) -> Ctx {
        let mut stop = false;
        while !stop {
            let mut fds: Vec<libc::pollfd> = Vec::with_capacity(self.fds.len());

            for (fd, handler) in self.fds.iter() {
                match handler {
                    &Handler::Timer{ .. } | &Handler::Signal{ .. } => {
                        fds.push(libc::pollfd { fd: *fd, events: libc::POLLIN, revents: 0 });
                    }
                    &Handler::Fd{ ref evs, .. } => {
                        fds.push(libc::pollfd { fd: *fd, events: evs.0, revents: 0 });
                    }
                }
            }

            assert!(unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as u64, -1) } != -1);

            for pollfd in fds {
                if pollfd.revents != 0 {

                    let mut remove_fd = false;
                    {
                        let mut controller = EvLoopController { stop_ref: &mut stop, remove_self: &mut remove_fd };

                        match self.fds.get(&pollfd.fd).unwrap() {
                            &Handler::Timer{ ref cb } => {
                                let mut ret: u64 = 0;
                                assert!(unsafe { libc::read(pollfd.fd, &mut ret as *mut u64 as *mut libc::c_void, 8) } != -1);
                                cb(&mut controller, &mut ctx, ret);
                            }
                            &Handler::Signal{ ref cb } => {
                                cb(&mut controller, &mut ctx);
                            }
                            &Handler::Fd{ ref cb, .. } => {
                                cb(FdEv(pollfd.revents), &mut controller, &mut ctx);
                            }
                        }
                    }

                    if remove_fd {
                        self.fds.remove(&pollfd.fd);
                    }
                }
            }
        }
        ctx
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    use std::rc::Rc;

    #[test]
    fn it_works() {
        let it_worked: Rc<RefCell<bool>> = Rc::new(RefCell::new(false));

        let mut ev_loop = EvLoop::new();
        {
            let it_worked_clone = it_worked.clone();
            ev_loop.add_timer(100, 100, Box::new(move |ctrl, _, _| {
                *it_worked_clone.borrow_mut() = true;
                ctrl.stop();
            }));
        }
        ev_loop.run(());

        assert!(*(*it_worked).borrow());
    }

    #[test]
    fn it_works_2() {
        struct Ctx {
            cb1: u64,
            cb2: u64,
            cb3: bool,
        }

        let mut ev_loop: EvLoop<Ctx> = EvLoop::new();

        ev_loop.add_timer(100, 100, Box::new(move |ctrl, ctx, amt| {
            assert!(ctx.cb1 == 0);
            ctx.cb1 = amt;
            ctrl.remove_self();
        }));

        ev_loop.add_timer(100, 100, Box::new(move |ctrl, ctx, amt| {
            assert!(ctx.cb2 == 0);
            ctx.cb2 = amt;
            ctrl.remove_self();
        }));

        {
            let fd = unsafe { timerfd_create(libc::CLOCK_MONOTONIC, libc::EFD_NONBLOCK) };
            assert!(fd != -1);

            let timeout_spec = mk_timespec(300);
            let period_spec = mk_timespec(300);
            let timerspec = itimerspec { it_interval: period_spec, it_value: timeout_spec };

            assert!(unsafe { timerfd_settime(fd, 0, &timerspec, std::ptr::null_mut()) } != -1);
            ev_loop.add_fd(fd, READ_EV, Box::new(move |_, ctrl, ctx| {
                assert!(ctx.cb3 == false);
                ctx.cb3 = true;
                ctrl.remove_self();
                ctrl.stop();
            }));
        }

        let ctx = ev_loop.run(Ctx { cb1: 0, cb2: 0, cb3: false });

        assert_eq!(ctx.cb1, 1);
        assert_eq!(ctx.cb2, 1);
        assert!(ctx.cb3);
    }
}
<|endoftext|>


<commit_before>//! Protocol messages
//!
//! All protocol messages are serialized by serde according to the bincode data format. For
//! transmission on the wire, `tokio_io::codec::length_delimited` is used to prepend protocol
//! messages by an additional length header, thereby creating frames. It is crucial to
//!
//! The main type `Message` and the types in its fields are dump containers, which are not
//! responsible for any protocol logic (except for syntactic validation including validation of
//! `PublicKey` and `SecretKey` fields). Consequently, all fields of `Message` and all fields of
//! its contained types such as `Header` and `Payload` are public.

use secp256k1::key::{PublicKey, SecretKey};
use secp256k1::Signature;
use ::{SessionId, PeerIndex, SymmetricKey, SequenceNum};

/// A protocol message
///
/// Protocol messages consist of a header and a payload.
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Message {
    pub header: Header,
    pub payload: Payload,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Header {
    pub session_id: SessionId,
    pub peer_index: PeerIndex,
    pub sequence_num: SequenceNum,
    pub signature: Signature,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) enum Payload {
    KeyExchange(KeyExchange),
    DcExponential(DcExponential),
    DcMain(DcMain),
    Blame(Blame),
    Confirm(Confirm),
    Reveal(Reveal),
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct KeyExchange {
    pub ke_pk: PublicKey,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct DcExponential {
    pub commitment: [u8; 32],
    pub dc_exp: Vec<[u8; 16]>,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct DcMain {
    pub ok: bool,
    pub dc_xor: Vec<Vec<u8>>,
    pub ke_pk: PublicKey,
    pub extension: Extension,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) enum Extension {
    None,
    DcAddSecp256k1Scalar(/* TODO */),
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Blame {
    pub ke_sk: SecretKey,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Confirm {
    pub data: Vec<u8>,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Reveal {
    pub keys: Vec<(PeerIndex, SymmetricKey)>,
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;
    use tokio_io::codec::length_delimited;
    use tokio_serde_bincode::{ReadBincode, WriteBincode};
    use futures::sink::Sink;
    use futures::{Future, Stream};

    use super::*;
    use secp256k1::key::SecretKey;

    #[test]
    fn roundtrip_serde_bincode() {
        // Create secret key, public key, message digest and signature
        let slice: [u8; 32] = [0xab; 32];
        let sk = SecretKey::from_slice(&::SECP256K1, &slice).unwrap();
        let ke_pk = PublicKey::from_secret_key(&::SECP256K1, &sk).unwrap();
        assert!(ke_pk.is_valid());
        let slice: [u8; 32] = [0x01; 32];
        let msg = ::secp256k1::Message::from_slice(&slice).unwrap();
        let sig = ::SECP256K1.sign(&msg, &sk).unwrap();

        // Create message
        let msg1 = Message {
            header: Header {
                peer_index: 17,
                session_id: SessionId([56; 32]),
                sequence_num: 14,
                signature: sig,
            },
            payload: Payload::KeyExchange(KeyExchange {
                ke_pk: ke_pk,
            }),
        };

        // Write message
        let pipe = Cursor::new(Vec::new());
        let write = WriteBincode::new(length_delimited::FramedWrite::new(pipe));
        let write = write.send(msg1.clone()).wait().unwrap();

        // Read message again
        let pipe = Cursor::new(write.into_inner().into_inner().into_inner());
        let read = ReadBincode::<_ ,Message>::new(length_delimited::FramedRead::new(pipe));
        let msg2 = read.wait().next().unwrap().unwrap();

        assert_eq!(msg1, msg2);
    }
}
<commit_msg>Put Fp elements instead of [u8; 16] in messages<commit_after>//! Protocol messages
//!
//! All protocol messages are serialized by serde according to the bincode data format. For
//! transmission on the wire, `tokio_io::codec::length_delimited` is used to prepend protocol
//! messages by an additional length header, thereby creating frames. It is crucial to
//!
//! The main type `Message` and the types in its fields are dump containers, which are not
//! responsible for any protocol logic (except for syntactic validation including validation of
//! `PublicKey` and `SecretKey` fields). Consequently, all fields of `Message` and all fields of
//! its contained types such as `Header` and `Payload` are public.

use secp256k1::key::{PublicKey, SecretKey};
use secp256k1::Signature;
use ::{SessionId, PeerIndex, SymmetricKey, SequenceNum};
use field::Fp;

/// A protocol message
///
/// Protocol messages consist of a header and a payload.
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Message {
    pub header: Header,
    pub payload: Payload,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Header {
    pub session_id: SessionId,
    pub peer_index: PeerIndex,
    pub sequence_num: SequenceNum,
    pub signature: Signature,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) enum Payload {
    KeyExchange(KeyExchange),
    DcExponential(DcExponential),
    DcMain(DcMain),
    Blame(Blame),
    Confirm(Confirm),
    Reveal(Reveal),
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct KeyExchange {
    pub ke_pk: PublicKey,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct DcExponential {
    pub commitment: [u8; 32],
    pub dc_exp: Vec<Fp>,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct DcMain {
    pub ok: bool,
    pub dc_xor: Vec<Vec<u8>>,
    pub ke_pk: PublicKey,
    pub extension: Extension,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) enum Extension {
    None,
    DcAddSecp256k1Scalar(/* TODO */),
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Blame {
    pub ke_sk: SecretKey,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Confirm {
    pub data: Vec<u8>,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub(crate) struct Reveal {
    pub keys: Vec<(PeerIndex, SymmetricKey)>,
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;
    use tokio_io::codec::length_delimited;
    use tokio_serde_bincode::{ReadBincode, WriteBincode};
    use futures::sink::Sink;
    use futures::{Future, Stream};

    use super::*;
    use secp256k1::key::SecretKey;

    #[test]
    fn roundtrip_serde_bincode() {
        // Create secret key, public key, message digest and signature
        let slice: [u8; 32] = [0xab; 32];
        let sk = SecretKey::from_slice(&::SECP256K1, &slice).unwrap();
        let ke_pk = PublicKey::from_secret_key(&::SECP256K1, &sk).unwrap();
        assert!(ke_pk.is_valid());
        let slice: [u8; 32] = [0x01; 32];
        let msg = ::secp256k1::Message::from_slice(&slice).unwrap();
        let sig = ::SECP256K1.sign(&msg, &sk).unwrap();

        // Create message
        let msg1 = Message {
            header: Header {
                peer_index: 17,
                session_id: SessionId([56; 32]),
                sequence_num: 14,
                signature: sig,
            },
            payload: Payload::KeyExchange(KeyExchange {
                ke_pk: ke_pk,
            }),
        };

        // Write message
        let pipe = Cursor::new(Vec::new());
        let write = WriteBincode::new(length_delimited::FramedWrite::new(pipe));
        let write = write.send(msg1.clone()).wait().unwrap();

        // Read message again
        let pipe = Cursor::new(write.into_inner().into_inner().into_inner());
        let read = ReadBincode::<_ ,Message>::new(length_delimited::FramedRead::new(pipe));
        let msg2 = read.wait().next().unwrap().unwrap();

        assert_eq!(msg1, msg2);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A helper class for dealing with static archives

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
use std::str;
use syntax::diagnostic::Handler as ErrorHandler;
use rustc_llvm::archive_ro::ArchiveRO;

use tempdir::TempDir;

pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";

pub struct ArchiveConfig<'a> {
    pub handler: &'a ErrorHandler,
    pub dst: PathBuf,
    pub lib_search_paths: Vec<PathBuf>,
    pub slib_prefix: String,
    pub slib_suffix: String,
    pub maybe_ar_prog: Option<String>
}

pub struct Archive<'a> {
    handler: &'a ErrorHandler,
    dst: PathBuf,
    lib_search_paths: Vec<PathBuf>,
    slib_prefix: String,
    slib_suffix: String,
    maybe_ar_prog: Option<String>
}

/// Helper for adding many files to an archive with a single invocation of
/// `ar`.
#[must_use = "must call build() to finish building the archive"]
pub struct ArchiveBuilder<'a> {
    archive: Archive<'a>,
    work_dir: TempDir,
    /// Filename of each member that should be added to the archive.
    members: Vec<PathBuf>,
    should_update_symbols: bool,
}

fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
          args: &str, cwd: Option<&Path>,
          paths: &[&Path]) -> Output {
    let ar = match *maybe_ar_prog {
        Some(ref ar) => &ar[..],
        None => "ar"
    };
    let mut cmd = Command::new(ar);

    cmd.arg(args).args(paths).stdout(Stdio::piped()).stderr(Stdio::piped());
    debug!("{:?}", cmd);

    match cwd {
        Some(p) => {
            cmd.current_dir(p);
            debug!("inside {:?}", p.display());
        }
        None => {}
    }

    match cmd.spawn() {
        Ok(prog) => {
            let o = prog.wait_with_output().unwrap();
            if !o.status.success() {
                handler.err(&format!("{:?} failed with: {}", cmd, o.status));
                handler.note(&format!("stdout ---\n{}",
                                  str::from_utf8(&o.stdout).unwrap()));
                handler.note(&format!("stderr ---\n{}",
                                  str::from_utf8(&o.stderr).unwrap())
                             );
                handler.abort_if_errors();
            }
            o
        },
        Err(e) => {
            handler.err(&format!("could not exec `{}`: {}", &ar[..],
                             e));
            handler.abort_if_errors();
            panic!("rustc::back::archive::run_ar() should not reach this point");
        }
    }
}

pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
                    search_paths: &[PathBuf],
                    handler: &ErrorHandler) -> PathBuf {
    // On Windows, static libraries sometimes show up as libfoo.a and other
    // times show up as foo.lib
    let oslibname = format!("{}{}{}", osprefix, name, ossuffix);
    let unixlibname = format!("lib{}.a", name);

    for path in search_paths {
        debug!("looking for {} inside {:?}", name, path);
        let test = path.join(&oslibname[..]);
        if test.exists() { return test }
        if oslibname != unixlibname {
            let test = path.join(&unixlibname[..]);
            if test.exists() { return test }
        }
    }
    handler.fatal(&format!("could not find native static library `{}`, \
                           perhaps an -L flag is missing?",
                          name));
}

impl<'a> Archive<'a> {
    fn new(config: ArchiveConfig<'a>) -> Archive<'a> {
        let ArchiveConfig { handler, dst, lib_search_paths, slib_prefix, slib_suffix,
            maybe_ar_prog } = config;
        Archive {
            handler: handler,
            dst: dst,
            lib_search_paths: lib_search_paths,
            slib_prefix: slib_prefix,
            slib_suffix: slib_suffix,
            maybe_ar_prog: maybe_ar_prog
        }
    }

    /// Opens an existing static archive
    pub fn open(config: ArchiveConfig<'a>) -> Archive<'a> {
        let archive = Archive::new(config);
        assert!(archive.dst.exists());
        archive
    }

    /// Removes a file from this archive
    pub fn remove_file(&mut self, file: &str) {
        run_ar(self.handler, &self.maybe_ar_prog, "d", None, &[&self.dst, &Path::new(file)]);
    }

    /// Lists all files in an archive
    pub fn files(&self) -> Vec<String> {
        let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, &[&self.dst]);
        let output = str::from_utf8(&output.stdout).unwrap();
        // use lines_any because windows delimits output with `\r\n` instead of
        // just `\n`
        output.lines_any().map(|s| s.to_string()).collect()
    }

    /// Creates an `ArchiveBuilder` for adding files to this archive.
    pub fn extend(self) -> ArchiveBuilder<'a> {
        ArchiveBuilder::new(self)
    }
}

impl<'a> ArchiveBuilder<'a> {
    fn new(archive: Archive<'a>) -> ArchiveBuilder<'a> {
        ArchiveBuilder {
            archive: archive,
            work_dir: TempDir::new("rsar").unwrap(),
            members: vec![],
            should_update_symbols: false,
        }
    }

    /// Create a new static archive, ready for adding files.
    pub fn create(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
        let archive = Archive::new(config);
        ArchiveBuilder::new(archive)
    }

    /// Adds all of the contents of a native library to this archive. This will
    /// search in the relevant locations for a library named `name`.
    pub fn add_native_library(&mut self, name: &str) -> io::Result<()> {
        let location = find_library(name,
                                    &self.archive.slib_prefix,
                                    &self.archive.slib_suffix,
                                    &self.archive.lib_search_paths,
                                    self.archive.handler);
        self.add_archive(&location, name, |_| false)
    }

    /// Adds all of the contents of the rlib at the specified path to this
    /// archive.
    ///
    /// This ignores adding the bytecode from the rlib, and if LTO is enabled
    /// then the object file also isn't added.
    pub fn add_rlib(&mut self, rlib: &Path, name: &str,
                    lto: bool) -> io::Result<()> {
        // Ignoring obj file starting with the crate name
        // as simple comparison is not enough - there
        // might be also an extra name suffix
        let obj_start = format!("{}", name);
        let obj_start = &obj_start[..];
        // Ignoring all bytecode files, no matter of
        // name
        let bc_ext = ".bytecode.deflate";

        self.add_archive(rlib, &name[..], |fname: &str| {
            let skip_obj = lto && fname.starts_with(obj_start)
                && fname.ends_with(".o");
            skip_obj || fname.ends_with(bc_ext) || fname == METADATA_FILENAME
        })
    }

    /// Adds an arbitrary file to this archive
    pub fn add_file(&mut self, file: &Path) -> io::Result<()> {
        let filename = Path::new(file.file_name().unwrap());
        let new_file = self.work_dir.path().join(&filename);
        try!(fs::copy(file, &new_file));
        self.members.push(filename.to_path_buf());
        Ok(())
    }

    /// Indicate that the next call to `build` should updates all symbols in
    /// the archive (run 'ar s' over it).
    pub fn update_symbols(&mut self) {
        self.should_update_symbols = true;
    }

    /// Combine the provided files, rlibs, and native libraries into a single
    /// `Archive`.
    pub fn build(self) -> Archive<'a> {
        // Get an absolute path to the destination, so `ar` will work even
        // though we run it from `self.work_dir`.
        let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
        assert!(!abs_dst.is_relative());
        let mut args = vec![&*abs_dst];
        let mut total_len = abs_dst.to_string_lossy().len();

        if self.members.is_empty() {
            // OSX `ar` does not allow using `r` with no members, but it does
            // allow running `ar s file.a` to update symbols only.
            if self.should_update_symbols {
                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
                       "s", Some(self.work_dir.path()), &args[..]);
            }
            return self.archive;
        }

        // Don't allow the total size of `args` to grow beyond 32,000 bytes.
        // Windows will raise an error if the argument string is longer than
        // 32,768, and we leave a bit of extra space for the program name.
        const ARG_LENGTH_LIMIT: usize = 32_000;

        for member_name in &self.members {
            let len = member_name.to_string_lossy().len();

            // `len + 1` to account for the space that's inserted before each
            // argument.  (Windows passes command-line arguments as a single
            // string, not an array of strings.)
            if total_len + len + 1 > ARG_LENGTH_LIMIT {
                // Add the archive members seen so far, without updating the
                // symbol table (`S`).
                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
                       "cruS", Some(self.work_dir.path()), &args[..]);

                args.clear();
                args.push(&abs_dst);
                total_len = abs_dst.to_string_lossy().len();
            }

            args.push(member_name);
            total_len += len + 1;
        }

        // Add the remaining archive members, and update the symbol table if
        // necessary.
        let flags = if self.should_update_symbols { "crus" } else { "cruS" };
        run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
               flags, Some(self.work_dir.path()), &args[..]);

        self.archive
    }

    fn add_archive<F>(&mut self, archive: &Path, name: &str,
                      mut skip: F) -> io::Result<()>
        where F: FnMut(&str) -> bool,
    {
        let archive = match ArchiveRO::open(archive) {
            Some(ar) => ar,
            None => return Err(io::Error::new(io::ErrorKind::Other,
                                              "failed to open archive")),
        };

        // Next, we must rename all of the inputs to "guaranteed unique names".
        // We write each file into `self.work_dir` under its new unique name.
        // The reason for this renaming is that archives are keyed off the name
        // of the files, so if two files have the same name they will override
        // one another in the archive (bad).
        //
        // We skip any files explicitly desired for skipping, and we also skip
        // all SYMDEF files as these are just magical placeholders which get
        // re-created when we make a new archive anyway.
        for file in archive.iter() {
            let filename = match file.name() {
                Some(s) => s,
                None => continue,
            };
            if filename.contains(".SYMDEF") { continue }
            if skip(filename) { continue }

            // An archive can contain files of the same name multiple times, so
            // we need to be sure to not have them overwrite one another when we
            // extract them. Consequently we need to find a truly unique file
            // name for us!
            let mut new_filename = String::new();
            for n in 0.. {
                let n = if n == 0 {String::new()} else {format!("-{}", n)};
                new_filename = format!("r{}-{}-{}", n, name, filename);

                // LLDB (as mentioned in back::link) crashes on filenames of
                // exactly
                // 16 bytes in length. If we're including an object file with
                //    exactly 16-bytes of characters, give it some prefix so
                //    that it's not 16 bytes.
                new_filename = if new_filename.len() == 16 {
                    format!("lldb-fix-{}", new_filename)
                } else {
                    new_filename
                };

                let present = self.members.iter().filter_map(|p| {
                    p.file_name().and_then(|f| f.to_str())
                }).any(|s| s == new_filename);
                if !present {
                    break
                }
            }
            let dst = self.work_dir.path().join(&new_filename);
            try!(try!(File::create(&dst)).write_all(file.data()));
            self.members.push(PathBuf::from(new_filename));
        }

        Ok(())
    }
}
<commit_msg>Auto merge of #25238 - alexcrichton:fix-archive-with-slashes, r=brson<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A helper class for dealing with static archives

use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
use std::str;
use syntax::diagnostic::Handler as ErrorHandler;
use rustc_llvm::archive_ro::ArchiveRO;

use tempdir::TempDir;

pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";

pub struct ArchiveConfig<'a> {
    pub handler: &'a ErrorHandler,
    pub dst: PathBuf,
    pub lib_search_paths: Vec<PathBuf>,
    pub slib_prefix: String,
    pub slib_suffix: String,
    pub maybe_ar_prog: Option<String>
}

pub struct Archive<'a> {
    handler: &'a ErrorHandler,
    dst: PathBuf,
    lib_search_paths: Vec<PathBuf>,
    slib_prefix: String,
    slib_suffix: String,
    maybe_ar_prog: Option<String>
}

/// Helper for adding many files to an archive with a single invocation of
/// `ar`.
#[must_use = "must call build() to finish building the archive"]
pub struct ArchiveBuilder<'a> {
    archive: Archive<'a>,
    work_dir: TempDir,
    /// Filename of each member that should be added to the archive.
    members: Vec<PathBuf>,
    should_update_symbols: bool,
}

fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
          args: &str, cwd: Option<&Path>,
          paths: &[&Path]) -> Output {
    let ar = match *maybe_ar_prog {
        Some(ref ar) => &ar[..],
        None => "ar"
    };
    let mut cmd = Command::new(ar);

    cmd.arg(args).args(paths).stdout(Stdio::piped()).stderr(Stdio::piped());
    debug!("{:?}", cmd);

    match cwd {
        Some(p) => {
            cmd.current_dir(p);
            debug!("inside {:?}", p.display());
        }
        None => {}
    }

    match cmd.spawn() {
        Ok(prog) => {
            let o = prog.wait_with_output().unwrap();
            if !o.status.success() {
                handler.err(&format!("{:?} failed with: {}", cmd, o.status));
                handler.note(&format!("stdout ---\n{}",
                                  str::from_utf8(&o.stdout).unwrap()));
                handler.note(&format!("stderr ---\n{}",
                                  str::from_utf8(&o.stderr).unwrap())
                             );
                handler.abort_if_errors();
            }
            o
        },
        Err(e) => {
            handler.err(&format!("could not exec `{}`: {}", &ar[..],
                             e));
            handler.abort_if_errors();
            panic!("rustc::back::archive::run_ar() should not reach this point");
        }
    }
}

pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
                    search_paths: &[PathBuf],
                    handler: &ErrorHandler) -> PathBuf {
    // On Windows, static libraries sometimes show up as libfoo.a and other
    // times show up as foo.lib
    let oslibname = format!("{}{}{}", osprefix, name, ossuffix);
    let unixlibname = format!("lib{}.a", name);

    for path in search_paths {
        debug!("looking for {} inside {:?}", name, path);
        let test = path.join(&oslibname[..]);
        if test.exists() { return test }
        if oslibname != unixlibname {
            let test = path.join(&unixlibname[..]);
            if test.exists() { return test }
        }
    }
    handler.fatal(&format!("could not find native static library `{}`, \
                           perhaps an -L flag is missing?",
                          name));
}

impl<'a> Archive<'a> {
    fn new(config: ArchiveConfig<'a>) -> Archive<'a> {
        let ArchiveConfig { handler, dst, lib_search_paths, slib_prefix, slib_suffix,
            maybe_ar_prog } = config;
        Archive {
            handler: handler,
            dst: dst,
            lib_search_paths: lib_search_paths,
            slib_prefix: slib_prefix,
            slib_suffix: slib_suffix,
            maybe_ar_prog: maybe_ar_prog
        }
    }

    /// Opens an existing static archive
    pub fn open(config: ArchiveConfig<'a>) -> Archive<'a> {
        let archive = Archive::new(config);
        assert!(archive.dst.exists());
        archive
    }

    /// Removes a file from this archive
    pub fn remove_file(&mut self, file: &str) {
        run_ar(self.handler, &self.maybe_ar_prog, "d", None, &[&self.dst, &Path::new(file)]);
    }

    /// Lists all files in an archive
    pub fn files(&self) -> Vec<String> {
        let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, &[&self.dst]);
        let output = str::from_utf8(&output.stdout).unwrap();
        // use lines_any because windows delimits output with `\r\n` instead of
        // just `\n`
        output.lines_any().map(|s| s.to_string()).collect()
    }

    /// Creates an `ArchiveBuilder` for adding files to this archive.
    pub fn extend(self) -> ArchiveBuilder<'a> {
        ArchiveBuilder::new(self)
    }
}

impl<'a> ArchiveBuilder<'a> {
    fn new(archive: Archive<'a>) -> ArchiveBuilder<'a> {
        ArchiveBuilder {
            archive: archive,
            work_dir: TempDir::new("rsar").unwrap(),
            members: vec![],
            should_update_symbols: false,
        }
    }

    /// Create a new static archive, ready for adding files.
    pub fn create(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
        let archive = Archive::new(config);
        ArchiveBuilder::new(archive)
    }

    /// Adds all of the contents of a native library to this archive. This will
    /// search in the relevant locations for a library named `name`.
    pub fn add_native_library(&mut self, name: &str) -> io::Result<()> {
        let location = find_library(name,
                                    &self.archive.slib_prefix,
                                    &self.archive.slib_suffix,
                                    &self.archive.lib_search_paths,
                                    self.archive.handler);
        self.add_archive(&location, name, |_| false)
    }

    /// Adds all of the contents of the rlib at the specified path to this
    /// archive.
    ///
    /// This ignores adding the bytecode from the rlib, and if LTO is enabled
    /// then the object file also isn't added.
    pub fn add_rlib(&mut self, rlib: &Path, name: &str,
                    lto: bool) -> io::Result<()> {
        // Ignoring obj file starting with the crate name
        // as simple comparison is not enough - there
        // might be also an extra name suffix
        let obj_start = format!("{}", name);
        let obj_start = &obj_start[..];
        // Ignoring all bytecode files, no matter of
        // name
        let bc_ext = ".bytecode.deflate";

        self.add_archive(rlib, &name[..], |fname: &str| {
            let skip_obj = lto && fname.starts_with(obj_start)
                && fname.ends_with(".o");
            skip_obj || fname.ends_with(bc_ext) || fname == METADATA_FILENAME
        })
    }

    /// Adds an arbitrary file to this archive
    pub fn add_file(&mut self, file: &Path) -> io::Result<()> {
        let filename = Path::new(file.file_name().unwrap());
        let new_file = self.work_dir.path().join(&filename);
        try!(fs::copy(file, &new_file));
        self.members.push(filename.to_path_buf());
        Ok(())
    }

    /// Indicate that the next call to `build` should updates all symbols in
    /// the archive (run 'ar s' over it).
    pub fn update_symbols(&mut self) {
        self.should_update_symbols = true;
    }

    /// Combine the provided files, rlibs, and native libraries into a single
    /// `Archive`.
    pub fn build(self) -> Archive<'a> {
        // Get an absolute path to the destination, so `ar` will work even
        // though we run it from `self.work_dir`.
        let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
        assert!(!abs_dst.is_relative());
        let mut args = vec![&*abs_dst];
        let mut total_len = abs_dst.to_string_lossy().len();

        if self.members.is_empty() {
            // OSX `ar` does not allow using `r` with no members, but it does
            // allow running `ar s file.a` to update symbols only.
            if self.should_update_symbols {
                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
                       "s", Some(self.work_dir.path()), &args[..]);
            }
            return self.archive;
        }

        // Don't allow the total size of `args` to grow beyond 32,000 bytes.
        // Windows will raise an error if the argument string is longer than
        // 32,768, and we leave a bit of extra space for the program name.
        const ARG_LENGTH_LIMIT: usize = 32_000;

        for member_name in &self.members {
            let len = member_name.to_string_lossy().len();

            // `len + 1` to account for the space that's inserted before each
            // argument.  (Windows passes command-line arguments as a single
            // string, not an array of strings.)
            if total_len + len + 1 > ARG_LENGTH_LIMIT {
                // Add the archive members seen so far, without updating the
                // symbol table (`S`).
                run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
                       "cruS", Some(self.work_dir.path()), &args[..]);

                args.clear();
                args.push(&abs_dst);
                total_len = abs_dst.to_string_lossy().len();
            }

            args.push(member_name);
            total_len += len + 1;
        }

        // Add the remaining archive members, and update the symbol table if
        // necessary.
        let flags = if self.should_update_symbols { "crus" } else { "cruS" };
        run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
               flags, Some(self.work_dir.path()), &args[..]);

        self.archive
    }

    fn add_archive<F>(&mut self, archive: &Path, name: &str,
                      mut skip: F) -> io::Result<()>
        where F: FnMut(&str) -> bool,
    {
        let archive = match ArchiveRO::open(archive) {
            Some(ar) => ar,
            None => return Err(io::Error::new(io::ErrorKind::Other,
                                              "failed to open archive")),
        };

        // Next, we must rename all of the inputs to "guaranteed unique names".
        // We write each file into `self.work_dir` under its new unique name.
        // The reason for this renaming is that archives are keyed off the name
        // of the files, so if two files have the same name they will override
        // one another in the archive (bad).
        //
        // We skip any files explicitly desired for skipping, and we also skip
        // all SYMDEF files as these are just magical placeholders which get
        // re-created when we make a new archive anyway.
        for file in archive.iter() {
            let filename = match file.name() {
                Some(s) => s,
                None => continue,
            };
            if filename.contains(".SYMDEF") { continue }
            if skip(filename) { continue }

            // Archives on unix systems typically do not have slashes in
            // filenames as the `ar` utility generally only uses the last
            // component of a path for the filename list in the archive. On
            // Windows, however, archives assembled with `lib.exe` will preserve
            // the full path to the file that was placed in the archive,
            // including path separators.
            //
            // The code below is munging paths so it'll go wrong pretty quickly
            // if there's some unexpected slashes in the filename, so here we
            // just chop off everything but the filename component. Note that
            // this can cause duplicate filenames, but that's also handled below
            // as well.
            let filename = Path::new(filename).file_name().unwrap()
                                              .to_str().unwrap();

            // An archive can contain files of the same name multiple times, so
            // we need to be sure to not have them overwrite one another when we
            // extract them. Consequently we need to find a truly unique file
            // name for us!
            let mut new_filename = String::new();
            for n in 0.. {
                let n = if n == 0 {String::new()} else {format!("-{}", n)};
                new_filename = format!("r{}-{}-{}", n, name, filename);

                // LLDB (as mentioned in back::link) crashes on filenames of
                // exactly
                // 16 bytes in length. If we're including an object file with
                //    exactly 16-bytes of characters, give it some prefix so
                //    that it's not 16 bytes.
                new_filename = if new_filename.len() == 16 {
                    format!("lldb-fix-{}", new_filename)
                } else {
                    new_filename
                };

                let present = self.members.iter().filter_map(|p| {
                    p.file_name().and_then(|f| f.to_str())
                }).any(|s| s == new_filename);
                if !present {
                    break
                }
            }
            let dst = self.work_dir.path().join(&new_filename);
            try!(try!(File::create(&dst)).write_all(file.data()));
            self.members.push(PathBuf::from(new_filename));
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>/// A point in some (metric) space.
pub trait Point {
    /// Accurate compute the distance from `self` to `other`.
    ///
    /// This should be real and non-negative, or else algorithms may
    /// return unexpected results.
    fn dist(&self, other: &Self) -> f64;

    /// Compute an estimate of the distance from `self` to `other`.
    ///
    /// This should be less than or equal to `self.dist(other)` or
    /// else algorithms may return unexpected results.
    #[allow(unused_variables)]
    fn dist_lower_bound(&self, other: &Self) -> f64 {
        ::std::f64::NEG_INFINITY
    }
}

/// A data structure that contains points of some sort.
pub trait Points {
    /// The representation of a point.
    ///
    /// It is expected that this should be stable for the given
    /// instance of a `Points`, but doesn't need to be stable across
    /// instances, e.g. if some hypothetical structure `Foo` stores
    /// points of type `struct Bar(f64, f64)` and two different `Foo`s
    /// store the point `Bar(0.0, 1.0)`, there's no requirement for
    /// the `Point` representing those `Bar`s to be identical. In
    /// particular, this allows one to use an index into a vector of
    /// points stored inside the `Self` type.
    type Point;
}
/// Collections of points that can be queried to find nearby points.
pub trait RegionQuery: Points {
    /// An iterator over the nearby points and their distances of a given one.
    type Neighbours: Iterator<Item = (f64, Self::Point)>;

    /// Return an iterator over points in `self` with distance from
    /// `point` less than or equal to `epsilon`.
    ///
    /// It is expected that this includes `point` itself if `epsilon
    /// >= 0`.
    ///
    /// The behaviour is unspecified if `point` is not in `self`, and
    /// if `epsilon < 0` (although it is strongly recommended that the
    /// iterator is empty in this case).
    fn neighbours(&self, point: &Self::Point, epsilon: f64) -> Self::Neighbours;
}

/// Collections of points that can list everything they contain.
pub trait ListPoints: Points {
    /// An iterator over all the points in an instance of `Self`
    type AllPoints: Iterator<Item = Self::Point>;

    /// Return an iterator over all points in `self`.
    ///
    /// It is expected that this iterator isn't invalidated by calling
    /// other methods like `RegionQuery::neighbours` (if the type also
    /// implements that).
    fn all_points(&self) -> Self::AllPoints;
}

use std::ops::Range;
use std::slice::Iter;
use std::iter::Enumerate;

/// A point collection where queries are answered via brute-force
/// scans over the whole list.
///
/// Points are represented via their indices into the list passed to
/// `new`.
pub struct BruteScan<'a, P: Point + 'a> {
    points: &'a [P]
}

impl<'a, P: Point> BruteScan<'a, P> {
    /// Create a new `BruteScan`.
    pub fn new(p: &'a [P]) -> BruteScan<'a, P> {
        BruteScan { points: p }
    }
}
impl<'a,P: Point> Points for BruteScan<'a, P> {
    type Point = usize;
}
impl<'a,P: Point> ListPoints for BruteScan<'a, P> {
    type AllPoints = Range<usize>;
    fn all_points(&self) -> Range<usize> {
        0..self.points.len()
    }
}

impl<'a, P: Point> RegionQuery for BruteScan<'a, P> {
    type Neighbours = BruteScanNeighbours<'a, P>;

    fn neighbours(&self, point: &usize, eps: f64) -> BruteScanNeighbours<'a, P> {
        BruteScanNeighbours {
            points: self.points.iter().enumerate(),
            point: &self.points[*point],
            eps: eps
        }
    }
}

/// An iterator over the neighbours of a point in a `BruteScan`.
pub struct BruteScanNeighbours<'a, P: Point + 'a> {
    points: Enumerate<Iter<'a, P>>,
    point: &'a P,
    eps: f64,
}

impl<'a,P: Point> Iterator for BruteScanNeighbours<'a, P> {
    type Item = (f64, usize);

    fn next(&mut self) -> Option<(f64,usize)> {
        let BruteScanNeighbours { ref mut points, ref point, eps } = *self;

        points.filter_map(|(i, p)| {
            if point.dist_lower_bound(p) <= eps {
                let d = point.dist(p);
                if d <= eps {
                    return Some((d, i))
                }
            };
            None
        }).next()
    }
}

/// Points in ℝn with the L2 norm.
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Euclid<T>(pub T);

pub trait Euclidean {
    fn zero() -> Self;
    fn add(&mut self, &Self);
    fn scale(&mut self, f64);
    fn dist2(&self, other: &Self) -> f64;
}

macro_rules! euclidean_points {
    ($($e: expr),*) => {
        $(
            impl Point for Euclid<[f64; $e]> {
                fn dist(&self, other: &Euclid<[f64; $e]>) -> f64 {
                    self.dist2(other).sqrt()
                }

                fn dist_lower_bound(&self, other: &Euclid<[f64; $e]>) -> f64 {
                    (self.0[0] - other.0[0]).abs()
                }
            }
            impl Euclidean for Euclid<[f64; $e]> {
                fn zero() -> Self {
                    Euclid([0.0; $e])
                }
                fn add(&mut self, other: &Self) {
                    for (place, val) in self.0.iter_mut().zip(other.0.iter()) {
                        *place += *val
                    }
                }
                fn scale(&mut self, factor: f64) {
                    for place in &mut self.0 {
                        *place *= factor
                    }
                }
                fn dist2(&self, other: &Euclid<[f64; $e]>) -> f64 {
                    self.0.iter().zip(other.0.iter())
                        .map(|(a, b)| {
                            let d = *a - *b;
                            d * d
                        })
                        .fold(0.0, |a, b| a + b)
                }
            }
            )*
    }
}
euclidean_points!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn euclid() {
        let p1 = Euclid([0.0, 1.0]);
        let p2 = Euclid([1.0, 0.0]);
        assert!((p1.dist(&p2) - 2f64.sqrt()).abs() < 1e-10);
    }
    #[test]
    fn naive_neigbours() {
        let points = [Euclid([0.0]), Euclid([10.0]), Euclid([5.0]), Euclid([2.5])];
        let points = BruteScan::new(&points);

        type V = Vec<(f64, usize)>;

        assert_eq!(points.neighbours(&0, 1.0).collect::<V>(),
                   [(0.0, 0)]);
        assert_eq!(points.neighbours(&0, 3.0).collect::<V>(),
                   [(0.0, 0), (2.5, 3)]);
        assert_eq!(points.neighbours(&1, 3.0).collect::<V>(),
                   [(0.0, 1)]);
        assert_eq!(points.neighbours(&1, 10.0).collect::<V>(),
                   [(10.0, 0), (0.0, 1), (5.0, 2), (7.5, 3)]);
        assert_eq!(points.neighbours(&3, 3.0).collect::<V>(),
                   [(2.5, 0), (2.5, 2), (0.0, 3)]);
    }
}
<commit_msg>Make &P's (P: Point) impl Point.<commit_after>/// A point in some (metric) space.
pub trait Point {
    /// Accurate compute the distance from `self` to `other`.
    ///
    /// This should be real and non-negative, or else algorithms may
    /// return unexpected results.
    fn dist(&self, other: &Self) -> f64;

    /// Compute an estimate of the distance from `self` to `other`.
    ///
    /// This should be less than or equal to `self.dist(other)` or
    /// else algorithms may return unexpected results.
    #[allow(unused_variables)]
    fn dist_lower_bound(&self, other: &Self) -> f64 {
        ::std::f64::NEG_INFINITY
    }
}

impl<'a, P: Point + ?Sized> Point for &'a P {
    fn dist(&self, other: &Self) -> f64 {
        (**self).dist(other)
    }
    fn dist_lower_bound(&self, other: &Self) -> f64 {
        (**self).dist_lower_bound(other)
    }
}

/// A data structure that contains points of some sort.
pub trait Points {
    /// The representation of a point.
    ///
    /// It is expected that this should be stable for the given
    /// instance of a `Points`, but doesn't need to be stable across
    /// instances, e.g. if some hypothetical structure `Foo` stores
    /// points of type `struct Bar(f64, f64)` and two different `Foo`s
    /// store the point `Bar(0.0, 1.0)`, there's no requirement for
    /// the `Point` representing those `Bar`s to be identical. In
    /// particular, this allows one to use an index into a vector of
    /// points stored inside the `Self` type.
    type Point;
}
/// Collections of points that can be queried to find nearby points.
pub trait RegionQuery: Points {
    /// An iterator over the nearby points and their distances of a given one.
    type Neighbours: Iterator<Item = (f64, Self::Point)>;

    /// Return an iterator over points in `self` with distance from
    /// `point` less than or equal to `epsilon`.
    ///
    /// It is expected that this includes `point` itself if `epsilon
    /// >= 0`.
    ///
    /// The behaviour is unspecified if `point` is not in `self`, and
    /// if `epsilon < 0` (although it is strongly recommended that the
    /// iterator is empty in this case).
    fn neighbours(&self, point: &Self::Point, epsilon: f64) -> Self::Neighbours;
}

/// Collections of points that can list everything they contain.
pub trait ListPoints: Points {
    /// An iterator over all the points in an instance of `Self`
    type AllPoints: Iterator<Item = Self::Point>;

    /// Return an iterator over all points in `self`.
    ///
    /// It is expected that this iterator isn't invalidated by calling
    /// other methods like `RegionQuery::neighbours` (if the type also
    /// implements that).
    fn all_points(&self) -> Self::AllPoints;
}

use std::ops::Range;
use std::slice::Iter;
use std::iter::Enumerate;

/// A point collection where queries are answered via brute-force
/// scans over the whole list.
///
/// Points are represented via their indices into the list passed to
/// `new`.
pub struct BruteScan<'a, P: Point + 'a> {
    points: &'a [P]
}

impl<'a, P: Point> BruteScan<'a, P> {
    /// Create a new `BruteScan`.
    pub fn new(p: &'a [P]) -> BruteScan<'a, P> {
        BruteScan { points: p }
    }
}
impl<'a,P: Point> Points for BruteScan<'a, P> {
    type Point = usize;
}
impl<'a,P: Point> ListPoints for BruteScan<'a, P> {
    type AllPoints = Range<usize>;
    fn all_points(&self) -> Range<usize> {
        0..self.points.len()
    }
}

impl<'a, P: Point> RegionQuery for BruteScan<'a, P> {
    type Neighbours = BruteScanNeighbours<'a, P>;

    fn neighbours(&self, point: &usize, eps: f64) -> BruteScanNeighbours<'a, P> {
        BruteScanNeighbours {
            points: self.points.iter().enumerate(),
            point: &self.points[*point],
            eps: eps
        }
    }
}

/// An iterator over the neighbours of a point in a `BruteScan`.
pub struct BruteScanNeighbours<'a, P: Point + 'a> {
    points: Enumerate<Iter<'a, P>>,
    point: &'a P,
    eps: f64,
}

impl<'a,P: Point> Iterator for BruteScanNeighbours<'a, P> {
    type Item = (f64, usize);

    fn next(&mut self) -> Option<(f64,usize)> {
        let BruteScanNeighbours { ref mut points, point, eps } = *self;

        points.filter_map(|(i, p)| {
            if point.dist_lower_bound(p) <= eps {
                let d = point.dist(p);
                if d <= eps {
                    return Some((d, i))
                }
            };
            None
        }).next()
    }
}

/// Points in ℝn with the L2 norm.
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct Euclid<T>(pub T);

pub trait Euclidean {
    fn zero() -> Self;
    fn add(&mut self, &Self);
    fn scale(&mut self, f64);
    fn dist2(&self, other: &Self) -> f64;
}

macro_rules! euclidean_points {
    ($($e: expr),*) => {
        $(
            impl Point for Euclid<[f64; $e]> {
                fn dist(&self, other: &Euclid<[f64; $e]>) -> f64 {
                    self.dist2(other).sqrt()
                }

                fn dist_lower_bound(&self, other: &Euclid<[f64; $e]>) -> f64 {
                    (self.0[0] - other.0[0]).abs()
                }
            }
            impl Euclidean for Euclid<[f64; $e]> {
                fn zero() -> Self {
                    Euclid([0.0; $e])
                }
                fn add(&mut self, other: &Self) {
                    for (place, val) in self.0.iter_mut().zip(other.0.iter()) {
                        *place += *val
                    }
                }
                fn scale(&mut self, factor: f64) {
                    for place in &mut self.0 {
                        *place *= factor
                    }
                }
                fn dist2(&self, other: &Euclid<[f64; $e]>) -> f64 {
                    self.0.iter().zip(other.0.iter())
                        .map(|(a, b)| {
                            let d = *a - *b;
                            d * d
                        })
                        .fold(0.0, |a, b| a + b)
                }
            }
            )*
    }
}
euclidean_points!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn euclid() {
        let p1 = Euclid([0.0, 1.0]);
        let p2 = Euclid([1.0, 0.0]);
        assert!((p1.dist(&p2) - 2f64.sqrt()).abs() < 1e-10);
    }
    #[test]
    fn naive_neigbours() {
        let points = [Euclid([0.0]), Euclid([10.0]), Euclid([5.0]), Euclid([2.5])];
        let points = BruteScan::new(&points);

        type V = Vec<(f64, usize)>;

        assert_eq!(points.neighbours(&0, 1.0).collect::<V>(),
                   [(0.0, 0)]);
        assert_eq!(points.neighbours(&0, 3.0).collect::<V>(),
                   [(0.0, 0), (2.5, 3)]);
        assert_eq!(points.neighbours(&1, 3.0).collect::<V>(),
                   [(0.0, 1)]);
        assert_eq!(points.neighbours(&1, 10.0).collect::<V>(),
                   [(10.0, 0), (0.0, 1), (5.0, 2), (7.5, 3)]);
        assert_eq!(points.neighbours(&3, 3.0).collect::<V>(),
                   [(2.5, 0), (2.5, 2), (0.0, 3)]);
    }
}
<|endoftext|>


<commit_before>use bytes::{BufMut, BytesMut};

use nom::{IResult, Needed};

use imap_proto;
pub use imap_proto::types::*;

use std::io;
use std::mem;
use std::str;

use tokio_core::net::TcpStream;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

pub type ImapTransport = Framed<TlsStream<TcpStream>, ImapCodec>;

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> ImapCodec {
        ImapCodec { decode_need_message_bytes: 0 }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut)
             -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let res = match imap_proto::parse_response(buf) {
            IResult::Done(remaining, response) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                Some((response, buf.len() - remaining.len()))
            },
            IResult::Incomplete(Needed::Size(min)) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            },
            IResult::Incomplete(_) => {
                return Ok(None);
            },
            IResult::Error(err) => {
                panic!("error {} during parsing of {:?}", err, buf);
            },
        };
        let (response, rsp_len) = res.unwrap();
        let raw = buf.split_to(rsp_len);
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl Encoder for ImapCodec {
    type Item = Request;
    type Error = io::Error;
    fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut)
             -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put(b' ');
        dst.put(&msg.1);
        dst.put("\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: BytesMut,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    pub response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done(ref req_id, ..) => Some(req_id),
            _ => None,
        }
    }
    pub fn parsed(&self) -> &Response {
        unsafe { mem::transmute(&self.response) }
    }
}
<commit_msg>Adapt to struct variant change in imap-proto<commit_after>use bytes::{BufMut, BytesMut};

use nom::{IResult, Needed};

use imap_proto;
pub use imap_proto::types::*;

use std::io;
use std::mem;
use std::str;

use tokio_core::net::TcpStream;
use tokio_io::codec::{Decoder, Encoder, Framed};
use tokio_tls::TlsStream;

pub type ImapTransport = Framed<TlsStream<TcpStream>, ImapCodec>;

pub struct ImapCodec {
    decode_need_message_bytes: usize,
}

impl Default for ImapCodec {
    fn default() -> ImapCodec {
        ImapCodec { decode_need_message_bytes: 0 }
    }
}

impl<'a> Decoder for ImapCodec {
    type Item = ResponseData;
    type Error = io::Error;
    fn decode(&mut self, buf: &mut BytesMut)
             -> Result<Option<Self::Item>, io::Error> {
        if self.decode_need_message_bytes > buf.len() {
            return Ok(None);
        }
        let res = match imap_proto::parse_response(buf) {
            IResult::Done(remaining, response) => {
                // This SHOULD be acceptable/safe: BytesMut storage memory is
                // allocated on the heap and should not move. It will not be
                // freed as long as we keep a reference alive, which we do
                // by retaining a reference to the split buffer, below.
                let response = unsafe { mem::transmute(response) };
                Some((response, buf.len() - remaining.len()))
            },
            IResult::Incomplete(Needed::Size(min)) => {
                self.decode_need_message_bytes = min;
                return Ok(None);
            },
            IResult::Incomplete(_) => {
                return Ok(None);
            },
            IResult::Error(err) => {
                panic!("error {} during parsing of {:?}", err, buf);
            },
        };
        let (response, rsp_len) = res.unwrap();
        let raw = buf.split_to(rsp_len);
        self.decode_need_message_bytes = 0;
        Ok(Some(ResponseData { raw, response }))
    }
}

impl Encoder for ImapCodec {
    type Item = Request;
    type Error = io::Error;
    fn encode(&mut self, msg: Self::Item, dst: &mut BytesMut)
             -> Result<(), io::Error> {
        dst.put(msg.0.as_bytes());
        dst.put(b' ');
        dst.put(&msg.1);
        dst.put("\r\n");
        Ok(())
    }
}

#[derive(Debug)]
pub struct ResponseData {
    raw: BytesMut,
    // This reference is really scoped to the lifetime of the `raw`
    // member, but unfortunately Rust does not allow that yet. It
    // is transmuted to `'static` by the `Decoder`, instead, and
    // references returned to callers of `ResponseData` are limited
    // to the lifetime of the `ResponseData` struct.
    pub response: Response<'static>,
}

impl ResponseData {
    pub fn request_id(&self) -> Option<&RequestId> {
        match self.response {
            Response::Done{ ref tag, .. } => Some(tag),
            _ => None,
        }
    }
    pub fn parsed(&self) -> &Response {
        unsafe { mem::transmute(&self.response) }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use std::fmt;
use std::ops::Range as RangeOp;

use super::bound::{BoundType, Bound};

// Unpack Bound into scope to reduce verbosity
use super::bound::Bound::*;

#[derive(Clone, Debug, PartialEq)]
pub struct Range<T> {
    lower: Bound<T>,
    upper: Bound<T>,
}

impl<T> Range<T> {
    pub fn new(lower: Bound<T>, upper: Bound<T>) -> Range<T> {
        Range {
            lower: lower,
            upper: upper,
        }
    }

    pub fn lower_inf(&self) -> bool {
        match self.lower {
            Bound::Unbounded => true,
            _ => false,
        }
    }

    pub fn upper_inf(&self) -> bool {
        match self.upper {
            Bound::Unbounded => true,
            _ => false,
        }
    }

    pub fn is_bounded(&self) -> bool {
        self.lower.is_bounded() && self.upper.is_bounded()
    }
}

impl<T> From<RangeOp<Bound<T>>> for Range<T> {
    fn from(range: RangeOp<Bound<T>>) -> Range<T> {
        Range {
            lower: range.start,
            upper: range.end,
        }
    }
}

// Add shorthands for common range types such as Range::from(1..10). The lower
// end is always inclusive and the upper end is always exclusive.
macro_rules! add_impl {
    ($($t:ty)*) => ($(
        impl From<RangeOp<$t>> for Range<$t> {
            fn from(range: RangeOp<$t>) -> Range<$t> {
                Range::from(Inclusive(range.start) .. Exclusive(range.end))
            }
        }
    )*)
}

add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }

impl<T: Clone> Range<T> {
    pub fn lower(&self) -> Bound<T> {
        self.lower.clone()
    }

    pub fn upper(&self) -> Bound<T> {
        self.upper.clone()
    }
}

impl<T: fmt::Display> fmt::Display for Range<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.lower {
            Bound::Inclusive(ref x) => write!(f, "[{}", x),
            Bound::Exclusive(ref x) => write!(f, "({}", x),
            Bound::Unbounded => write!(f, "("),
        }?;

        write!(f, ",")?;

        match self.upper {
            Bound::Inclusive(ref x) => write!(f, "{}]", x),
            Bound::Exclusive(ref x) => write!(f, "{})", x),
            Bound::Unbounded => write!(f, ")"),
        }
    }
}

impl<T: PartialOrd> PartialOrd for Range<T> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match Bound::compare_bounds(BoundType::Lower, &self.lower, &other.lower) {
            Some(Ordering::Equal) => {
                Bound::compare_bounds(BoundType::Upper, &self.upper, &other.upper)
            },
            cmp => cmp,
        }
    }
}
<commit_msg>Renamed add_impl macro to from_rangeop_impl_for_range<commit_after>use std::cmp::Ordering;
use std::fmt;
use std::ops::Range as RangeOp;

use super::bound::{BoundType, Bound};

// Unpack Bound into scope to reduce verbosity
use super::bound::Bound::*;

#[derive(Clone, Debug, PartialEq)]
pub struct Range<T> {
    lower: Bound<T>,
    upper: Bound<T>,
}

impl<T> Range<T> {
    pub fn new(lower: Bound<T>, upper: Bound<T>) -> Range<T> {
        Range {
            lower: lower,
            upper: upper,
        }
    }

    pub fn lower_inf(&self) -> bool {
        match self.lower {
            Bound::Unbounded => true,
            _ => false,
        }
    }

    pub fn upper_inf(&self) -> bool {
        match self.upper {
            Bound::Unbounded => true,
            _ => false,
        }
    }

    pub fn is_bounded(&self) -> bool {
        self.lower.is_bounded() && self.upper.is_bounded()
    }
}

impl<T> From<RangeOp<Bound<T>>> for Range<T> {
    fn from(range: RangeOp<Bound<T>>) -> Range<T> {
        Range {
            lower: range.start,
            upper: range.end,
        }
    }
}

// Add shorthands for common range types such as Range::from(1..10). The lower
// end is always inclusive and the upper end is always exclusive.
macro_rules! from_rangeop_impl_for_range {
    ($($t:ty)*) => ($(
        impl From<RangeOp<$t>> for Range<$t> {
            fn from(range: RangeOp<$t>) -> Range<$t> {
                Range::from(Inclusive(range.start) .. Exclusive(range.end))
            }
        }
    )*)
}

from_rangeop_impl_for_range! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }

impl<T: Clone> Range<T> {
    pub fn lower(&self) -> Bound<T> {
        self.lower.clone()
    }

    pub fn upper(&self) -> Bound<T> {
        self.upper.clone()
    }
}

impl<T: fmt::Display> fmt::Display for Range<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.lower {
            Bound::Inclusive(ref x) => write!(f, "[{}", x),
            Bound::Exclusive(ref x) => write!(f, "({}", x),
            Bound::Unbounded => write!(f, "("),
        }?;

        write!(f, ",")?;

        match self.upper {
            Bound::Inclusive(ref x) => write!(f, "{}]", x),
            Bound::Exclusive(ref x) => write!(f, "{})", x),
            Bound::Unbounded => write!(f, ")"),
        }
    }
}

impl<T: PartialOrd> PartialOrd for Range<T> {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match Bound::compare_bounds(BoundType::Lower, &self.lower, &other.lower) {
            Some(Ordering::Equal) => {
                Bound::compare_bounds(BoundType::Upper, &self.upper, &other.upper)
            },
            cmp => cmp,
        }
    }
}
<|endoftext|>