<commit_before>use rusqlite::Connection;

#[derive(Debug)]
pub struct Provider {
    id: i32,
    name: String,
}

pub fn table_create_provider(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE PROVIDER (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_provider(conn: &Connection, name: &String) -> Result<i32, &'static str> {
    let bill = name.clone();
    let me = Provider { id: 0, name: bill };
    let provider_instance = conn.execute(
        "INSERT INTO PROVIDER (name)
                  VALUES (?1)",
        &[&me.name],
    );
    if provider_instance.is_err() {
        return Err("Insert failed");
    }
    provider_instance.unwrap();
    return Ok(0);
}

pub fn list_provider(conn: &Connection) -> Vec<Provider> {
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| Provider {
        id: row.get(0),
        name: row.get(1),
    });
    let mut items = Vec::<Provider>::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 provider_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name FROM PROVIDER").unwrap();
    let person_iter = stmt.query_map(&[], |row| Provider {
        id: row.get(0),
        name: row.get(1),
    }).unwrap();

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

pub fn pk_provider_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let bill = name.clone();
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER WHERE name = ?1")
        .unwrap();
    let provider_iter = stmt.query_map(&[&bill], |row| Provider {
        id: row.get(0),
        name: row.get(1),
    }).unwrap();
    let mut found = 0;
    for person in provider_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = bill.id;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<commit_msg>Beutify the rust code<commit_after>use rusqlite::Connection;

#[derive(Debug)]
pub struct Provider {
    id: i32,
    name: String,
}

pub fn table_create_provider(conn: &Connection) -> &Connection {
    conn.execute(
        "CREATE TABLE PROVIDER (
                  id              INTEGER PRIMARY KEY ASC,
                  name            TEXT NOT NULL UNIQUE
                  )",
        &[],
    ).unwrap();
    return conn;
}

pub fn insert_provider(conn: &Connection, name: &String) -> Result<i32, &'static str> {
    let bill = name.clone();
    let me = Provider { id: 0, name: bill };
    let provider_instance = conn.execute(
        "INSERT INTO PROVIDER (name)
                  VALUES (?1)",
        &[&me.name],
    );
    if provider_instance.is_err() {
        return Err("Insert failed");
    }
    provider_instance.unwrap();
    return Ok(0);
}

pub fn list_provider(conn: &Connection) -> Vec<Provider> {
    let mut stmt = conn.prepare("SELECT id, name  FROM PROVIDER").unwrap();
    let wraped_fs_file_iter = stmt.query_map(&[], |row| Provider {
        id: row.get(0),
        name: row.get(1),
    });
    let mut items = Vec::<Provider>::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 provider_list(conn: &Connection) {
    let mut stmt = conn.prepare("SELECT id, name FROM PROVIDER").unwrap();
    let person_iter =
        stmt.query_map(&[], |row| Provider {
            id: row.get(0),
            name: row.get(1),
        }).unwrap();

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

pub fn pk_provider_by_name(
    conn: &Connection,
    name: &String,
    pk: &mut i32,
) -> Result<i32, &'static str> {
    let bill = name.clone();
    let mut stmt = conn
        .prepare("SELECT id, name  FROM PROVIDER WHERE name = ?1")
        .unwrap();
    let provider_iter =
        stmt.query_map(&[&bill], |row| Provider {
            id: row.get(0),
            name: row.get(1),
        }).unwrap();
    let mut found = 0;
    for person in provider_iter {
        let bill = person.unwrap();
        *pk = bill.id;
        found = bill.id;
    }
    if found != 0 {
        return Ok(found);
    }
    return Err("None found");
}
<|endoftext|>


<commit_before>use super::{Connection, Message, MessageItem, Error};
use std::collections::TreeMap;

pub struct Props {
    name: String,
    path: String,
    interface: String,
    timeout_ms: int,
}

impl Props {
    pub fn new(name: &str, path: &str, interface: &str, timeout_ms: int) -> Props {
        Props {
            name: name.to_string(),
            path: path.to_string(),
            interface: interface.to_string(),
            timeout_ms: timeout_ms
        }
    }

    pub fn get(&self, conn: &Connection, propname: &str) -> Result<MessageItem, Error> {
        let mut m = Message::new_method_call(self.name.as_slice(), self.path.as_slice(),
            "org.freedesktop.DBus.Properties", "Get").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string())
        ]);
        let mut r = try!(conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Variant(ref v) = &reply[0] {
                return Ok(*v.deref().clone())
            }
       }
       let f = format!("Invalid reply for property get {}: '{}'", propname, reply);
       return Err(Error::new_custom("InvalidReply", f.as_slice()));
    }

    pub fn set(&self, conn: &Connection, propname: &str, value: MessageItem) -> Result<(), Error> {
        let mut m = Message::new_method_call(self.name.as_slice(), self.path.as_slice(),
            "org.freedesktop.DBus.Properties", "Set").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string()),
            MessageItem::Variant(box value),
        ]);
        let mut r = try!(conn.send_with_reply_and_block(m, self.timeout_ms));
        try!(r.as_result());
        Ok(())
    }

    pub fn get_all(&self, conn: &Connection) -> Result<TreeMap<String, MessageItem>, Error> {
        let mut m = Message::new_method_call(self.name.as_slice(), self.path.as_slice(),
            "org.freedesktop.DBus.Properties", "GetAll").unwrap();
        m.append_items(&[MessageItem::Str(self.interface.clone())]);
        let mut r = try!(conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Array(ref a, _) = &reply[0] {
                let mut t = TreeMap::new();
                let mut haserr = false;
                for p in a.iter() {
                    if let &MessageItem::DictEntry(ref k, ref v) = p {
                        if let &MessageItem::Str(ref ks) = &**k {
                            t.insert(ks.to_string(), *v.deref().clone());
                        } else { haserr = true; };
                    } else { haserr = true; };
                }
                if !haserr { return Ok(t) };
            }
        }
        let f = format!("Invalid reply for property GetAll: '{}'", reply);
        return Err(Error::new_custom("InvalidReply", f.as_slice()));
    }
}

pub struct PropHandler {
    p: Props,
    map: TreeMap<String, MessageItem>,
}

impl PropHandler {
    pub fn new(p: Props) -> PropHandler {
        PropHandler { p: p, map: TreeMap::new() }
    }

    pub fn get_all(&mut self, conn: &Connection) -> Result<(), Error> {
        self.map = try!(self.p.get_all(conn));
        Ok(())
    }

    pub fn map_mut(&mut self) -> &mut TreeMap<String, MessageItem> { &mut self.map }
    pub fn map(&self) -> &TreeMap<String, MessageItem> { &self.map }

    pub fn get(&mut self, conn: &Connection, propname: &str) -> Result<&MessageItem, Error> {
        let v = try!(self.p.get(conn, propname));
        self.map.insert(propname.to_string(), v);
        Ok(self.map.get(propname).unwrap())
    }

    pub fn set(&mut self, conn: &Connection, propname: &str, value: MessageItem) -> Result<(), Error> {
        try!(self.p.set(conn, propname, value.clone()));
        self.map.insert(propname.to_string(), value);
        Ok(())
    }

    fn invalid_args(m: &Message) -> Message {
        Message::new_error(m, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid arguments").unwrap()
    }

    fn handle_get(&self, msg: &mut Message) -> Message {
        let items = msg.get_items();
        let name = if let Some(s) = items.get(1) { s } else { return PropHandler::invalid_args(msg) };
        let name = if let &MessageItem::Str(ref s) = name { s } else { return PropHandler::invalid_args(msg) };
        let value = if let Some(s) = self.map.get(name) { s } else { return PropHandler::invalid_args(msg) };

        let mut reply = Message::new_method_return(msg).unwrap();
        reply.append_items(&[MessageItem::Variant(box value.clone())]);
        reply
    }

    fn handle_getall(&self, msg: &mut Message) -> Message {
        let mut reply = Message::new_method_return(msg).unwrap();
        for (k, v) in self.map.iter() {
            reply.append_items(&[MessageItem::DictEntry(box MessageItem::Str(k.clone()), box v.clone())]);
        }
        reply
    }

    /* Return value:
       None => not handled,
       Some(Err(())) => message reply send failed,
       Some(Ok()) => message reply send ok */
    pub fn handle_message(&mut self, conn: &Connection, msg: &mut Message) -> Option<Result<(), ()>> {
        let (_, path, iface, method) = msg.headers();
        if iface.is_none() || iface.unwrap().as_slice() != "org.freedesktop.DBus.Properties" { return None; }
        if path.is_none() || path.unwrap() != self.p.path { return None; }
        if method.is_none() { return None; }

        let items = msg.get_items();
        if let Some(i) = items.get(0) {
            if let &MessageItem::Str(ref s) = i {
                if *s != self.p.interface { return None; }
            } else { return None; } // Hmm, invalid message
        } else { return None }; // Hmm, invalid message

        // Ok, we have a match
        let reply = match method.unwrap().as_slice() {
            "Get" => self.handle_get(msg),
//            "Set" => self.handle_set(msg),
            "GetAll" => self.handle_getall(msg),
            _ => PropHandler::invalid_args(msg)
        };
        Some(conn.send(reply))
    }
}

/* Unfortunately org.freedesktop.DBus has no properties we can use for testing, but PolicyKit should be around on most distros. */
#[test]
fn test_get_policykit_version() {
    use super::BusType;
    let mut c = Connection::get_private(BusType::System).unwrap();
    let p = Props::new("org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority",
        "org.freedesktop.PolicyKit1.Authority", 10000);

    /* Let's use both the get and getall methods and see if we get the same result */
    let v = p.get(&mut c, "BackendVersion").unwrap();
    let vall = p.get_all(&mut c).unwrap();

    let v2 = match vall.get("BackendVersion").unwrap() {
        &MessageItem::Variant(ref q) => &**q,
        _ => { panic!("Invalid GetAll: {}", vall); }
    };

    assert_eq!(&v, &*v2);
    match v {
        MessageItem::Str(ref s) => { println!("Policykit Backend version is {}", s); }
        _ => { panic!("Invalid Get: {}", v); }
    };

}

#[test]
fn test_prop_server() {
    let mut c = Connection::get_private(super::BusType::Session).unwrap();
    let busname = format!("com.example.prophandler.test{}", ::std::rand::random::<u32>());
    assert_eq!(c.register_name(busname.as_slice(), super::NameFlag::ReplaceExisting as u32).unwrap(), super::RequestNameReply::PrimaryOwner);

    let mut p = PropHandler::new(Props::new(&*busname, "/propserver", &*busname, 5000));
    c.register_object_path("/propserver").unwrap();
    p.map_mut().insert("Foo".to_string(), super::MessageItem::Int16(-15));

    spawn(move || {
        let mut c = Connection::get_private(super::BusType::Session).unwrap();
        let mut pr = PropHandler::new(Props::new(&*busname, "/propserver", &*busname, 5000));
        assert_eq!(pr.get(&mut c, "Foo").unwrap(), &super::MessageItem::Int16(-15));
    });

    loop {
        let n = match c.iter(1000).next() {
            None => panic!("c.iter.next returned None"),
            Some(n) => n,
        };
        if let super::ConnectionItem::MethodCall(mut msg) = n {
            let q = p.handle_message(&mut c, &mut msg);
            if q.is_none() {
                println!("Non-matching message {}", msg);
                c.send(super::Message::new_error(&msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method").unwrap()).unwrap();
                continue;
            }
            assert_eq!(q, Some(Ok(())));
            break;
        }
    }
}
<commit_msg>Store connection reference inside Props<commit_after>use super::{Connection, Message, MessageItem, Error};
use std::collections::TreeMap;

pub struct Props<'a> {
    name: String,
    path: String,
    interface: String,
    timeout_ms: int,
    conn: &'a Connection,
}

impl<'a> Props<'a> {
    pub fn new(conn: &'a Connection, name: &str, path: &str, interface: &str, timeout_ms: int) -> Props<'a> {
        Props {
            name: name.to_string(),
            path: path.to_string(),
            interface: interface.to_string(),
            timeout_ms: timeout_ms,
            conn: conn,
        }
    }

    pub fn get(&self, propname: &str) -> Result<MessageItem, Error> {
        let mut m = Message::new_method_call(self.name.as_slice(), self.path.as_slice(),
            "org.freedesktop.DBus.Properties", "Get").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string())
        ]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Variant(ref v) = &reply[0] {
                return Ok(*v.deref().clone())
            }
       }
       let f = format!("Invalid reply for property get {}: '{}'", propname, reply);
       return Err(Error::new_custom("InvalidReply", f.as_slice()));
    }

    pub fn set(&self, propname: &str, value: MessageItem) -> Result<(), Error> {
        let mut m = Message::new_method_call(self.name.as_slice(), self.path.as_slice(),
            "org.freedesktop.DBus.Properties", "Set").unwrap();
        m.append_items(&[
            MessageItem::Str(self.interface.clone()),
            MessageItem::Str(propname.to_string()),
            MessageItem::Variant(box value),
        ]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        try!(r.as_result());
        Ok(())
    }

    pub fn get_all(&self) -> Result<TreeMap<String, MessageItem>, Error> {
        let mut m = Message::new_method_call(self.name.as_slice(), self.path.as_slice(),
            "org.freedesktop.DBus.Properties", "GetAll").unwrap();
        m.append_items(&[MessageItem::Str(self.interface.clone())]);
        let mut r = try!(self.conn.send_with_reply_and_block(m, self.timeout_ms));
        let reply = try!(r.as_result()).get_items();
        if reply.len() == 1 {
            if let &MessageItem::Array(ref a, _) = &reply[0] {
                let mut t = TreeMap::new();
                let mut haserr = false;
                for p in a.iter() {
                    if let &MessageItem::DictEntry(ref k, ref v) = p {
                        if let &MessageItem::Str(ref ks) = &**k {
                            t.insert(ks.to_string(), *v.deref().clone());
                        } else { haserr = true; };
                    } else { haserr = true; };
                }
                if !haserr { return Ok(t) };
            }
        }
        let f = format!("Invalid reply for property GetAll: '{}'", reply);
        return Err(Error::new_custom("InvalidReply", f.as_slice()));
    }
}

pub struct PropHandler<'a> {
    p: Props<'a>,
    map: TreeMap<String, MessageItem>,
}

impl<'a> PropHandler<'a> {
    pub fn new(p: Props) -> PropHandler {
        PropHandler { p: p, map: TreeMap::new() }
    }

    pub fn get_all(&mut self) -> Result<(), Error> {
        self.map = try!(self.p.get_all());
        Ok(())
    }

    pub fn map_mut(&mut self) -> &mut TreeMap<String, MessageItem> { &mut self.map }
    pub fn map(&self) -> &TreeMap<String, MessageItem> { &self.map }

    pub fn get(&mut self, propname: &str) -> Result<&MessageItem, Error> {
        let v = try!(self.p.get(propname));
        self.map.insert(propname.to_string(), v);
        Ok(self.map.get(propname).unwrap())
    }

    pub fn set(&mut self, propname: &str, value: MessageItem) -> Result<(), Error> {
        try!(self.p.set(propname, value.clone()));
        self.map.insert(propname.to_string(), value);
        Ok(())
    }

    fn invalid_args(m: &Message) -> Message {
        Message::new_error(m, "org.freedesktop.DBus.Error.InvalidArgs", "Invalid arguments").unwrap()
    }

    fn handle_get(&self, msg: &mut Message) -> Message {
        let items = msg.get_items();
        let name = if let Some(s) = items.get(1) { s } else { return PropHandler::invalid_args(msg) };
        let name = if let &MessageItem::Str(ref s) = name { s } else { return PropHandler::invalid_args(msg) };
        let value = if let Some(s) = self.map.get(name) { s } else { return PropHandler::invalid_args(msg) };

        let mut reply = Message::new_method_return(msg).unwrap();
        reply.append_items(&[MessageItem::Variant(box value.clone())]);
        reply
    }

    fn handle_getall(&self, msg: &mut Message) -> Message {
        let mut reply = Message::new_method_return(msg).unwrap();
        for (k, v) in self.map.iter() {
            reply.append_items(&[MessageItem::DictEntry(box MessageItem::Str(k.clone()), box v.clone())]);
        }
        reply
    }

    /* Return value:
       None => not handled,
       Some(Err(())) => message reply send failed,
       Some(Ok()) => message reply send ok */
    pub fn handle_message(&mut self, msg: &mut Message) -> Option<Result<(), ()>> {
        let (_, path, iface, method) = msg.headers();
        if iface.is_none() || iface.unwrap().as_slice() != "org.freedesktop.DBus.Properties" { return None; }
        if path.is_none() || path.unwrap() != self.p.path { return None; }
        if method.is_none() { return None; }

        let items = msg.get_items();
        if let Some(i) = items.get(0) {
            if let &MessageItem::Str(ref s) = i {
                if *s != self.p.interface { return None; }
            } else { return None; } // Hmm, invalid message
        } else { return None }; // Hmm, invalid message

        // Ok, we have a match
        let reply = match method.unwrap().as_slice() {
            "Get" => self.handle_get(msg),
//            "Set" => self.handle_set(msg),
            "GetAll" => self.handle_getall(msg),
            _ => PropHandler::invalid_args(msg)
        };
        Some(self.p.conn.send(reply))
    }
}

/* Unfortunately org.freedesktop.DBus has no properties we can use for testing, but PolicyKit should be around on most distros. */
#[test]
fn test_get_policykit_version() {
    use super::BusType;
    let c = Connection::get_private(BusType::System).unwrap();
    let p = Props::new(&c, "org.freedesktop.PolicyKit1", "/org/freedesktop/PolicyKit1/Authority",
        "org.freedesktop.PolicyKit1.Authority", 10000);

    /* Let's use both the get and getall methods and see if we get the same result */
    let v = p.get("BackendVersion").unwrap();
    let vall = p.get_all().unwrap();

    let v2 = match vall.get("BackendVersion").unwrap() {
        &MessageItem::Variant(ref q) => &**q,
        _ => { panic!("Invalid GetAll: {}", vall); }
    };

    assert_eq!(&v, &*v2);
    match v {
        MessageItem::Str(ref s) => { println!("Policykit Backend version is {}", s); }
        _ => { panic!("Invalid Get: {}", v); }
    };

}

#[test]
fn test_prop_server() {
    let c = Connection::get_private(super::BusType::Session).unwrap();
    let busname = format!("com.example.prophandler.test{}", ::std::rand::random::<u32>());
    assert_eq!(c.register_name(busname.as_slice(), super::NameFlag::ReplaceExisting as u32).unwrap(), super::RequestNameReply::PrimaryOwner);

    let mut p = PropHandler::new(Props::new(&c, &*busname, "/propserver", &*busname, 5000));
    c.register_object_path("/propserver").unwrap();
    p.map_mut().insert("Foo".to_string(), super::MessageItem::Int16(-15));

    spawn(move || {
        let c = Connection::get_private(super::BusType::Session).unwrap();
        let mut pr = PropHandler::new(Props::new(&c, &*busname, "/propserver", &*busname, 5000));
        assert_eq!(pr.get("Foo").unwrap(), &super::MessageItem::Int16(-15));
    });

    loop {
        let n = match c.iter(1000).next() {
            None => panic!("c.iter.next returned None"),
            Some(n) => n,
        };
        if let super::ConnectionItem::MethodCall(mut msg) = n {
            let q = p.handle_message(&mut msg);
            if q.is_none() {
                println!("Non-matching message {}", msg);
                c.send(super::Message::new_error(&msg, "org.freedesktop.DBus.Error.UnknownMethod", "Unknown method").unwrap()).unwrap();
                continue;
            }
            assert_eq!(q, Some(Ok(())));
            break;
        }
    }
}
<|endoftext|>


<commit_before>//!A raytracer.
#![feature(path, io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;

use rand::distributions::IndependentSample;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

const EPS: f32 = 0.00005;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection {
    time: f32,
    point: Point3,
    normal: Vec3
}

trait Scene {
    fn intersect(&self, ray: Ray3) -> Option<Intersection>;
}

struct Sphere {
    center: Point3,
    radius: f32
}

impl Scene for Sphere {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > EPS {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal
                })
            } else if t2 > EPS {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3
}

impl Scene for Plane {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > EPS {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal
                })
            } else {
                None
            }
        }
    }
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        match self.0.intersect(ray) {
            Some(ai) => {
                match self.1.intersect(ray) {
                    Some(bi) => if ai.time < bi.time {
                        Some(ai)
                    } else {
                        Some(bi)
                    },
                    None => Some(ai)
                }
            },
            None => self.1.intersect(ray)
        }
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(angle.cos(), angle.sin(), z)
}

fn main() {
    let mut rng = rand::thread_rng();

    let num_bounces = 10;
    let rays_per_pixel = 10;
    let scene = (
        (Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35
        }),
        (Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0)
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0)
        })
    );
    let light = Point3::new(1.0, -1.5, 0.5);

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            for _ in 0..num_bounces {
                if let Some(intersection) = scene.intersect(ray) {
                    let light_ray = Ray3 {
                        start: intersection.point,
                        dir: light - intersection.point
                    };

                    let can_see_light = match scene.intersect(light_ray) {
                        Some(light_intersection) => {
                            light_intersection.time > 1.
                        },
                        None => true
                    };

                    if can_see_light {
                        let light_strength = 10.0 / light_ray.dir.mag2();
                        let scale = (intersection.normal.mag2() * light_ray.dir.mag2()).sqrt();
                        total_light += light_strength * intersection.normal.dot(light_ray.dir) / scale;
                    }

                    let cand_dir = rand_sphere(&mut rng);
                    let dir = if cand_dir.dot(intersection.normal) < 0. {
                        -cand_dir
                    } else {
                        cand_dir
                    };
                    ray = Ray3 {
                        start: intersection.point,
                        dir: dir
                    }
                } else {
                    break;
                }
            }
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(clamp(total_light / rays_per_pixel as f32)*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<commit_msg>Fixups for multiple bounces<commit_after>//!A raytracer.
#![feature(path, io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;

use rand::distributions::IndependentSample;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

const EPS: f32 = 0.00005;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection {
    time: f32,
    point: Point3,
    normal: Vec3
}

trait Scene {
    fn intersect(&self, ray: Ray3) -> Option<Intersection>;
}

struct Sphere {
    center: Point3,
    radius: f32
}

impl Scene for Sphere {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim > 0. {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if t1 > EPS {
                let p = ray.start + ray.dir * t1;
                let normal = p - self.center;
                Some(Intersection {
                    time: t1,
                    point: p,
                    normal: normal
                })
            } else if t2 > EPS {
                let p = ray.start + ray.dir * t2;
                let normal = p - self.center;
                Some(Intersection {
                    time: t2,
                    point: p,
                    normal: normal
                })
            } else {
                None
            }
        } else {
            None
        }
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3
}

impl Scene for Plane {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > EPS {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal
                })
            } else {
                None
            }
        }
    }
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    fn intersect(&self, ray: Ray3) -> Option<Intersection> {
        match self.0.intersect(ray) {
            Some(ai) => {
                match self.1.intersect(ray) {
                    Some(bi) => if ai.time < bi.time {
                        Some(ai)
                    } else {
                        Some(bi)
                    },
                    None => Some(ai)
                }
            },
            None => self.1.intersect(ray)
        }
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let mut rng = rand::thread_rng();

    let num_bounces = 10;
    let rays_per_pixel = 10;
    let scene = (
        (Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35
        }),
        (Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0)
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0)
        })
    );
    let light = Point3::new(1.0, -1.5, 0.5);

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::new(imgx, imgy);

    // Iterate over the coordiantes and pixels of the image
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            let mut strength = 1.;
            for _ in 0..num_bounces {
                if let Some(intersection) = scene.intersect(ray) {
                    let light_ray = Ray3 {
                        start: intersection.point,
                        dir: light - intersection.point
                    };

                    let can_see_light = match scene.intersect(light_ray) {
                        Some(light_intersection) => {
                            light_intersection.time > 1.
                        },
                        None => true
                    };

                    if can_see_light {
                        let light_strength = 10.0 / light_ray.dir.mag2();
                        let scale = (intersection.normal.mag2() * light_ray.dir.mag2()).sqrt();
                        total_light += strength * light_strength * intersection.normal.dot(light_ray.dir) / scale;
                    }

                    let cand_dir = rand_sphere(&mut rng);
                    let dir = if cand_dir.dot(intersection.normal) < 0. {
                        -cand_dir
                    } else {
                        cand_dir
                    };
                    ray = Ray3 {
                        start: intersection.point,
                        dir: dir
                    };
                    strength *= dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                } else {
                    break;
                }
            }
        }

        // Create an 8bit pixel of type Luma and value i
        // and assign in to the pixel at position (x, y)
        *pixel = image::Luma([(clamp(total_light / rays_per_pixel as f32)*255.) as u8]);
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<|endoftext|>


<commit_before>//! Types for rectangles.

#[allow(clippy::module_inception)]
mod rect {
    use crate::float_eq_cairo::ApproxEqCairo;
    use core::ops::{Add, Range, Sub};
    use float_cmp::approx_eq;
    use num_traits::Zero;

    // Use our own min() and max() that are acceptable for floating point

    fn min<T: PartialOrd>(x: T, y: T) -> T {
        if x <= y {
            x
        } else {
            y
        }
    }

    fn max<T: PartialOrd>(x: T, y: T) -> T {
        if x >= y {
            x
        } else {
            y
        }
    }

    #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
    pub struct Rect<T> {
        pub x0: T,
        pub y0: T,
        pub x1: T,
        pub y1: T,
    }

    impl<T> Rect<T> {
        #[inline]
        pub fn new(x0: T, y0: T, x1: T, y1: T) -> Self {
            Self { x0, y0, x1, y1 }
        }
    }

    impl<T> Rect<T>
    where
        T: Copy + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T> + Zero,
    {
        #[inline]
        pub fn from_size(w: T, h: T) -> Self {
            Self {
                x0: Zero::zero(),
                y0: Zero::zero(),
                x1: w,
                y1: h,
            }
        }

        #[inline]
        pub fn width(&self) -> T {
            self.x1 - self.x0
        }

        #[inline]
        pub fn height(&self) -> T {
            self.y1 - self.y0
        }

        #[inline]
        pub fn size(&self) -> (T, T) {
            (self.width(), self.height())
        }

        #[inline]
        pub fn x_range(&self) -> Range<T> {
            self.x0..self.x1
        }

        #[inline]
        pub fn y_range(&self) -> Range<T> {
            self.y0..self.y1
        }

        #[inline]
        pub fn contains(self, x: T, y: T) -> bool {
            x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
        }

        #[inline]
        pub fn translate(&self, by: (T, T)) -> Self {
            Self {
                x0: self.x0 + by.0,
                y0: self.y0 + by.1,
                x1: self.x1 + by.0,
                y1: self.y1 + by.1,
            }
        }

        #[inline]
        pub fn intersection(&self, rect: &Self) -> Option<Self> {
            let (x0, y0, x1, y1) = (
                max(self.x0, rect.x0),
                max(self.y0, rect.y0),
                min(self.x1, rect.x1),
                min(self.y1, rect.y1),
            );

            if x1 > x0 && y1 > y0 {
                Some(Self { x0, y0, x1, y1 })
            } else {
                None
            }
        }

        #[inline]
        pub fn union(&self, rect: &Self) -> Self {
            Self {
                x0: min(self.x0, rect.x0),
                y0: min(self.y0, rect.y0),
                x1: max(self.x1, rect.x1),
                y1: max(self.y1, rect.y1),
            }
        }
    }

    impl Rect<i32> {
        #[inline]
        pub fn is_empty(&self) -> bool {
            // Give an explicit type to the right hand side of the ==, since sometimes
            // type inference fails to figure it out.  I have no idea why.
            self.width() == <i32 as Zero>::zero() || self.height() == <i32 as Zero>::zero()
        }

        #[inline]
        pub fn scale(self, x: f64, y: f64) -> Self {
            Self {
                x0: (f64::from(self.x0) * x).floor() as i32,
                y0: (f64::from(self.y0) * y).floor() as i32,
                x1: (f64::from(self.x1) * x).ceil() as i32,
                y1: (f64::from(self.y1) * y).ceil() as i32,
            }
        }
    }

    impl Rect<f64> {
        #[inline]
        pub fn is_empty(&self) -> bool {
            self.width().approx_eq_cairo(0.0) || self.height().approx_eq_cairo(0.0)
        }

        #[inline]
        pub fn scale(self, x: f64, y: f64) -> Self {
            Self {
                x0: self.x0 * x,
                y0: self.y0 * y,
                x1: self.x1 * x,
                y1: self.y1 * y,
            }
        }

        pub fn approx_eq(&self, other: &Self) -> bool {
            // FIXME: this is super fishy; shouldn't we be using 2x the epsilon against the width/height
            // instead of the raw coordinates?
            approx_eq!(f64, self.x0, other.x0)
                && approx_eq!(f64, self.y0, other.y0)
                && approx_eq!(f64, self.x1, other.x1)
                && approx_eq!(f64, self.y1, other.y1)
        }
    }
}

pub type Rect = rect::Rect<f64>;

impl From<Rect> for IRect {
    #[inline]
    fn from(r: Rect) -> Self {
        Self {
            x0: r.x0.floor() as i32,
            y0: r.y0.floor() as i32,
            x1: r.x1.ceil() as i32,
            y1: r.y1.ceil() as i32,
        }
    }
}

impl From<cairo::Rectangle> for Rect {
    #[inline]
    fn from(r: cairo::Rectangle) -> Self {
        Self {
            x0: r.x,
            y0: r.y,
            x1: r.x + r.width,
            y1: r.y + r.height,
        }
    }
}

impl From<Rect> for cairo::Rectangle {
    #[inline]
    fn from(r: Rect) -> Self {
        Self {
            x: r.x0,
            y: r.y0,
            width: r.x1 - r.x0,
            height: r.y1 - r.y0,
        }
    }
}

pub type IRect = rect::Rect<i32>;

impl From<IRect> for Rect {
    #[inline]
    fn from(r: IRect) -> Self {
        Self {
            x0: f64::from(r.x0),
            y0: f64::from(r.y0),
            x1: f64::from(r.x1),
            y1: f64::from(r.y1),
        }
    }
}

impl From<cairo::Rectangle> for IRect {
    #[inline]
    fn from(r: cairo::Rectangle) -> Self {
        Self {
            x0: r.x.floor() as i32,
            y0: r.y.floor() as i32,
            x1: (r.x + r.width).ceil() as i32,
            y1: (r.y + r.height).ceil() as i32,
        }
    }
}

impl From<IRect> for cairo::Rectangle {
    #[inline]
    fn from(r: IRect) -> Self {
        Self {
            x: f64::from(r.x0),
            y: f64::from(r.y0),
            width: f64::from(r.x1 - r.x0),
            height: f64::from(r.y1 - r.y0),
        }
    }
}
<commit_msg>Increase the epsilon for Rect::approx_eq()<commit_after>//! Types for rectangles.

#[allow(clippy::module_inception)]
mod rect {
    use crate::float_eq_cairo::ApproxEqCairo;
    use core::ops::{Add, Range, Sub};
    use float_cmp::approx_eq;
    use num_traits::Zero;

    // Use our own min() and max() that are acceptable for floating point

    fn min<T: PartialOrd>(x: T, y: T) -> T {
        if x <= y {
            x
        } else {
            y
        }
    }

    fn max<T: PartialOrd>(x: T, y: T) -> T {
        if x >= y {
            x
        } else {
            y
        }
    }

    #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
    pub struct Rect<T> {
        pub x0: T,
        pub y0: T,
        pub x1: T,
        pub y1: T,
    }

    impl<T> Rect<T> {
        #[inline]
        pub fn new(x0: T, y0: T, x1: T, y1: T) -> Self {
            Self { x0, y0, x1, y1 }
        }
    }

    impl<T> Rect<T>
    where
        T: Copy + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T> + Zero,
    {
        #[inline]
        pub fn from_size(w: T, h: T) -> Self {
            Self {
                x0: Zero::zero(),
                y0: Zero::zero(),
                x1: w,
                y1: h,
            }
        }

        #[inline]
        pub fn width(&self) -> T {
            self.x1 - self.x0
        }

        #[inline]
        pub fn height(&self) -> T {
            self.y1 - self.y0
        }

        #[inline]
        pub fn size(&self) -> (T, T) {
            (self.width(), self.height())
        }

        #[inline]
        pub fn x_range(&self) -> Range<T> {
            self.x0..self.x1
        }

        #[inline]
        pub fn y_range(&self) -> Range<T> {
            self.y0..self.y1
        }

        #[inline]
        pub fn contains(self, x: T, y: T) -> bool {
            x >= self.x0 && x < self.x1 && y >= self.y0 && y < self.y1
        }

        #[inline]
        pub fn translate(&self, by: (T, T)) -> Self {
            Self {
                x0: self.x0 + by.0,
                y0: self.y0 + by.1,
                x1: self.x1 + by.0,
                y1: self.y1 + by.1,
            }
        }

        #[inline]
        pub fn intersection(&self, rect: &Self) -> Option<Self> {
            let (x0, y0, x1, y1) = (
                max(self.x0, rect.x0),
                max(self.y0, rect.y0),
                min(self.x1, rect.x1),
                min(self.y1, rect.y1),
            );

            if x1 > x0 && y1 > y0 {
                Some(Self { x0, y0, x1, y1 })
            } else {
                None
            }
        }

        #[inline]
        pub fn union(&self, rect: &Self) -> Self {
            Self {
                x0: min(self.x0, rect.x0),
                y0: min(self.y0, rect.y0),
                x1: max(self.x1, rect.x1),
                y1: max(self.y1, rect.y1),
            }
        }
    }

    impl Rect<i32> {
        #[inline]
        pub fn is_empty(&self) -> bool {
            // Give an explicit type to the right hand side of the ==, since sometimes
            // type inference fails to figure it out.  I have no idea why.
            self.width() == <i32 as Zero>::zero() || self.height() == <i32 as Zero>::zero()
        }

        #[inline]
        pub fn scale(self, x: f64, y: f64) -> Self {
            Self {
                x0: (f64::from(self.x0) * x).floor() as i32,
                y0: (f64::from(self.y0) * y).floor() as i32,
                x1: (f64::from(self.x1) * x).ceil() as i32,
                y1: (f64::from(self.y1) * y).ceil() as i32,
            }
        }
    }

    impl Rect<f64> {
        #[inline]
        pub fn is_empty(&self) -> bool {
            self.width().approx_eq_cairo(0.0) || self.height().approx_eq_cairo(0.0)
        }

        #[inline]
        pub fn scale(self, x: f64, y: f64) -> Self {
            Self {
                x0: self.x0 * x,
                y0: self.y0 * y,
                x1: self.x1 * x,
                y1: self.y1 * y,
            }
        }

        pub fn approx_eq(&self, other: &Self) -> bool {
            // FIXME: this is super fishy; shouldn't we be using 2x the epsilon against the width/height
            // instead of the raw coordinates?
            approx_eq!(f64, self.x0, other.x0, epsilon = 0.0001)
                && approx_eq!(f64, self.y0, other.y0, epsilon = 0.0001)
                && approx_eq!(f64, self.x1, other.x1, epsilon = 0.0001)
                && approx_eq!(f64, self.y1, other.y1, epsilon = 0.00012)
        }
    }
}

pub type Rect = rect::Rect<f64>;

impl From<Rect> for IRect {
    #[inline]
    fn from(r: Rect) -> Self {
        Self {
            x0: r.x0.floor() as i32,
            y0: r.y0.floor() as i32,
            x1: r.x1.ceil() as i32,
            y1: r.y1.ceil() as i32,
        }
    }
}

impl From<cairo::Rectangle> for Rect {
    #[inline]
    fn from(r: cairo::Rectangle) -> Self {
        Self {
            x0: r.x,
            y0: r.y,
            x1: r.x + r.width,
            y1: r.y + r.height,
        }
    }
}

impl From<Rect> for cairo::Rectangle {
    #[inline]
    fn from(r: Rect) -> Self {
        Self {
            x: r.x0,
            y: r.y0,
            width: r.x1 - r.x0,
            height: r.y1 - r.y0,
        }
    }
}

pub type IRect = rect::Rect<i32>;

impl From<IRect> for Rect {
    #[inline]
    fn from(r: IRect) -> Self {
        Self {
            x0: f64::from(r.x0),
            y0: f64::from(r.y0),
            x1: f64::from(r.x1),
            y1: f64::from(r.y1),
        }
    }
}

impl From<cairo::Rectangle> for IRect {
    #[inline]
    fn from(r: cairo::Rectangle) -> Self {
        Self {
            x0: r.x.floor() as i32,
            y0: r.y.floor() as i32,
            x1: (r.x + r.width).ceil() as i32,
            y1: (r.y + r.height).ceil() as i32,
        }
    }
}

impl From<IRect> for cairo::Rectangle {
    #[inline]
    fn from(r: IRect) -> Self {
        Self {
            x: f64::from(r.x0),
            y: f64::from(r.y0),
            width: f64::from(r.x1 - r.x0),
            height: f64::from(r.y1 - r.y0),
        }
    }
}
<|endoftext|>


<commit_before>//! [Lambda terms](https://en.wikipedia.org/wiki/Lambda_calculus#Lambda_terms)

use self::Term::*;
use self::Error::*;
use std::fmt;
use std::borrow::Cow;

/// A lambda term that is either a variable with a De Bruijn index, an abstraction over a term or
/// an applicaction of one term to another.
#[derive(Debug, PartialEq, Clone)]
pub enum Term {
    Var(usize),
    Abs(Box<Term>),
    App(Box<Term>, Box<Term>)
}

/// An error that can be returned when an inapplicable function is applied to a term.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotAVar,
    NotAnAbs,
    NotAnApp,
    NotANum,
    NotAPair,
    NotAList
}

impl Term {
    /// Applies `self` to another term without substitution or reduction.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::arithmetic::{zero, succ};
    ///
    /// assert_eq!(succ().app(zero()), App(Box::new(succ()), Box::new(zero())));
    /// ```
    pub fn app(self, argument: Term) -> Term { App(Box::new(self), Box::new(argument)) }

    /// Consumes a lambda variable and returns its De Bruijn index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar(), Ok(1));
    /// ```
    pub fn unvar(self) -> Result<usize, Error> {
        match self {
            Var(n) => Ok(n),
            _ => Err(NotAVar)
        }
    }

    /// Consumes an abstraction and returns its underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs(), Ok(Var(1)));
    /// ```
    pub fn unabs(self) -> Result<Term, Error> {
        match self {
            Abs(x) => Ok(*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref(), Ok(&Var(1)));
    /// ```
    pub fn unabs_ref(&self) -> Result<&Term, Error> {
        match *self {
            Abs(ref x) => Ok(&*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a mutable reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn unabs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        match *self {
            Abs(ref mut x) => Ok(&mut *x),
            _ => Err(NotAnAbs)
        }
    }

    /// Consumes an application and returns a pair containing its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp(), Ok((Var(0), Var(1))));
    /// ```
    pub fn unapp(self) -> Result<(Term, Term), Error> {
        match self {
            App(lhs, rhs) => Ok((*lhs, *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref(), Ok((&Var(0), &Var(1))));
    /// ```
    pub fn unapp_ref(&self) -> Result<(&Term, &Term), Error> {
        match *self {
            App(ref lhs, ref rhs) => Ok((&*lhs, &*rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing mutable references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref_mut(), Ok((&mut Var(0), &mut Var(1))));
    /// ```
    pub fn unapp_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        match *self {
            App(ref mut lhs, ref mut rhs) => Ok((&mut *lhs, &mut *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns the left-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs(), Ok(Var(0)));
    /// ```
    pub fn lhs(self) -> Result<Term, Error> {
        if let Ok((lhs, _)) = self.unapp() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref(), Ok(&Var(0)));
    /// ```
    pub fn lhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref_mut(), Ok(&mut Var(0)));
    /// ```
    pub fn lhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref_mut() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns the right-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs(), Ok(Var(1)));
    /// ```
    pub fn rhs(self) -> Result<Term, Error> {
        if let Ok((_, rhs)) = self.unapp() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref(), Ok(&Var(1)));
    /// ```
    pub fn rhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn rhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref_mut() { Ok(rhs) } else { Err(NotAnApp) }
    }
}

/// Wraps a term in an abstraction. Consumes its argument.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::abs;
///
/// assert_eq!(abs(Var(1)), Abs(Box::new(Var(1))));
/// ```
pub fn abs(term: Term) -> Term { Abs(Box::new(term)) }

/// Produces an application of its arguments without substitution or reduction, consuming them in
/// the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::app;
///
/// assert_eq!(app(Var(0), Var(1)), App(Box::new(Var(0)), Box::new(Var(1))));
/// ```
pub fn app(lhs: Term, rhs: Term) -> Term { App(Box::new(lhs), Box::new(rhs)) }

/// Applies two terms with substitution and variable update (but without reduction), consuming them
/// in the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    Ok(lhs.unabs().unwrap())
}

fn _apply(lhs: &mut Term, rhs: Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs; // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 2) // update free variables' indices from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs.clone(), depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth);
        }
    }
}

fn update_free_variables(term: &mut Term, depth: usize) {
    match *term {
        Var(i) => if i > depth {
            *term = Var(i + depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), depth + 1)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), depth);
        }
    }
}

/// Set to `true` for λ or `false` for \ when displaying lambda terms. The default is `true`.
pub const DISPLAY_PRETTY: bool = true;

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", show_precedence(0, self))
    }
}

fn show_precedence(context_precedence: usize, term: &Term) -> String {
    match *term {
        Var(i) => format!("{:X}", i), // max. index = 15
        Abs(ref t) => {
            let ret = format!("{}{}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, t);
            parenthesize_if(context_precedence > 1, &ret).into()
        },
        App(ref t1, ref t2) => {
            let ret = format!("{}{}", show_precedence(2, t1), show_precedence(3, t2));
            parenthesize_if(context_precedence == 3, &ret).into()
        }
    }
}

fn parenthesize_if(condition: bool, input: &str) -> Cow<str> {
    if condition {
        format!("({})", input).into()
    } else {
        input.into()
    }
}

// WIP
/*
fn beta_reduce(mut term: Term) -> Result<Term, Error> {
    match term {
        App(lhs, rhs) => term = try!(apply(*lhs, *rhs)),
        Abs(t) => try!(beta_reduce(*t)),
        _ => ()
    }

    Ok(term)
}
*/
fn _beta_reduce(term: &mut Term) {
    match *term {
        App(_, _) => {
            let (lhs, rhs) = term.clone().unapp().unwrap();
            println!("attempting to reduce {}...", *term);
            if let Ok(reduced) = apply(lhs, rhs) {
                println!("\tattempt successful: {}", reduced);
                *term = reduced;
            } else {
                println!("\tfailed; trying to reduce the inner terms");
                let (mut lhs, mut rhs) = term.clone().unapp().unwrap();
                _beta_reduce(&mut lhs);
                _beta_reduce(&mut rhs);
            }
        },
        Abs(ref mut t) => _beta_reduce(t),
        _ => ()
    }
}

#[cfg(test)]
mod test {
    use arithmetic::*;
    use term::{apply, _beta_reduce};

    #[test]
    fn applying() {
        let mut unreduced = apply(succ(), zero()).unwrap();
        println!("before: {}", unreduced);
        let _ = _beta_reduce(&mut unreduced);
        println!("after: {}", unreduced);
    }

    #[test]
    fn displaying_terms() {
        assert_eq!(&format!("{}", zero()), "λλ1");
        assert_eq!(&format!("{}", succ()), "λλλ2(321)");
        assert_eq!(&format!("{}", pred()), "λλλ3(λλ1(24))(λ2)(λ1)");
    }
}
<commit_msg>Fix apply()<commit_after>//! [Lambda terms](https://en.wikipedia.org/wiki/Lambda_calculus#Lambda_terms)

use self::Term::*;
use self::Error::*;
use std::fmt;
use std::borrow::Cow;

/// A lambda term that is either a variable with a De Bruijn index, an abstraction over a term or
/// an applicaction of one term to another.
#[derive(Debug, PartialEq, Clone)]
pub enum Term {
    Var(usize),
    Abs(Box<Term>),
    App(Box<Term>, Box<Term>)
}

/// An error that can be returned when an inapplicable function is applied to a term.
#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    NotAVar,
    NotAnAbs,
    NotAnApp,
    NotANum,
    NotAPair,
    NotAList
}

impl Term {
    /// Applies `self` to another term without substitution or reduction.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::arithmetic::{zero, succ};
    ///
    /// assert_eq!(succ().app(zero()), App(Box::new(succ()), Box::new(zero())));
    /// ```
    pub fn app(self, argument: Term) -> Term { App(Box::new(self), Box::new(argument)) }

    /// Consumes a lambda variable and returns its De Bruijn index.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(1).unvar(), Ok(1));
    /// ```
    pub fn unvar(self) -> Result<usize, Error> {
        match self {
            Var(n) => Ok(n),
            _ => Err(NotAVar)
        }
    }

    /// Consumes an abstraction and returns its underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs(), Ok(Var(1)));
    /// ```
    pub fn unabs(self) -> Result<Term, Error> {
        match self {
            Abs(x) => Ok(*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref(), Ok(&Var(1)));
    /// ```
    pub fn unabs_ref(&self) -> Result<&Term, Error> {
        match *self {
            Abs(ref x) => Ok(&*x),
            _ => Err(NotAnAbs)
        }
    }

    /// Returns a mutable reference to an abstraction's underlying term.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    /// use lambda_calculus::term::abs;
    ///
    /// assert_eq!(abs(Var(1)).unabs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn unabs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        match *self {
            Abs(ref mut x) => Ok(&mut *x),
            _ => Err(NotAnAbs)
        }
    }

    /// Consumes an application and returns a pair containing its underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp(), Ok((Var(0), Var(1))));
    /// ```
    pub fn unapp(self) -> Result<(Term, Term), Error> {
        match self {
            App(lhs, rhs) => Ok((*lhs, *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref(), Ok((&Var(0), &Var(1))));
    /// ```
    pub fn unapp_ref(&self) -> Result<(&Term, &Term), Error> {
        match *self {
            App(ref lhs, ref rhs) => Ok((&*lhs, &*rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns a pair containing mutable references to an application's underlying terms.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).unapp_ref_mut(), Ok((&mut Var(0), &mut Var(1))));
    /// ```
    pub fn unapp_ref_mut(&mut self) -> Result<(&mut Term, &mut Term), Error> {
        match *self {
            App(ref mut lhs, ref mut rhs) => Ok((&mut *lhs, &mut *rhs)),
            _ => Err(NotAnApp)
        }
    }

    /// Returns the left-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs(), Ok(Var(0)));
    /// ```
    pub fn lhs(self) -> Result<Term, Error> {
        if let Ok((lhs, _)) = self.unapp() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref(), Ok(&Var(0)));
    /// ```
    pub fn lhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the left-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).lhs_ref_mut(), Ok(&mut Var(0)));
    /// ```
    pub fn lhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((lhs, _)) = self.unapp_ref_mut() { Ok(lhs) } else { Err(NotAnApp) }
    }

    /// Returns the right-hand side term of an application. Consumes `self`.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs(), Ok(Var(1)));
    /// ```
    pub fn rhs(self) -> Result<Term, Error> {
        if let Ok((_, rhs)) = self.unapp() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref(), Ok(&Var(1)));
    /// ```
    pub fn rhs_ref(&self) -> Result<&Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref() { Ok(rhs) } else { Err(NotAnApp) }
    }

    /// Returns a mutable reference to the right-hand side term of an application.
    ///
    /// # Example
    /// ```
    /// use lambda_calculus::term::Term::*;
    ///
    /// assert_eq!(Var(0).app(Var(1)).rhs_ref_mut(), Ok(&mut Var(1)));
    /// ```
    pub fn rhs_ref_mut(&mut self) -> Result<&mut Term, Error> {
        if let Ok((_, rhs)) = self.unapp_ref_mut() { Ok(rhs) } else { Err(NotAnApp) }
    }
}

/// Wraps a term in an abstraction. Consumes its argument.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::abs;
///
/// assert_eq!(abs(Var(1)), Abs(Box::new(Var(1))));
/// ```
pub fn abs(term: Term) -> Term { Abs(Box::new(term)) }

/// Produces an application of its arguments without substitution or reduction, consuming them in
/// the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::Term::*;
/// use lambda_calculus::term::app;
///
/// assert_eq!(app(Var(0), Var(1)), App(Box::new(Var(0)), Box::new(Var(1))));
/// ```
pub fn app(lhs: Term, rhs: Term) -> Term { App(Box::new(lhs), Box::new(rhs)) }

/// Applies two terms with substitution and variable update (but without reduction), consuming them
/// in the process.
///
/// # Example
/// ```
/// use lambda_calculus::term::apply;
/// use lambda_calculus::parser::parse;
///
/// let lhs    = parse(&"λλ42(λ13)").unwrap();
/// let rhs    = parse(&"λ51").unwrap();
/// let result = parse(&"λ3(λ61)(λ1(λ71))").unwrap();
///
/// assert_eq!(apply(lhs, rhs), Ok(result));
/// ```
pub fn apply(mut lhs: Term, rhs: Term) -> Result<Term, Error> {
    _apply(&mut lhs, rhs, 0);

    Ok(try!(lhs.unabs()))
}

fn _apply(lhs: &mut Term, rhs: Term, depth: usize) {
    match *lhs {
        Var(i) => if i == depth {
            *lhs = rhs; // substitute a top-level variable from lhs with rhs
            update_free_variables(lhs, depth - 1) // update free variables' indices from rhs
        } else if i > depth {
            *lhs = Var(i - 1) // decrement a free variable's index
        },
        Abs(_) => {
            _apply(lhs.unabs_ref_mut().unwrap(), rhs, depth + 1)
        },
        App(_, _) => {
            _apply(lhs.lhs_ref_mut().unwrap(), rhs.clone(), depth);
            _apply(lhs.rhs_ref_mut().unwrap(), rhs, depth);
        }
    }
}

fn update_free_variables(term: &mut Term, depth: usize) {
    match *term {
        Var(i) => if i > depth {
            *term = Var(i + depth)
        },
        Abs(_) => {
            update_free_variables(term.unabs_ref_mut().unwrap(), depth)
        },
        App(_, _) => {
            update_free_variables(term.lhs_ref_mut().unwrap(), depth);
            update_free_variables(term.rhs_ref_mut().unwrap(), depth);
        }
    }
}

/// Set to `true` for λ or `false` for \ when displaying lambda terms. The default is `true`.
pub const DISPLAY_PRETTY: bool = true;

impl fmt::Display for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", show_precedence(0, self))
    }
}

fn show_precedence(context_precedence: usize, term: &Term) -> String {
    match *term {
        Var(i) => format!("{:X}", i), // max. index = 15
        Abs(ref t) => {
            let ret = format!("{}{}", if DISPLAY_PRETTY { 'λ' } else { '\\' }, t);
            parenthesize_if(context_precedence > 1, &ret).into()
        },
        App(ref t1, ref t2) => {
            let ret = format!("{}{}", show_precedence(2, t1), show_precedence(3, t2));
            parenthesize_if(context_precedence == 3, &ret).into()
        }
    }
}

fn parenthesize_if(condition: bool, input: &str) -> Cow<str> {
    if condition {
        format!("({})", input).into()
    } else {
        input.into()
    }
}

// WIP
/*
fn beta_reduce(mut term: Term) -> Result<Term, Error> {
    match term {
        App(lhs, rhs) => term = try!(apply(*lhs, *rhs)),
        Abs(t) => try!(beta_reduce(*t)),
        _ => ()
    }

    Ok(term)
}
*/
fn _beta_reduce(term: &mut Term) {
    match *term {
        App(_, _) => {
            let (lhs, rhs) = term.clone().unapp().unwrap();
            println!("attempting to reduce {}...", *term);
            if let Ok(reduced) = apply(lhs, rhs) {
                println!("\tattempt successful: {}", reduced);
                *term = reduced;
            } else {
                println!("\tfailed; trying to reduce the inner terms");
                let (mut lhs, mut rhs) = term.clone().unapp().unwrap();
                _beta_reduce(&mut lhs);
                _beta_reduce(&mut rhs);
            }
        },
        Abs(ref mut t) => _beta_reduce(t),
        _ => ()
    }
}

#[cfg(test)]
mod test {
    use arithmetic::*;
    use term::{apply, _beta_reduce};

    #[test]
    fn applying() {
        let mut unreduced = apply(succ(), zero()).unwrap();
        println!("before: {}", unreduced);
        let _ = _beta_reduce(&mut unreduced);
        println!("after: {}", unreduced);
    }

    #[test]
    fn displaying_terms() {
        assert_eq!(&format!("{}", zero()), "λλ1");
        assert_eq!(&format!("{}", succ()), "λλλ2(321)");
        assert_eq!(&format!("{}", pred()), "λλλ3(λλ1(24))(λ2)(λ1)");
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]

#[phase(plugin)]
extern crate phf_mac;
extern crate phf;

mod map {
    use std::collections::{HashMap, HashSet};
    use phf::PhfMap;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfMap<int> = phf_map!(
        "foo" => 10,
    );

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfMap<int> = phf_map!(
        "foo" => 10
    );

    #[test]
    fn test_two() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        assert!(Some(&10) == map.find(&("foo")));
        assert!(Some(&11) == map.find(&("bar")));
        assert_eq!(None, map.find(&("asdf")));
        assert_eq!(2, map.len());
    }

    #[test]
    fn test_entries() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        let mut hash = HashMap::new();
        for (key, &value) in map.entries() {
            hash.insert(key, value);
        }
        assert!(Some(&10) == hash.find(&("foo")));
        assert!(Some(&11) == hash.find(&("bar")));
        assert_eq!(2, hash.len());
    }

    #[test]
    fn test_keys() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        let mut hash = HashSet::new();
        for key in map.keys() {
            hash.insert(key);
        }
        assert!(hash.contains(&("foo")));
        assert!(hash.contains(&("bar")));
        assert_eq!(2, hash.len());
    }

    #[test]
    fn test_values() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        let mut hash = HashSet::new();
        for &value in map.values() {
            hash.insert(value);
        }
        assert!(hash.contains(&10));
        assert!(hash.contains(&11));
        assert_eq!(2, hash.len());
    }

    #[test]
    fn test_large() {
        static map: PhfMap<int> = phf_map!(
            "a" => 0,
            "b" => 1,
            "c" => 2,
            "d" => 3,
            "e" => 4,
            "f" => 5,
            "g" => 6,
            "h" => 7,
            "i" => 8,
            "j" => 9,
            "k" => 10,
            "l" => 11,
            "m" => 12,
            "n" => 13,
            "o" => 14,
            "p" => 15,
            "q" => 16,
            "r" => 17,
            "s" => 18,
            "t" => 19,
            "u" => 20,
            "v" => 21,
            "w" => 22,
            "x" => 23,
            "y" => 24,
            "z" => 25,
        );
        assert!(map.find(&("a")) == Some(&0));
    }

    #[test]
    fn test_macro_key() {
        static map: PhfMap<int> = phf_map!(
            concat!("foo", "bar") => 1
        );
        assert!(Some(&1) == map.find(&("foobar")));
    }
}

mod set {
    use std::collections::HashSet;
    use phf::PhfSet;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfSet = phf_set! {
        "foo",
    };

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfSet = phf_set! {
        "foo"
    };

    #[test]
    fn test_two() {
        static SET: PhfSet = phf_set! {
            "hello",
            "world",
        };
        assert!(SET.contains(&"hello"));
        assert!(SET.contains(&"world"));
        assert!(!SET.contains(&"foo"));
        assert_eq!(2, SET.len());
    }

    #[test]
    fn test_iter() {
        static SET: PhfSet = phf_set! {
            "hello",
            "world",
        };
        let set = SET.iter().collect::<HashSet<_>>();
        assert!(set.contains(&"hello"));
        assert!(set.contains(&"world"));
        assert_eq!(2, set.len());
    }
}

mod ordered_map {
    use phf::PhfOrderedMap;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfOrderedMap<int> = phf_ordered_map!(
        "foo" => 10,
    );

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfOrderedMap<int> = phf_ordered_map!(
        "foo" => 10
    );

    #[test]
    fn test_two() {
        static map: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
        );
        assert!(Some(&10) == map.find(&"foo"));
        assert!(Some(&11) == map.find(&"bar"));
        assert_eq!(None, map.find(&"asdf"));
        assert_eq!(2, map.len());
    }

    #[test]
    fn test_entries() {
        static MAP: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
            "baz" => 12,
        );
        let vec = MAP.entries().map(|(k, &v)| (k, v)).collect::<Vec<_>>();
        assert_eq!(vec, vec!(("foo", 10), ("bar", 11), ("baz", 12)));
    }

    #[test]
    fn test_keys() {
        static MAP: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
            "baz" => 12,
        );
        let vec = MAP.keys().collect::<Vec<_>>();
        assert_eq!(vec, vec!("foo", "bar", "baz"));
    }

    #[test]
    fn test_values() {
        static MAP: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
            "baz" => 12,
        );
        let vec = MAP.values().map(|&v| v).collect::<Vec<_>>();
        assert_eq!(vec, vec!(10, 11, 12));
    }
}

mod ordered_set {
    use phf::PhfOrderedSet;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfOrderedSet = phf_ordered_set! {
        "foo",
    };

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfOrderedSet = phf_ordered_set! {
        "foo"
    };

    #[test]
    fn test_two() {
        static SET: PhfOrderedSet = phf_ordered_set! {
            "hello",
            "there",
            "world",
        };
        assert!(SET.contains(&"hello"));
        assert!(SET.contains(&"there"));
        assert!(SET.contains(&"world"));
        assert!(!SET.contains(&"foo"));
        assert_eq!(3, SET.len());
    }

    #[test]
    fn test_iter() {
        static SET: PhfOrderedSet = phf_ordered_set! {
            "hello",
            "there",
            "world",
        };
        let vec = SET.iter().collect::<Vec<_>>();
        assert_eq!(vec, vec!("hello", "there", "world"));
    }
}
<commit_msg>Fix type inference<commit_after>#![feature(phase)]

#[phase(plugin)]
extern crate phf_mac;
extern crate phf;

mod map {
    use std::collections::{HashMap, HashSet};
    use phf::PhfMap;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfMap<int> = phf_map!(
        "foo" => 10,
    );

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfMap<int> = phf_map!(
        "foo" => 10
    );

    #[test]
    fn test_two() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        assert!(Some(&10) == map.find(&("foo")));
        assert!(Some(&11) == map.find(&("bar")));
        assert_eq!(None, map.find(&("asdf")));
        assert_eq!(2, map.len());
    }

    #[test]
    fn test_entries() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        let mut hash = HashMap::new();
        for (key, &value) in map.entries() {
            hash.insert(key, value);
        }
        assert!(Some(&10) == hash.find(&("foo")));
        assert!(Some(&11) == hash.find(&("bar")));
        assert_eq!(2, hash.len());
    }

    #[test]
    fn test_keys() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        let mut hash = HashSet::new();
        for key in map.keys() {
            hash.insert(key);
        }
        assert!(hash.contains(&("foo")));
        assert!(hash.contains(&("bar")));
        assert_eq!(2, hash.len());
    }

    #[test]
    fn test_values() {
        static map: PhfMap<int> = phf_map!(
            "foo" => 10,
            "bar" => 11,
        );
        let mut hash = HashSet::new();
        for &value in map.values() {
            hash.insert(value);
        }
        assert!(hash.contains(&10));
        assert!(hash.contains(&11));
        assert_eq!(2, hash.len());
    }

    #[test]
    fn test_large() {
        static map: PhfMap<int> = phf_map!(
            "a" => 0,
            "b" => 1,
            "c" => 2,
            "d" => 3,
            "e" => 4,
            "f" => 5,
            "g" => 6,
            "h" => 7,
            "i" => 8,
            "j" => 9,
            "k" => 10,
            "l" => 11,
            "m" => 12,
            "n" => 13,
            "o" => 14,
            "p" => 15,
            "q" => 16,
            "r" => 17,
            "s" => 18,
            "t" => 19,
            "u" => 20,
            "v" => 21,
            "w" => 22,
            "x" => 23,
            "y" => 24,
            "z" => 25,
        );
        assert!(map.find(&("a")) == Some(&0));
    }

    #[test]
    fn test_macro_key() {
        static map: PhfMap<int> = phf_map!(
            concat!("foo", "bar") => 1
        );
        assert!(Some(&1) == map.find(&("foobar")));
    }
}

mod set {
    use std::collections::HashSet;
    use phf::PhfSet;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfSet = phf_set! {
        "foo",
    };

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfSet = phf_set! {
        "foo"
    };

    #[test]
    fn test_two() {
        static SET: PhfSet = phf_set! {
            "hello",
            "world",
        };
        assert!(SET.contains(&"hello"));
        assert!(SET.contains(&"world"));
        assert!(!SET.contains(&"foo"));
        assert_eq!(2, SET.len());
    }

    #[test]
    fn test_iter() {
        static SET: PhfSet = phf_set! {
            "hello",
            "world",
        };
        let set = SET.iter().collect::<HashSet<_>>();
        assert!(set.contains(&"hello"));
        assert!(set.contains(&"world"));
        assert_eq!(2, set.len());
    }
}

mod ordered_map {
    use phf::PhfOrderedMap;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfOrderedMap<int> = phf_ordered_map!(
        "foo" => 10,
    );

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfOrderedMap<int> = phf_ordered_map!(
        "foo" => 10
    );

    #[test]
    fn test_two() {
        static map: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
        );
        assert!(Some(&10) == map.find(&"foo"));
        assert!(Some(&11) == map.find(&"bar"));
        assert_eq!(None, map.find(&"asdf"));
        assert_eq!(2, map.len());
    }

    #[test]
    fn test_entries() {
        static MAP: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
            "baz" => 12,
        );
        let vec = MAP.entries().map(|(k, &v)| (k, v)).collect::<Vec<_>>();
        assert_eq!(vec, vec!(("foo", 10i), ("bar", 11), ("baz", 12)));
    }

    #[test]
    fn test_keys() {
        static MAP: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
            "baz" => 12,
        );
        let vec = MAP.keys().collect::<Vec<_>>();
        assert_eq!(vec, vec!("foo", "bar", "baz"));
    }

    #[test]
    fn test_values() {
        static MAP: PhfOrderedMap<int> = phf_ordered_map!(
            "foo" => 10,
            "bar" => 11,
            "baz" => 12,
        );
        let vec = MAP.values().map(|&v| v).collect::<Vec<_>>();
        assert_eq!(vec, vec!(10i, 11, 12));
    }
}

mod ordered_set {
    use phf::PhfOrderedSet;

    #[allow(dead_code)]
    static TRAILING_COMMA: PhfOrderedSet = phf_ordered_set! {
        "foo",
    };

    #[allow(dead_code)]
    static NO_TRAILING_COMMA: PhfOrderedSet = phf_ordered_set! {
        "foo"
    };

    #[test]
    fn test_two() {
        static SET: PhfOrderedSet = phf_ordered_set! {
            "hello",
            "there",
            "world",
        };
        assert!(SET.contains(&"hello"));
        assert!(SET.contains(&"there"));
        assert!(SET.contains(&"world"));
        assert!(!SET.contains(&"foo"));
        assert_eq!(3, SET.len());
    }

    #[test]
    fn test_iter() {
        static SET: PhfOrderedSet = phf_ordered_set! {
            "hello",
            "there",
            "world",
        };
        let vec = SET.iter().collect::<Vec<_>>();
        assert_eq!(vec, vec!("hello", "there", "world"));
    }
}
<|endoftext|>


<commit_before>use crate::{Browser, Error, ErrorKind, Result};
use std::os::unix::process::ExitStatusExt;
use std::process::{Command, ExitStatus};

mod common;
use common::from_status;

/// Deal with opening of browsers on Linux and *BSD - currently supports only the default browser
///
/// The mechanism of opening the default browser is as follows:
/// 1. Attempt to use $BROWSER env var if available
/// 2. Attempt to open the url via xdg-open, gvfs-open, gnome-open, open, respectively, whichever works
///    first
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<()> {
    from_status(open_browser_unix(browser, url))
}

fn open_browser_unix(browser: Browser, url: &str) -> Result<ExitStatus> {
    match browser {
        Browser::Default => open_on_unix_using_browser_env(url)
            .or_else(|_| -> Result<ExitStatus> { Command::new("xdg-open").arg(url).status() })
            .or_else(|r| -> Result<ExitStatus> {
                if let Ok(desktop) = ::std::env::var("XDG_CURRENT_DESKTOP") {
                    if desktop == "KDE" {
                        return Command::new("kioclient").arg("exec").arg(url).status();
                    }
                }
                Err(r) // If either `if` check fails, fall through to the next or_else
            })
            .or_else(|_| -> Result<ExitStatus> { Command::new("gvfs-open").arg(url).status() })
            .or_else(|_| -> Result<ExitStatus> { Command::new("gnome-open").arg(url).status() })
            .or_else(|_| -> Result<ExitStatus> {
                Command::new("kioclient").arg("exec").arg(url).status()
            })
            .or_else(|e| -> Result<ExitStatus> {
                if let Ok(_child) = Command::new("x-www-browser").arg(url).spawn() {
                    return Ok(ExitStatusExt::from_raw(0));
                }
                Err(e)
            }),
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now",
        )),
    }
}

fn open_on_unix_using_browser_env(url: &str) -> Result<ExitStatus> {
    let browsers = ::std::env::var("BROWSER")
        .map_err(|_| -> Error { Error::new(ErrorKind::NotFound, "BROWSER env not set") })?;
    for browser in browsers.split(':') {
        // $BROWSER can contain ':' delimited options, each representing a potential browser command line
        if !browser.is_empty() {
            // each browser command can have %s to represent URL, while %c needs to be replaced
            // with ':' and %% with '%'
            let cmdline = browser
                .replace("%s", url)
                .replace("%c", ":")
                .replace("%%", "%");
            let cmdarr: Vec<&str> = cmdline.split_whitespace().collect();
            let mut cmd = Command::new(&cmdarr[0]);
            if cmdarr.len() > 1 {
                cmd.args(&cmdarr[1..cmdarr.len()]);
            }
            if !browser.contains("%s") {
                // append the url as an argument only if it was not already set via %s
                cmd.arg(url);
            }
            if let Ok(status) = cmd.status() {
                return Ok(status);
            }
        }
    }
    Err(Error::new(
        ErrorKind::NotFound,
        "No valid command in $BROWSER",
    ))
}
<commit_msg>Bring consistent behaviour on Unix. Non-terminal browsers are guaranteed to not block the thread<commit_after>use crate::{Browser, Error, ErrorKind, Result};
use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf;
use std::process::{Command, Stdio};

macro_rules! try_browser {
    ( $name:expr, $( $arg:expr ),+ ) => {
        for_matching_path($name, |pb| {
            let mut cmd = Command::new(pb);
            $(
                cmd.arg($arg);
            )+
            run_command(&mut cmd, !is_text_browser(&pb))
        })
    }
}

/// Deal with opening of browsers on Linux and *BSD - currently supports only the default browser
///
/// The mechanism of opening the default browser is as follows:
/// 1. Attempt to use $BROWSER env var if available
/// 2. Attempt to open the url via xdg-open, gvfs-open, gnome-open, open, respectively, whichever works
///    first
#[inline]
pub fn open_browser_internal(_: Browser, url: &str) -> Result<()> {
    // we first try with the $BROWSER env
    try_with_browser_env(url)
        // then we try with xdg-open
        .or_else(|_| try_browser!("xdg-open", url))
        // else do desktop specific stuff
        .or_else(|r| {
            // detect desktop
            let desktop_env: String = std::env::var("XDG_CURRENT_DESKTOP")
                .unwrap_or_else(|_| String::from("unknown"))
                .to_ascii_uppercase();
            match desktop_env.as_str() {
                "KDE" => try_browser!("kde-open", url).or_else(|_| try_browser!("kde-open5", url)),
                "GNOME" | "CINNAMON" => try_browser!("gio", "open", url)
                    .or_else(|_| try_browser!("gvfs-open", url))
                    .or_else(|_| try_browser!("gnome-open", url)),
                "MATE" => try_browser!("gio", "open", url)
                    .or_else(|_| try_browser!("gvfs-open", url))
                    .or_else(|_| try_browser!("mate-open", url)),
                "XFCE" => try_browser!("exo-open", url)
                    .or_else(|_| try_browser!("gio", "open", url))
                    .or_else(|_| try_browser!("gvfs-open", url)),
                _ => Err(r),
            }
        })
        // at the end, we'll try x-www-browser and return the result as is
        .or_else(|_| try_browser!("x-www-browser", url))
        // and convert the result into a () on success
        .and_then(|_| Ok(()))
        .or_else(|_| {
            Err(Error::new(
                ErrorKind::NotFound,
                "No valid browsers detected. You can specify one in BROWSERS environment variable",
            ))
        })
}

#[inline]
fn try_with_browser_env(url: &str) -> Result<()> {
    // $BROWSER can contain ':' delimited options, each representing a potential browser command line
    for browser in std::env::var("BROWSER")
        .unwrap_or_else(|_| String::from(""))
        .split(':')
    {
        if !browser.is_empty() {
            // each browser command can have %s to represent URL, while %c needs to be replaced
            // with ':' and %% with '%'
            let cmdline = browser
                .replace("%s", url)
                .replace("%c", ":")
                .replace("%%", "%");
            let cmdarr: Vec<&str> = cmdline.split_ascii_whitespace().collect();
            let browser_cmd = cmdarr[0];
            let env_exit = for_matching_path(browser_cmd, |pb| {
                let mut cmd = Command::new(pb);
                for i in 1..cmdarr.len() {
                    cmd.arg(cmdarr[i]);
                }
                if !browser.contains("%s") {
                    // append the url as an argument only if it was not already set via %s
                    cmd.arg(url);
                }
                run_command(&mut cmd, !is_text_browser(&pb))
            });
            if env_exit.is_ok() {
                return Ok(());
            }
        }
    }
    Err(Error::new(
        ErrorKind::NotFound,
        "No valid browser configured in BROWSER environment variable",
    ))
}

/// Returns true if specified command refers to a known list of text browsers
#[inline]
fn is_text_browser(pb: &PathBuf) -> bool {
    for browser in TEXT_BROWSERS.iter() {
        if pb.ends_with(&browser) {
            return true;
        }
    }
    false
}

#[inline]
fn for_matching_path<F>(name: &str, op: F) -> Result<()>
where
    F: FnOnce(&PathBuf) -> Result<()>,
{
    let err = Err(Error::new(ErrorKind::NotFound, "command not found"));

    // if the name already includes path separator, we should not try to do a PATH search on it
    // as it's likely an absolutely or relative name, so we treat it as such.
    if name.contains(std::path::MAIN_SEPARATOR) {
        let pb = std::path::PathBuf::from(name);
        if let Ok(metadata) = pb.metadata() {
            if metadata.is_file() && metadata.permissions().mode() & 0o111 != 0 {
                return op(&pb);
            }
        } else {
            return err;
        }
    } else {
        // search for this name inside PATH
        if let Ok(path) = std::env::var("PATH") {
            for entry in path.split(":") {
                let mut pb = std::path::PathBuf::from(entry);
                pb.push(name);
                if let Ok(metadata) = pb.metadata() {
                    if metadata.is_file() && metadata.permissions().mode() & 0o111 != 0 {
                        return op(&pb);
                    }
                }
            }
        }
    }
    // return the not found err, if we didn't find anything above
    err
}

/// Run the specified command in foreground/background
#[inline]
fn run_command(cmd: &mut Command, background: bool) -> Result<()> {
    if background {
        // if we're in background, set stdin/stdout to null and spawn a child, as we're
        // not supposed to have any interaction.
        cmd.stdin(Stdio::null())
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .spawn()
            .and_then(|_| Ok(()))
    } else {
        // if we're in foreground, use status() instead of spawn(), as we'd like to wait
        // till completion
        cmd.status().and_then(|status| {
            if status.success() {
                Ok(())
            } else {
                Err(Error::new(
                    ErrorKind::Other,
                    "command present but exited unsuccessfully",
                ))
            }
        })
    }
}

static TEXT_BROWSERS: [&'static str; 9] = [
    "lynx", "links", "links2", "elinks", "w3m", "eww", "netrik", "retawq", "curl",
];
<|endoftext|>


<commit_before>extern crate time;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

/// Calculate the exponential weighted moving average for a vector of numbers, with a smoothing
/// factor `alpha` between 0 and 1. A higher `alpha` discounts older observations faster.
pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> f64 {
    let (prev_sample, prev_avg) = samples.iter().fold((0.0, 0.0), |acc, ref sample| match acc {
        (0.0, 0.0) => (sample.to_f64().unwrap(), sample.to_f64().unwrap()),
        (prev_sample, prev_avg) => (sample.to_f64().unwrap(), alpha * prev_sample + (1.0 - alpha) * prev_avg)
    });
    alpha * prev_sample + (1.0 - alpha) * prev_avg
}

mod test {
    #[test]
    fn test_ewma_empty_vector() {
        use super::ewma;

        let empty: Vec<u32> = vec!();
        let alpha = 1.0/3.0;
        assert_eq!(ewma(empty, alpha), 0.0);
    }

    #[test]
    fn test_ewma_one_element() {
        use super::ewma;

        let input = vec!(1u);
        let alpha = 1.0/3.0;
        assert_eq!(ewma(input, alpha), 1.0);
    }

    #[test]
    fn test_exponential_smoothed_moving_average() {
        use super::ewma;
        use std::iter::range_inclusive;

        let input = range_inclusive(1u, 10).collect();
        let alpha = 1.0/3.0;
        let expected = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0];
        assert_eq!(ewma(input, alpha), expected[expected.len() - 1]);
    }
}
<commit_msg>Import trait.<commit_after>extern crate time;

use std::num::ToPrimitive;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

/// Calculate the exponential weighted moving average for a vector of numbers, with a smoothing
/// factor `alpha` between 0 and 1. A higher `alpha` discounts older observations faster.
pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> f64 {
    let (prev_sample, prev_avg) = samples.iter().fold((0.0, 0.0), |acc, ref sample| match acc {
        (0.0, 0.0) => (sample.to_f64().unwrap(), sample.to_f64().unwrap()),
        (prev_sample, prev_avg) => (sample.to_f64().unwrap(), alpha * prev_sample + (1.0 - alpha) * prev_avg)
    });
    alpha * prev_sample + (1.0 - alpha) * prev_avg
}

mod test {
    #[test]
    fn test_ewma_empty_vector() {
        use super::ewma;

        let empty: Vec<u32> = vec!();
        let alpha = 1.0/3.0;
        assert_eq!(ewma(empty, alpha), 0.0);
    }

    #[test]
    fn test_ewma_one_element() {
        use super::ewma;

        let input = vec!(1u);
        let alpha = 1.0/3.0;
        assert_eq!(ewma(input, alpha), 1.0);
    }

    #[test]
    fn test_exponential_smoothed_moving_average() {
        use super::ewma;
        use std::iter::range_inclusive;

        let input = range_inclusive(1u, 10).collect();
        let alpha = 1.0/3.0;
        let expected = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0];
        assert_eq!(ewma(input, alpha), expected[expected.len() - 1]);
    }
}
<|endoftext|>