<commit_before>use std::cmp::Ord;
use std::option::{None, Option, Some};
use std::to_string::ToString;

/// FourNode
struct FourNode<V: ToString+Ord>(V, V, V, Option<(Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>)>);

impl <V: ToString+Ord> FourNode<V> {

    fn new(node: Node<V>, value: V) -> FourNode<V> {
        match node {
            LeafThreeNode(value1, value2) =>
                if value > value2      { FourNode(value1, value2, value, None) }
                else if value < value1 { FourNode(value, value1, value2, None) }
                else                   { FourNode(value1, value, value2, None) },
            _ => fail!(""),
        }
    }

    /// Convert a Split into a TwoNode with the middle value as the value of the new parent node
    fn to_two_node(self) -> Node<V> {
        match self {
            FourNode(v1, v2, v3, None) => TwoNode(v2, box LeafTwoNode(v1), box LeafTwoNode(v3)),
            FourNode(v1, v2, v3, Some((n1, n2, n3, n4))) => TwoNode(v2, box TwoNode(v1, n1, n2), box TwoNode(v3, n3, n4)),
        }
    }
}

/// InsertResult
enum InsertResult<V: ToString+Ord> {
    Fit(Node<V>),  // box this node?
    Split(FourNode<V>),  // split should always contain a ThreeNode/LeafThreeNode. box this?
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Node
enum Node<V: ToString+Ord> {
    LeafTwoNode(V),
    LeafThreeNode(V, V),
    TwoNode(V, Box<Node<V>>, Box<Node<V>>),
    ThreeNode(V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
}

impl <V: ToString+Ord> ToString for Node<V> {
    fn to_string(&self) -> String {
        match *self {
            LeafTwoNode(ref v) => format!("LeafTwoNode({:s})", v.to_string()),
            LeafThreeNode(ref v1, ref v2) => format!("LeafThreeNode({:s}, {:s})", v1.to_string(), v2.to_string()),
            TwoNode(ref v, ref left, ref middle) => format!("TwoNode({:s}, {:s}, {:s})", v.to_string(), left.to_string(), middle.to_string()),
            ThreeNode(_, _, ref left, ref middle, ref right) => format!("ThreeNode({:s}, {:s}, {:s})", left.to_string(), middle.to_string(), right.to_string()),
        }
    }
}

impl <V: ToString+Ord> Node<V> {
    // PRIVATE
    /// Extend this TwoNode with the provided value and child node to make it a ThreeNode
    fn extend(self, other_value: V, other_node: Box<Node<V>>) -> Node<V> {
        match self {
            TwoNode(self_value, self_left, self_middle) => {
                if self_value > other_value {
                    ThreeNode(other_value, self_value, other_node, self_left, self_middle)
                } else {
                    ThreeNode(self_value, other_value, self_left, self_middle, other_node)
                }
            }
            _ => fail!(""),
        }
    }

    fn extend4(self, other_value: V, other_node: Box<Node<V>>) -> FourNode<V> {
        match self {
            ThreeNode(self_value1, self_value2, self_left, self_middle, self_right) => {
                if other_value < self_value1 {
                    FourNode(other_value, self_value1, self_value2, Some((other_node, self_left, self_middle, self_right)))
                } else {
                    FourNode(self_value1, self_value2, other_value, Some((self_left, self_middle, self_right, other_node)))
                }
            }
            _ => fail!(""),
        }
    }

    fn next_direction(&self, to_insert: &V) -> Direction {
        match *self {
            TwoNode(ref value, _, _) =>
                if *to_insert < *value { Left }
                else                   { Middle },
            ThreeNode(ref value1, ref value2, _, _, _) =>
                if      *to_insert < *value1 { Left }
                else if *to_insert > *value2 { Right }
                else                         { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &TwoNode(ref v, _, _) |
                &LeafTwoNode(ref v) if to_check == v => true,

            &ThreeNode(ref v1, ref v2, _, _, _) |
                &LeafThreeNode(ref v1, ref v2) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            LeafTwoNode(value) => {
                if to_insert > value { Fit(LeafThreeNode(value, to_insert)) }
                else                 { Fit(LeafThreeNode(to_insert, value)) }
            },

            // Split if leaf ThreeNode
            node @ LeafThreeNode(..) => Split(FourNode::new(node, to_insert)),

            // Recurse down if internal Node and handle results
            TwoNode(value, box left, box middle) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => fail!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left => TwoNode(value, box returned_node, box other_node),
                            Middle => TwoNode(value, box other_node, box returned_node),
                            _ => fail!(""),
                        },
                    Split(four_node) => four_node.to_two_node().extend(value, box other_node),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            ThreeNode(value1, value2, left, middle, right) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => fail!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let new_node = match next_direction {
                            Left => ThreeNode(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => ThreeNode(value1, value2, other_node1, box returned_node, other_node2),
                            Right => ThreeNode(value1, value2, other_node1, other_node2, box returned_node),
                            _ => fail!(""),
                        };
                        Fit(new_node)
                    },
                    Split(four_node) => {
                        let new_node: FourNode<V> = match next_direction {
                            Left => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Middle => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Right => four_node.to_two_node().extend(value2, other_node2).extend4(value1, other_node1),
                            _ => fail!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: ToString+Ord> {
    root: Option<Node<V>>,
}

impl <V: ToString+Ord> ToString for TTTree<V> {
    fn to_string(&self) -> String {
        match self.root {
            Some(ref node) => node.to_string(),
            None => "TTTree(<empty>)".to_string(),
        }
    }
}

impl <V: ToString+Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => LeafTwoNode(value),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(node @ FourNode(..)) => node.to_two_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}

// TODO:
// Collection trait
// convert this to Key/Value K/V
// remove ToString debugging stuffs

#[test]
fn it_works() {
    let mut tree: TTTree<uint> = TTTree::new();

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(60);
    match tree {
        TTTree{root: Some(LeafThreeNode(50, 60))} => (),
        _ => fail!(),
    }

    tree.insert(70);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafTwoNode(70)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(100);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(55);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafThreeNode(50, 55),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(68);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafTwoNode(100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(75);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafThreeNode(75, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(52);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box TwoNode(52,
                    box LeafTwoNode(50),
                    box LeafTwoNode(55),
                ),
                box TwoNode(70,
                    box LeafTwoNode(68),
                    box LeafThreeNode(75, 100),
                ),
            )
        )} => (),
        _ => fail!(),
    }
}
<commit_msg>Simplify dereferencing<commit_after>use std::cmp::Ord;
use std::option::{None, Option, Some};
use std::to_string::ToString;

/// FourNode
struct FourNode<V: ToString+Ord>(V, V, V, Option<(Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>)>);

impl <V: ToString+Ord> FourNode<V> {

    fn new(node: Node<V>, value: V) -> FourNode<V> {
        match node {
            LeafThreeNode(value1, value2) =>
                if value > value2      { FourNode(value1, value2, value, None) }
                else if value < value1 { FourNode(value, value1, value2, None) }
                else                   { FourNode(value1, value, value2, None) },
            _ => fail!(""),
        }
    }

    /// Convert a Split into a TwoNode with the middle value as the value of the new parent node
    fn to_two_node(self) -> Node<V> {
        match self {
            FourNode(v1, v2, v3, None) => TwoNode(v2, box LeafTwoNode(v1), box LeafTwoNode(v3)),
            FourNode(v1, v2, v3, Some((n1, n2, n3, n4))) => TwoNode(v2, box TwoNode(v1, n1, n2), box TwoNode(v3, n3, n4)),
        }
    }
}

/// InsertResult
enum InsertResult<V: ToString+Ord> {
    Fit(Node<V>),  // box this node?
    Split(FourNode<V>),  // split should always contain a ThreeNode/LeafThreeNode. box this?
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Node
enum Node<V: ToString+Ord> {
    LeafTwoNode(V),
    LeafThreeNode(V, V),
    TwoNode(V, Box<Node<V>>, Box<Node<V>>),
    ThreeNode(V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
}

impl <V: ToString+Ord> ToString for Node<V> {
    fn to_string(&self) -> String {
        match *self {
            LeafTwoNode(ref v) => format!("LeafTwoNode({:s})", v.to_string()),
            LeafThreeNode(ref v1, ref v2) => format!("LeafThreeNode({:s}, {:s})", v1.to_string(), v2.to_string()),
            TwoNode(ref v, ref left, ref middle) => format!("TwoNode({:s}, {:s}, {:s})", v.to_string(), left.to_string(), middle.to_string()),
            ThreeNode(_, _, ref left, ref middle, ref right) => format!("ThreeNode({:s}, {:s}, {:s})", left.to_string(), middle.to_string(), right.to_string()),
        }
    }
}

impl <V: ToString+Ord> Node<V> {
    // PRIVATE
    /// Extend this TwoNode with the provided value and child node to make it a ThreeNode
    fn extend(self, other_value: V, other_node: Box<Node<V>>) -> Node<V> {
        match self {
            TwoNode(self_value, self_left, self_middle) => {
                if self_value > other_value {
                    ThreeNode(other_value, self_value, other_node, self_left, self_middle)
                } else {
                    ThreeNode(self_value, other_value, self_left, self_middle, other_node)
                }
            }
            _ => fail!(""),
        }
    }

    fn extend4(self, other_value: V, other_node: Box<Node<V>>) -> FourNode<V> {
        match self {
            ThreeNode(self_value1, self_value2, self_left, self_middle, self_right) => {
                if other_value < self_value1 {
                    FourNode(other_value, self_value1, self_value2, Some((other_node, self_left, self_middle, self_right)))
                } else {
                    FourNode(self_value1, self_value2, other_value, Some((self_left, self_middle, self_right, other_node)))
                }
            }
            _ => fail!(""),
        }
    }

    fn next_direction(&self, to_insert: &V) -> Direction {
        match *self {
            TwoNode(ref value, _, _) =>
                if to_insert < value { Left }
                else                 { Middle },
            ThreeNode(ref value1, ref value2, _, _, _) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &TwoNode(ref v, _, _) |
                &LeafTwoNode(ref v) if to_check == v => true,

            &ThreeNode(ref v1, ref v2, _, _, _) |
                &LeafThreeNode(ref v1, ref v2) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            LeafTwoNode(value) => {
                if to_insert > value { Fit(LeafThreeNode(value, to_insert)) }
                else                 { Fit(LeafThreeNode(to_insert, value)) }
            },

            // Split if leaf ThreeNode
            node @ LeafThreeNode(..) => Split(FourNode::new(node, to_insert)),

            // Recurse down if internal Node and handle results
            TwoNode(value, box left, box middle) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => fail!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left => TwoNode(value, box returned_node, box other_node),
                            Middle => TwoNode(value, box other_node, box returned_node),
                            _ => fail!(""),
                        },
                    Split(four_node) => four_node.to_two_node().extend(value, box other_node),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            ThreeNode(value1, value2, left, middle, right) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => fail!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let new_node = match next_direction {
                            Left => ThreeNode(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => ThreeNode(value1, value2, other_node1, box returned_node, other_node2),
                            Right => ThreeNode(value1, value2, other_node1, other_node2, box returned_node),
                            _ => fail!(""),
                        };
                        Fit(new_node)
                    },
                    Split(four_node) => {
                        let new_node: FourNode<V> = match next_direction {
                            Left => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Middle => four_node.to_two_node().extend(value1, other_node1).extend4(value2, other_node2),
                            Right => four_node.to_two_node().extend(value2, other_node2).extend4(value1, other_node1),
                            _ => fail!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: ToString+Ord> {
    root: Option<Node<V>>,
}

impl <V: ToString+Ord> ToString for TTTree<V> {
    fn to_string(&self) -> String {
        match self.root {
            Some(ref node) => node.to_string(),
            None => "TTTree(<empty>)".to_string(),
        }
    }
}

impl <V: ToString+Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => LeafTwoNode(value),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(node @ FourNode(..)) => node.to_two_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}

// TODO:
// Collection trait
// convert this to Key/Value K/V
// remove ToString debugging stuffs

#[test]
fn it_works() {
    let mut tree: TTTree<uint> = TTTree::new();

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(50);
    match tree {
        TTTree{root: Some(LeafTwoNode(50))} => (),
        _ => fail!(),
    }

    tree.insert(60);
    match tree {
        TTTree{root: Some(LeafThreeNode(50, 60))} => (),
        _ => fail!(),
    }

    tree.insert(70);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafTwoNode(70)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(100);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafTwoNode(50),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(55);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box LeafThreeNode(50, 55),
                box LeafThreeNode(70, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(68);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafTwoNode(100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(75);
    match tree {
        TTTree{root: Some(
            ThreeNode(60, 70,
                box LeafThreeNode(50, 55),
                box LeafTwoNode(68),
                box LeafThreeNode(75, 100)
            )
        )} => (),
        _ => fail!(),
    }

    tree.insert(52);
    match tree {
        TTTree{root: Some(
            TwoNode(60,
                box TwoNode(52,
                    box LeafTwoNode(50),
                    box LeafTwoNode(55),
                ),
                box TwoNode(70,
                    box LeafTwoNode(68),
                    box LeafThreeNode(75, 100),
                ),
            )
        )} => (),
        _ => fail!(),
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate serialize;

use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream};
use std::vec::Vec;
use conn::{Conn, Connection};
use data::{Config, IrcReader, IrcWriter, Message};

pub mod conn;
pub mod data;

pub struct Bot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub conn: RefCell<Connection<T, U>>,
    pub config: Config,
    process: RefCell<|&Bot<T, U>, &str, &str, &[&str]|:'a -> IoResult<()>>,
    pub chanlists: HashMap<String, Vec<String>>,
}

impl<'a, T, U> Bot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub fn new(process: |&Bot<BufferedWriter<TcpStream>, TcpStream>, &str, &str, &[&str]|:'a -> IoResult<()>) -> IoResult<Bot<'a, BufferedWriter<TcpStream>, TcpStream>> {
        let config = try!(Config::load());
        let conn = try!(Connection::connect(config.server.as_slice(), config.port));
        Ok(Bot {
            conn: RefCell::new(conn),
            config: config,
            process: RefCell::new(process),
            chanlists: HashMap::new(),
        })
    }

    pub fn send_nick(&self, nick: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "NICK", [nick]))
    }

    pub fn send_user(&self, username: &str, real_name: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "USER", [username, "0", "*", real_name]))
    }

    pub fn send_join(&self, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "JOIN", [chan.as_slice()]))
    }

    pub fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "MODE", [chan.as_slice(), mode.as_slice()]))
    }

    pub fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "TOPIC", [chan.as_slice(), topic.as_slice()]))
    }

    pub fn send_invite(&self, person: &str, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "INVITE", [person.as_slice(), chan.as_slice()]))
    }

    pub fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PRIVMSG", [chan.as_slice(), msg.as_slice()]))
    }

    pub fn identify(&self) -> IoResult<()> {
        try!(self.send_nick(self.config.nickname.as_slice()));
        self.send_user(self.config.username.as_slice(), self.config.realname.as_slice())
    }

    pub fn output(&mut self) -> IoResult<()> {
        let mut reader = match self.conn.borrow_mut().deref_mut() {
            &Conn(_, ref recv) => BufferedReader::new(recv.clone()),
        };
        for line in reader.lines() {
            match line {
                Ok(ln) => {
                    let (source, command, args) = try!(process(ln.as_slice()));
                    try!(self.handle_command(source, command, args.as_slice()));
                    println!("{}", ln)
                },
                Err(e) => println!("Shit, you're fucked! {}", e),
            }
        }
        Ok(())
    }

    fn handle_command(&mut self, source: &str, command: &str, args: &[&str]) -> IoResult<()> {
        match (command, args) {
            ("PING", [msg]) => {
                try!(Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PONG", [msg])));
            },
            ("376", _) => { // End of MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("422", _) => { // Missing MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("353", [_, _, chan, users]) => { // /NAMES
                for user in users.split_str(" ") {
                    if !match self.chanlists.find_mut(&String::from_str(chan)) {
                        Some(vec) => {
                            vec.push(String::from_str(user));
                            true
                        },
                        None => false,
                    } {
                        self.chanlists.insert(String::from_str(chan), vec!(String::from_str(user)));
                    }
                }
            },
            ("JOIN", [chan]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => vec.push(String::from_str(source.slice_to(i))),
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            ("PART", [chan, _]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => {
                                match vec.as_slice().position_elem(&String::from_str(source.slice_to(i))) {
                                    Some(n) => {
                                        vec.swap_remove(n);
                                    },
                                    None => (),
                                };
                            },
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            _ => {
                try!((*self.process.borrow_mut().deref_mut())(self, source, command, args));
            },
        };
        Ok(())
    }
}

fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> {
    let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)");
    let cap = match reg.captures(msg) {
        Some(x) => x,
        None => return Err(IoError {
            kind: InvalidInput,
            desc: "Failed to parse line",
            detail: None,
        }),
    };
    let source = cap.at(1);
    let command = cap.at(2);
    let args = parse_args(cap.at(3));
    Ok((source, command, args))
}

fn parse_args(line: &str) -> Vec<&str> {
    let reg = regex!(r" ([^: ]+)| :([^\r\n]*)[\r\n]*$");
    reg.captures_iter(line).map(|cap| {
        match cap.at(1) {
            "" => cap.at(2),
            x => x,
        }
    }).collect()
}

#[test]
fn process_line_test() {
    let res = process(":flare.to.ca.fyrechat.net 353 pickles = #pickles :pickles awe\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "flare.to.ca.fyrechat.net");
    assert_eq!(command, "353");
    assert_eq!(args, vec!["pickles", "=", "#pickles", "pickles awe"]);

    let res = process("PING :flare.to.ca.fyrechat.net\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "");
    assert_eq!(command, "PING");
    assert_eq!(args, vec!["flare.to.ca.fyrechat.net"]);
}

#[test]
fn process_args_test() {
    let res = parse_args("PRIVMSG #vana :hi");
    assert_eq!(res, vec!["#vana", "hi"])
}
<commit_msg>Refactored Bot into IrcBot based on Bot trait.<commit_after>#![feature(phase)]
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
extern crate serialize;

use std::cell::RefCell;
use std::collections::HashMap;
use std::io::{BufferedReader, BufferedWriter, InvalidInput, IoError, IoResult, TcpStream};
use std::vec::Vec;
use conn::{Conn, Connection};
use data::{Config, IrcReader, IrcWriter, Message};

pub mod conn;
pub mod data;

pub trait Bot<'a> {
    fn send_nick(&self, nick: &str) -> IoResult<()>;
    fn send_user(&self, username: &str, real_name: &str) -> IoResult<()>;
    fn send_join(&self, chan: &str) -> IoResult<()>;
    fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()>;
    fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()>;
    fn send_invite(&self, person: &str, chan: &str) -> IoResult<()>;
    fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()>;
    fn identify(&self) -> IoResult<()>;
    fn output(&mut self) -> IoResult<()>;
}

pub struct IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub conn: RefCell<Connection<T, U>>,
    pub config: Config,
    process: RefCell<|&IrcBot<T, U>, &str, &str, &[&str]|:'a -> IoResult<()>>,
    pub chanlists: HashMap<String, Vec<String>>,
}

impl<'a, T, U> IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    pub fn new(process: |&IrcBot<BufferedWriter<TcpStream>, TcpStream>, &str, &str, &[&str]|:'a -> IoResult<()>) -> IoResult<IrcBot<'a, BufferedWriter<TcpStream>, TcpStream>> {
        let config = try!(Config::load());
        let conn = try!(Connection::connect(config.server.as_slice(), config.port));
        Ok(IrcBot {
            conn: RefCell::new(conn),
            config: config,
            process: RefCell::new(process),
            chanlists: HashMap::new(),
        })
    }

    fn handle_command(&mut self, source: &str, command: &str, args: &[&str]) -> IoResult<()> {
        match (command, args) {
            ("PING", [msg]) => {
                try!(Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PONG", [msg])));
            },
            ("376", _) => { // End of MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("422", _) => { // Missing MOTD
                for chan in self.config.channels.iter() {
                    try!(self.send_join(chan.as_slice()));
                }
            },
            ("353", [_, _, chan, users]) => { // /NAMES
                for user in users.split_str(" ") {
                    if !match self.chanlists.find_mut(&String::from_str(chan)) {
                        Some(vec) => {
                            vec.push(String::from_str(user));
                            true
                        },
                        None => false,
                    } {
                        self.chanlists.insert(String::from_str(chan), vec!(String::from_str(user)));
                    }
                }
            },
            ("JOIN", [chan]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => vec.push(String::from_str(source.slice_to(i))),
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            ("PART", [chan, _]) => {
                match self.chanlists.find_mut(&String::from_str(chan)) {
                    Some(vec) => {
                        match source.find('!') {
                            Some(i) => {
                                match vec.as_slice().position_elem(&String::from_str(source.slice_to(i))) {
                                    Some(n) => {
                                        vec.swap_remove(n);
                                    },
                                    None => (),
                                };
                            },
                            None => (),
                        };
                    },
                    None => (),
                }
            },
            _ => {
                try!((*self.process.borrow_mut().deref_mut())(self, source, command, args));
            },
        };
        Ok(())
    }
}

impl<'a, T, U> Bot<'a> for IrcBot<'a, T, U> where T: IrcWriter, U: IrcReader {
    fn send_nick(&self, nick: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "NICK", [nick]))
    }

    fn send_user(&self, username: &str, real_name: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "USER", [username, "0", "*", real_name]))
    }

    fn send_join(&self, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "JOIN", [chan.as_slice()]))
    }

    fn send_mode(&self, chan: &str, mode: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "MODE", [chan.as_slice(), mode.as_slice()]))
    }

    fn send_topic(&self, chan: &str, topic: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "TOPIC", [chan.as_slice(), topic.as_slice()]))
    }

    fn send_invite(&self, person: &str, chan: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "INVITE", [person.as_slice(), chan.as_slice()]))
    }

    fn send_privmsg(&self, chan: &str, msg: &str) -> IoResult<()> {
        Connection::send(self.conn.borrow_mut().deref_mut(), Message::new(None, "PRIVMSG", [chan.as_slice(), msg.as_slice()]))
    }

    fn identify(&self) -> IoResult<()> {
        try!(self.send_nick(self.config.nickname.as_slice()));
        self.send_user(self.config.username.as_slice(), self.config.realname.as_slice())
    }

    fn output(&mut self) -> IoResult<()> {
        let mut reader = match self.conn.borrow_mut().deref_mut() {
            &Conn(_, ref recv) => BufferedReader::new(recv.clone()),
        };
        for line in reader.lines() {
            match line {
                Ok(ln) => {
                    let (source, command, args) = try!(process(ln.as_slice()));
                    try!(self.handle_command(source, command, args.as_slice()));
                    println!("{}", ln)
                },
                Err(e) => println!("Shit, you're fucked! {}", e),
            }
        }
        Ok(())
    }
}

fn process(msg: &str) -> IoResult<(&str, &str, Vec<&str>)> {
    let reg = regex!(r"^(?::([^ ]+) )?([^ ]+)(.*)");
    let cap = match reg.captures(msg) {
        Some(x) => x,
        None => return Err(IoError {
            kind: InvalidInput,
            desc: "Failed to parse line",
            detail: None,
        }),
    };
    let source = cap.at(1);
    let command = cap.at(2);
    let args = parse_args(cap.at(3));
    Ok((source, command, args))
}

fn parse_args(line: &str) -> Vec<&str> {
    let reg = regex!(r" ([^: ]+)| :([^\r\n]*)[\r\n]*$");
    reg.captures_iter(line).map(|cap| {
        match cap.at(1) {
            "" => cap.at(2),
            x => x,
        }
    }).collect()
}

#[test]
fn process_line_test() {
    let res = process(":flare.to.ca.fyrechat.net 353 pickles = #pickles :pickles awe\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "flare.to.ca.fyrechat.net");
    assert_eq!(command, "353");
    assert_eq!(args, vec!["pickles", "=", "#pickles", "pickles awe"]);

    let res = process("PING :flare.to.ca.fyrechat.net\r\n").unwrap();
    let (source, command, args) = res;
    assert_eq!(source, "");
    assert_eq!(command, "PING");
    assert_eq!(args, vec!["flare.to.ca.fyrechat.net"]);
}

#[test]
fn process_args_test() {
    let res = parse_args("PRIVMSG #vana :hi");
    assert_eq!(res, vec!["#vana", "hi"])
}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://urschrei.github.io/polyline-ffi/")]
//! This module exposes functions for accessing the Polyline encoding and decoding functions via FFI
extern crate polyline;
use polyline::{encode_coordinates, decode_polyline};
use std::mem;
use std::slice;
use std::f64;
use std::ffi::{CStr, CString};

extern crate libc;
use self::libc::{c_char, c_void, uint32_t, size_t};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: size_t,
}

// Build an Array from &[[f64; 2]], so it can be leaked across the FFI boundary
impl From<Vec<[f64; 2]>> for Array {
    fn from(sl: Vec<[f64; 2]>) -> Self {
        let array = Array {
            data: sl.as_ptr() as *const c_void,
            len: sl.len() as size_t,
        };
        mem::forget(sl);
        array
    }
}

// Build &[[f64; 2]] from an Array, so it can be dropped
impl From<Array> for Vec<[f64; 2]> {
    fn from(arr: Array) -> Self {
        unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
    }
}

// Decode a Polyline into an Array
fn arr_from_string(incoming: String, precision: uint32_t) -> Array {
    let result: Array = match decode_polyline(incoming, precision) {
        Ok(res) => res.into(),
        // should be easy to check for
        Err(_) => vec![[f64::NAN, f64::NAN]].into(),
    };
    result.into()
}

// Decode an Array into a Polyline
fn string_from_arr(incoming: Array, precision: uint32_t) -> String {
    let inc: Vec<_> = incoming.into();
    match encode_coordinates(&inc, precision) {
        Ok(res) => res,
        // we don't need to adapt the error
        Err(res) => res,
    }
}

/// Convert a Polyline into an array of coordinates
///
/// Callers must pass two arguments:
///
/// - a pointer to `NUL`-terminated characters (`char*`)
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will always return an array: `[[NaN, NaN]]`
///
/// Implementations calling this function **must** call [`drop_float_array`](fn.drop_float_array.html)
/// with the returned [Array](struct.Array.html), in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn decode_polyline_ffi(pl: *const c_char, precision: uint32_t) -> Array {
    let s: String = unsafe { CStr::from_ptr(pl).to_string_lossy().into_owned() };
    arr_from_string(s, precision)
}

/// Convert an array of coordinates into a Polyline
///
/// Callers must pass two arguments:
///
/// - a [Struct](struct.Array.html) with two fields:
///     - `data`, a void pointer to an array of floating-point lat, lon coordinates: `[[1.0, 2.0]]`
///     - `len`, the length of the array being passed. Its type must be `size_t`: `1`
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will always return a string: "Couldn't decode Polyline"
///
/// Implementations calling this function **must** call [`drop_cstring`](fn.drop_cstring.html)
/// with the returned `c_char` pointer, in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn encode_coordinates_ffi(coords: Array, precision: uint32_t) -> *mut c_char {
    let s: String = string_from_arr(coords, precision);
    match CString::new(s) {
        Ok(res) => res.into_raw(),
        // It's arguably better to fail noisily, but this is robust
        Err(_) => CString::new("Couldn't decode Polyline".to_string()).unwrap().into_raw(),
    }
}

/// Free Array memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(arr: Array) {
    if arr.data.is_null() {
        return;
    }
    let _: Vec<_> = arr.into();
}

/// Free `CString` memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_cstring(p: *mut c_char) {
    let _ = unsafe { CString::from_raw(p) };
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::ptr;
    use std::ffi::{CString, CStr};

    #[test]
    fn test_array_conversion() {
        let original = vec![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
        // move into an Array, and leak it
        let arr: Array = original.into();
        // move back into a Vec -- leaked value still needs to be dropped
        let converted: Vec<_> = arr.into();
        assert_eq!(&converted, &[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]);
        // drop it
        drop_float_array(converted.into());
    }

    #[test]
    fn test_drop_empty_float_array() {
        let original = vec![[1.0, 2.0], [3.0, 4.0]];
        // move into an Array, and leak it
        let mut arr: Array = original.into();
        // zero Array contents
        arr.data = ptr::null();
        drop_float_array(arr);
    }

    #[test]
    fn test_coordinate_conversion() {
        let input = vec![[1.0, 2.0], [3.0, 4.0]];
        let output = "_ibE_seK_seK_seK";
        let input_arr: Array = input.into();
        let transformed: String = super::string_from_arr(input_arr, 5);
        assert_eq!(transformed, output);
    }

    #[test]
    fn test_string_conversion() {
        let input = "_ibE_seK_seK_seK".to_string();
        let output = [[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        assert_eq!(&transformed_arr, &output);
    }

    #[test]
    #[should_panic]
    fn test_bad_string_conversion() {
        let input = "_p~iF~ps|U_u🗑lLnnqC_mqNvxq`@".to_string();
        let output = vec![[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        // this will fail, bc transformed_arr is [[NaN, NaN]]
        assert_eq!(transformed_arr, output.as_slice());
    }

    #[test]
    fn test_ffi_polyline_decoding() {
        let input = CString::new("_ibE_seK_seK_seK").unwrap().as_ptr();
        let result: Vec<_> = decode_polyline_ffi(input, 5).into();
        assert_eq!(&result, &[[1.0, 2.0], [3.0, 4.0]]);
        drop_float_array(result.into());
    }

    #[test]
    fn test_ffi_coordinate_encoding() {
        let input: Array = vec![[1.0, 2.0], [3.0, 4.0]].into();
        let output = "_ibE_seK_seK_seK".to_string();
        let pl = encode_coordinates_ffi(input, 5);
        // Allocate a new String
        let result = unsafe { CStr::from_ptr(pl).to_str().unwrap() };
        assert_eq!(&result, &output);
        // Drop received FFI data
        drop_cstring(pl);
    }
}
<commit_msg>Doc fixes<commit_after>#![doc(html_root_url = "https://urschrei.github.io/polyline-ffi/")]
//! This module exposes functions for accessing the Polyline encoding and decoding functions via FFI
extern crate polyline;
use polyline::{encode_coordinates, decode_polyline};
use std::mem;
use std::slice;
use std::f64;
use std::ffi::{CStr, CString};

extern crate libc;
use self::libc::{c_char, c_void, uint32_t, size_t};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: size_t,
}

// Build an Array from &[[f64; 2]], so it can be leaked across the FFI boundary
impl From<Vec<[f64; 2]>> for Array {
    fn from(sl: Vec<[f64; 2]>) -> Self {
        let array = Array {
            data: sl.as_ptr() as *const c_void,
            len: sl.len() as size_t,
        };
        mem::forget(sl);
        array
    }
}

// Build &[[f64; 2]] from an Array, so it can be dropped
impl From<Array> for Vec<[f64; 2]> {
    fn from(arr: Array) -> Self {
        unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
    }
}

// Decode a Polyline into an Array
fn arr_from_string(incoming: String, precision: uint32_t) -> Array {
    let result: Array = match decode_polyline(incoming, precision) {
        Ok(res) => res.into(),
        // should be easy to check for
        Err(_) => vec![[f64::NAN, f64::NAN]].into(),
    };
    result.into()
}

// Decode an Array into a Polyline
fn string_from_arr(incoming: Array, precision: uint32_t) -> String {
    let inc: Vec<_> = incoming.into();
    match encode_coordinates(&inc, precision) {
        Ok(res) => res,
        // we don't need to adapt the error
        Err(res) => res,
    }
}

/// Convert a Polyline into an array of coordinates
///
/// Callers must pass two arguments:
///
/// - a pointer to `NUL`-terminated characters (`char*`)
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will return an [Array](struct.Array.html) whose `data` field is `[[NaN, NaN]]`, and whose `len` field is `1`.
///
/// Implementations calling this function **must** call [`drop_float_array`](fn.drop_float_array.html)
/// with the returned [Array](struct.Array.html), in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn decode_polyline_ffi(pl: *const c_char, precision: uint32_t) -> Array {
    let s: String = unsafe { CStr::from_ptr(pl).to_string_lossy().into_owned() };
    arr_from_string(s, precision)
}

/// Convert an array of coordinates into a Polyline
///
/// Callers must pass two arguments:
///
/// - a [Struct](struct.Array.html) with two fields:
///     - `data`, a void pointer to an array of floating-point lat, lon coordinates: `[[1.0, 2.0]]`
///     - `len`, the length of the array being passed. Its type must be `size_t`: `1`
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will return one of the following:
///
/// - a `char*` beginning with "Longitude error:" if invalid longitudes are passed
/// - a `char*` beginning with "Latitude error:" if invalid latitudes are passed
///
/// Implementations calling this function **must** call [`drop_cstring`](fn.drop_cstring.html)
/// with the returned `c_char` pointer, in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn encode_coordinates_ffi(coords: Array, precision: uint32_t) -> *mut c_char {
    let s: String = string_from_arr(coords, precision);
    match CString::new(s) {
        Ok(res) => res.into_raw(),
        // It's arguably better to fail noisily, but this is robust
        Err(_) => CString::new("Couldn't decode Polyline".to_string()).unwrap().into_raw(),
    }
}

/// Free Array memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(arr: Array) {
    if arr.data.is_null() {
        return;
    }
    let _: Vec<_> = arr.into();
}

/// Free `CString` memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_cstring(p: *mut c_char) {
    let _ = unsafe { CString::from_raw(p) };
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::ptr;
    use std::ffi::{CString, CStr};

    #[test]
    fn test_array_conversion() {
        let original = vec![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
        // move into an Array, and leak it
        let arr: Array = original.into();
        // move back into a Vec -- leaked value still needs to be dropped
        let converted: Vec<_> = arr.into();
        assert_eq!(&converted, &[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]);
        // drop it
        drop_float_array(converted.into());
    }

    #[test]
    fn test_drop_empty_float_array() {
        let original = vec![[1.0, 2.0], [3.0, 4.0]];
        // move into an Array, and leak it
        let mut arr: Array = original.into();
        // zero Array contents
        arr.data = ptr::null();
        drop_float_array(arr);
    }

    #[test]
    fn test_coordinate_conversion() {
        let input = vec![[1.0, 2.0], [3.0, 4.0]];
        let output = "_ibE_seK_seK_seK";
        let input_arr: Array = input.into();
        let transformed: String = super::string_from_arr(input_arr, 5);
        assert_eq!(transformed, output);
    }

    #[test]
    fn test_string_conversion() {
        let input = "_ibE_seK_seK_seK".to_string();
        let output = [[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        assert_eq!(&transformed_arr, &output);
    }

    #[test]
    #[should_panic]
    fn test_bad_string_conversion() {
        let input = "_p~iF~ps|U_u🗑lLnnqC_mqNvxq`@".to_string();
        let output = vec![[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        // this will fail, bc transformed_arr is [[NaN, NaN]]
        assert_eq!(transformed_arr, output.as_slice());
    }

    #[test]
    fn test_ffi_polyline_decoding() {
        let input = CString::new("_ibE_seK_seK_seK").unwrap().as_ptr();
        let result: Vec<_> = decode_polyline_ffi(input, 5).into();
        assert_eq!(&result, &[[1.0, 2.0], [3.0, 4.0]]);
        drop_float_array(result.into());
    }

    #[test]
    fn test_ffi_coordinate_encoding() {
        let input: Array = vec![[1.0, 2.0], [3.0, 4.0]].into();
        let output = "_ibE_seK_seK_seK".to_string();
        let pl = encode_coordinates_ffi(input, 5);
        // Allocate a new String
        let result = unsafe { CStr::from_ptr(pl).to_str().unwrap() };
        assert_eq!(&result, &output);
        // Drop received FFI data
        drop_cstring(pl);
    }
}
<|endoftext|>


<commit_before>//! Redis support for the `r2d2` connection pool.
#![doc(html_root_url="https://sorccu.github.io/r2d2-redis/doc")]
#![warn(missing_docs)]
extern crate r2d2;
extern crate redis;

use std::error;
use std::error::Error as _StdError;
use std::fmt;
use std::ops::Deref;

/// A unified enum of errors returned by redis::Client
#[derive(Debug)]
pub enum Error {
    /// A redis::RedisError
    Other(redis::RedisError),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}: {}", self.description(), self.cause().unwrap())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Other(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Other(ref err) => err.cause()
        }
    }
}

/// An `r2d2::ConnectionManager` for `redis::Client`s.
///
/// ## Example
///

/// ```
/// extern crate r2d2;
/// extern crate r2d2_redis;
/// extern crate redis;
///
/// use std::default::Default;
/// use std::ops::Deref;
/// use std::sync::Arc;
/// use std::thread;
/// use r2d2_redis::RedisConnectionManager;
///
/// fn main() {
///     let config = Default::default();
///     let manager = RedisConnectionManager::new("redis://localhost").unwrap();
///     let pool = Arc::new(r2d2::Pool::new(config, manager).unwrap());
///
///     let mut handles = vec![];
///
///     for _i in 0..10i32 {
///         let pool = pool.clone();
///         handles.push(thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             let reply = redis::cmd("PING").query::<String>(conn.deref()).unwrap();
///             assert_eq!("PONG", reply);
///         }));
///     }
///
///     for h in handles {
///         h.join().unwrap();
///     }
/// }
/// ```
#[derive(Debug)]
pub struct RedisConnectionManager {
    connection_info: redis::ConnectionInfo
}

impl RedisConnectionManager {
    /// Creates a new `RedisConnectionManager`.
    ///
    /// See `redis::Client::open` for a description of the parameter
    /// types.
    pub fn new<T: redis::IntoConnectionInfo>(params: T)
            -> Result<RedisConnectionManager, redis::RedisError> {
        match params.into_connection_info() {
            Ok(connection_info) => Ok(RedisConnectionManager {
                connection_info: connection_info
            }),
            Err(err) => Err(err)
        }
    }
}

impl r2d2::ManageConnection for RedisConnectionManager {
    type Connection = redis::Connection;
    type Error = Error;

    fn connect(&self) -> Result<redis::Connection, Error> {
        match redis::Client::open(self.connection_info.clone()) {
            Ok(client) => {
                client.get_connection().map_err(Error::Other)
            },
            Err(err) => Err(Error::Other(err))
        }
    }

    fn is_valid(&self, conn: &mut redis::Connection) -> Result<(), Error> {
        match redis::cmd("PING").query(conn.deref()) {
            Ok(v) => Ok(v),
            Err(err) => Err(Error::Other(err))
        }
    }

    fn has_broken(&self, _conn: &mut redis::Connection) -> bool {
        false
    }
}
<commit_msg>Simplify a few snippets without changing functionality.<commit_after>//! Redis support for the `r2d2` connection pool.
#![doc(html_root_url="https://sorccu.github.io/r2d2-redis/doc")]
#![warn(missing_docs)]
extern crate r2d2;
extern crate redis;

use std::error;
use std::error::Error as _StdError;
use std::fmt;

/// A unified enum of errors returned by redis::Client
#[derive(Debug)]
pub enum Error {
    /// A redis::RedisError
    Other(redis::RedisError),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}: {}", self.description(), self.cause().unwrap())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Other(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Other(ref err) => err.cause()
        }
    }
}

/// An `r2d2::ConnectionManager` for `redis::Client`s.
///
/// ## Example
///

/// ```
/// extern crate r2d2;
/// extern crate r2d2_redis;
/// extern crate redis;
///
/// use std::default::Default;
/// use std::ops::Deref;
/// use std::sync::Arc;
/// use std::thread;
/// use r2d2_redis::RedisConnectionManager;
///
/// fn main() {
///     let config = Default::default();
///     let manager = RedisConnectionManager::new("redis://localhost").unwrap();
///     let pool = Arc::new(r2d2::Pool::new(config, manager).unwrap());
///
///     let mut handles = vec![];
///
///     for _i in 0..10i32 {
///         let pool = pool.clone();
///         handles.push(thread::spawn(move || {
///             let conn = pool.get().unwrap();
///             let reply = redis::cmd("PING").query::<String>(conn.deref()).unwrap();
///             assert_eq!("PONG", reply);
///         }));
///     }
///
///     for h in handles {
///         h.join().unwrap();
///     }
/// }
/// ```
#[derive(Debug)]
pub struct RedisConnectionManager {
    connection_info: redis::ConnectionInfo
}

impl RedisConnectionManager {
    /// Creates a new `RedisConnectionManager`.
    ///
    /// See `redis::Client::open` for a description of the parameter
    /// types.
    pub fn new<T: redis::IntoConnectionInfo>(params: T)
            -> Result<RedisConnectionManager, redis::RedisError> {
        Ok(RedisConnectionManager {
            connection_info: try!(params.into_connection_info()),
        })
    }
}

impl r2d2::ManageConnection for RedisConnectionManager {
    type Connection = redis::Connection;
    type Error = Error;

    fn connect(&self) -> Result<redis::Connection, Error> {
        match redis::Client::open(self.connection_info.clone()) {
            Ok(client) => {
                client.get_connection().map_err(Error::Other)
            },
            Err(err) => Err(Error::Other(err))
        }
    }

    fn is_valid(&self, conn: &mut redis::Connection) -> Result<(), Error> {
        redis::cmd("PING").query(conn).map_err(Error::Other)
    }

    fn has_broken(&self, _conn: &mut redis::Connection) -> bool {
        false
    }
}
<|endoftext|>


<commit_before>extern crate iron;

use std::collections::HashMap;
use iron::{Handler, IronResult, Request, Response};

pub struct Vhosts {
    default: Box<Handler>,
    vhosts: HashMap<&'static str, Box<Handler>>,
}

impl Vhosts {

    pub fn new<H: Handler>(h: H) -> Vhosts {
        Vhosts {
            default: Box::new(h) as Box<Handler>,
            vhosts: HashMap::new()
        }
    }

    /// For adding a handler for a host
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// extern crate iron;
    /// extern crate iron_vhosts;
    ///
    /// use iron::prelude::*;
    /// use iron::status;
    /// use iron_vhosts::Vhosts;
    ///
    /// fn main () {
    ///     //Default handler passed to new
    ///     let mut vhosts = Vhosts::new(|_: &mut Request| Ok(Response::with((status::Ok, "vhost"))));
    ///
    ///     //Add any host specific handlers
    ///     vhosts.add_host("localhost", localhost_handler);
    ///     vhosts.add_host("media.localhost", media_handler);
    ///
    ///     fn localhost_handler(_: &mut Request) -> IronResult<Response> {
    ///         Ok(Response::with((status::Ok, "localhost")))
    ///     }
    ///
    ///     fn media_handler(_: &mut Request) -> IronResult<Response> {
    ///         Ok(Response::with((status::Ok, "media")))
    ///     }
    ///
    ///     Iron::new(vhosts).http("localhost:3000").unwrap();
    /// }
    /// ```
    pub fn add_host<H: Handler>(&mut self, host: &'static str, h: H) -> Option<Box<Handler>> {
        self.vhosts.insert(host, Box::new(h))
    }

}

impl Handler for Vhosts {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        //get the host from the request
        let host = {
            let host = req.url.host();
            format!("{}", host)
        };

        //get the handler associated to the host
        let handler = match self.vhosts.get(host.as_str()){
            Some(box_handler) => box_handler,
            None              => &self.default
        };

        //fire off the handler
        handler.handle(req)
    }
}

#[test]
fn it_works() {
}
<commit_msg>change state hashmap key from &'static str to String: allows dynamic setups<commit_after>extern crate iron;

use std::collections::HashMap;
use iron::{Handler, IronResult, Request, Response};

pub struct Vhosts {
    default: Box<Handler>,
    vhosts: HashMap<String, Box<Handler>>,
}

impl Vhosts {

    pub fn new<H: Handler>(h: H) -> Vhosts {
        Vhosts {
            default: Box::new(h) as Box<Handler>,
            vhosts: HashMap::new()
        }
    }

    /// For adding a handler for a host
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// extern crate iron;
    /// extern crate iron_vhosts;
    ///
    /// use iron::prelude::*;
    /// use iron::status;
    /// use iron_vhosts::Vhosts;
    ///
    /// fn main () {
    ///     //Default handler passed to new
    ///     let mut vhosts = Vhosts::new(|_: &mut Request| Ok(Response::with((status::Ok, "vhost"))));
    ///
    ///     //Add any host specific handlers
    ///     vhosts.add_host("localhost", localhost_handler);
    ///     vhosts.add_host("media.localhost", media_handler);
    ///
    ///     fn localhost_handler(_: &mut Request) -> IronResult<Response> {
    ///         Ok(Response::with((status::Ok, "localhost")))
    ///     }
    ///
    ///     fn media_handler(_: &mut Request) -> IronResult<Response> {
    ///         Ok(Response::with((status::Ok, "media")))
    ///     }
    ///
    ///     Iron::new(vhosts).http("localhost:3000").unwrap();
    /// }
    /// ```
    pub fn add_host<H: Handler, I:Into<String> >(&mut self, host: I, h: H) -> Option<Box<Handler>> {
        self.vhosts.insert(host.into(), Box::new(h))
    }

}

impl Handler for Vhosts {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        //get the host from the request
        let host = {
            let host = req.url.host();
            format!("{}", host)
        };

        //get the handler associated to the host
        let handler = match self.vhosts.get(host.as_str()){
            Some(box_handler) => box_handler,
            None              => &self.default
        };

        //fire off the handler
        handler.handle(req)
    }
}

#[test]
fn it_works() {
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

//! `sysinfo` is a crate used to get a system's information.
//!
//! Before any attempt to read the different structs' information, you need to update them to
//! get up-to-date information.
//!
//! # Examples
//!
//! ```
//! use sysinfo::{ProcessExt, SystemExt};
//!
//! let mut system = sysinfo::System::new_all();
//!
//! // First we update all information of our system struct.
//! system.refresh_all();
//!
//! // Now let's print every process' id and name:
//! for (pid, proc_) in system.get_processes() {
//!     println!("{}:{} => status: {:?}", pid, proc_.name(), proc_.status());
//! }
//!
//! // Then let's print the temperature of the different components:
//! for component in system.get_components() {
//!     println!("{:?}", component);
//! }
//!
//! // And then all disks' information:
//! for disk in system.get_disks() {
//!     println!("{:?}", disk);
//! }
//!
//! // And finally the RAM and SWAP information:
//! println!("total memory: {} KB", system.get_total_memory());
//! println!("used memory : {} KB", system.get_used_memory());
//! println!("total swap  : {} KB", system.get_total_swap());
//! println!("used swap   : {} KB", system.get_used_swap());
//!
//! // Display system information:
//! println!("System name:             {:?}", system.get_name());
//! println!("System kernel version:   {:?}", system.get_kernel_version());
//! println!("System OS version:       {:?}", system.get_os_version());
//! println!("System host name:        {:?}", system.get_host_name());
//! ```

#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
//#![deny(warnings)]
#![allow(unknown_lints)]
#![allow(clippy::upper_case_acronyms)]
#![allow(renamed_and_removed_lints)]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[cfg(feature = "debug")]
#[doc(hidden)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;

        #[cfg(test)]
        const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        const MIN_USERS: usize = 0;
    }
}

pub use common::{
    AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;
pub use utils::get_current_pid;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        if _new_limit < 0 {
            _new_limit = 0;
        }
        let max = sys::system::get_max_nb_fds();
        if _new_limit > max {
            _new_limit = max;
        }
        if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
            // If files are already open, to be sure that the number won't be bigger when those
            // files are closed, we subtract the current number of opened files to the new limit.
            let diff = max - **x;
            **x = _new_limit - diff;
            true
        } else {
            false
        }
    }
    #[cfg(all(not(target_os = "linux"), not(target_os = "android")))]
    {
        false
    }
}

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

    #[test]
    fn check_memory_usage() {
        let mut s = System::new();

        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.memory() == 0),
            false
        );
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        assert!(s.get_users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_all();
        assert!(s.get_users().is_empty());

        let s = System::new_all();
        assert!(s.get_users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        let users = s.get_users();
        assert!(users.len() >= MIN_USERS);

        for user in users {
            match user.get_name() {
                "root" => {
                    assert_eq!(*user.get_uid(), 0);
                    assert_eq!(*user.get_gid(), 0);
                }
                _ => {
                    assert!(*user.get_uid() > 0);
                    #[cfg(not(target_os = "windows"))]
                    assert!(*user.get_gid() > 0);
                }
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unknown systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s.get_name().expect("Failed to get system name").is_empty());

            assert!(!s
                .get_kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s
                .get_os_version()
                .expect("Failed to get os version")
                .is_empty());

            assert!(!s
                .get_long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unknown systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s
                .get_host_name()
                .expect("Failed to get host name")
                .is_empty());
        }
    }
}

// Used to check that System is Send and Sync.
#[cfg(doctest)]
doc_comment::doc_comment!(
    "
```
fn is_send<T: Send>() {}
is_send::<sysinfo::System>();
```

```
fn is_sync<T: Sync>() {}
is_sync::<sysinfo::System>();
```"
);
<commit_msg>src: lib: Add test for usage usage<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

//! `sysinfo` is a crate used to get a system's information.
//!
//! Before any attempt to read the different structs' information, you need to update them to
//! get up-to-date information.
//!
//! # Examples
//!
//! ```
//! use sysinfo::{ProcessExt, SystemExt};
//!
//! let mut system = sysinfo::System::new_all();
//!
//! // First we update all information of our system struct.
//! system.refresh_all();
//!
//! // Now let's print every process' id and name:
//! for (pid, proc_) in system.get_processes() {
//!     println!("{}:{} => status: {:?}", pid, proc_.name(), proc_.status());
//! }
//!
//! // Then let's print the temperature of the different components:
//! for component in system.get_components() {
//!     println!("{:?}", component);
//! }
//!
//! // And then all disks' information:
//! for disk in system.get_disks() {
//!     println!("{:?}", disk);
//! }
//!
//! // And finally the RAM and SWAP information:
//! println!("total memory: {} KB", system.get_total_memory());
//! println!("used memory : {} KB", system.get_used_memory());
//! println!("total swap  : {} KB", system.get_total_swap());
//! println!("used swap   : {} KB", system.get_used_swap());
//!
//! // Display system information:
//! println!("System name:             {:?}", system.get_name());
//! println!("System kernel version:   {:?}", system.get_kernel_version());
//! println!("System OS version:       {:?}", system.get_os_version());
//! println!("System host name:        {:?}", system.get_host_name());
//! ```

#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
//#![deny(warnings)]
#![allow(unknown_lints)]
#![allow(clippy::upper_case_acronyms)]
#![allow(renamed_and_removed_lints)]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[cfg(feature = "debug")]
#[doc(hidden)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;

        #[cfg(test)]
        const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        const MIN_USERS: usize = 0;
    }
}

pub use common::{
    AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;
pub use utils::get_current_pid;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        if _new_limit < 0 {
            _new_limit = 0;
        }
        let max = sys::system::get_max_nb_fds();
        if _new_limit > max {
            _new_limit = max;
        }
        if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
            // If files are already open, to be sure that the number won't be bigger when those
            // files are closed, we subtract the current number of opened files to the new limit.
            let diff = max - **x;
            **x = _new_limit - diff;
            true
        } else {
            false
        }
    }
    #[cfg(all(not(target_os = "linux"), not(target_os = "android")))]
    {
        false
    }
}

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

    #[test]
    fn check_memory_usage() {
        let mut s = System::new();

        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.memory() == 0),
            false
        );
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_cpu_usage() {
        let mut s = System::new();

        s.refresh_all();
        // All CPU usage will start at zero until the second refresh
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() == 0.0),
            true
        );

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                    && proc_.cpu_usage() <= (s.get_processors().len() as f32) * 100.0),
            true
        );
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        assert!(s.get_users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_all();
        assert!(s.get_users().is_empty());

        let s = System::new_all();
        assert!(s.get_users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        let users = s.get_users();
        assert!(users.len() >= MIN_USERS);

        for user in users {
            match user.get_name() {
                "root" => {
                    assert_eq!(*user.get_uid(), 0);
                    assert_eq!(*user.get_gid(), 0);
                }
                _ => {
                    assert!(*user.get_uid() > 0);
                    #[cfg(not(target_os = "windows"))]
                    assert!(*user.get_gid() > 0);
                }
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unknown systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s.get_name().expect("Failed to get system name").is_empty());

            assert!(!s
                .get_kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s
                .get_os_version()
                .expect("Failed to get os version")
                .is_empty());

            assert!(!s
                .get_long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unknown systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s
                .get_host_name()
                .expect("Failed to get host name")
                .is_empty());
        }
    }
}

// Used to check that System is Send and Sync.
#[cfg(doctest)]
doc_comment::doc_comment!(
    "
```
fn is_send<T: Send>() {}
is_send::<sysinfo::System>();
```

```
fn is_sync<T: Sync>() {}
is_sync::<sysinfo::System>();
```"
);
<|endoftext|>


<commit_before>extern crate getopts;
use getopts::{optopt,optflag,getopts,OptGroup,usage};
use std::os;

use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut printempty: bool = false;
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                for line in file.lines() {
                    let (a, b) = handle_line(line, &mut printempty, &mut linenum, options);
                    printempty = a;
                    linenum = b;
                }
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut printempty: bool = false;
    let mut linenum = 1u32;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line, &mut printempty, &mut linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn handle_line<'a>(
    line: IoResult<String>,
    printempty: &'a mut bool,
    linenum: &'a mut u32,
    options: &getopts::Matches) -> (bool, u32) {
    let linestr = line.unwrap();
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            *linenum = *print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        *linenum = *print_string(&linestr, linenum, options);
    }
    (*printempty, *linenum)
}

fn print_string<'a>(s: &String, linenum: &'a mut u32, options: &getopts::Matches) -> &'a mut u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            *linenum = *linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        *linenum = *linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: &'a mut u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if *b > 31 || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print!("^{}", (*b + 64) as char);
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        print!("^{}", (*b + 64) as char);
    }
}

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

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }
}
<commit_msg>Moving `cat_file` to its own method. Not sure about type sig syntax here...<commit_after>extern crate getopts;
use getopts::{optopt,optflag,getopts,OptGroup,usage};
use std::os;

use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                cat_file(file, options);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut printempty: bool = false;
    let mut linenum = 1u32;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line, &mut printempty, &mut linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file(mut file: old_io::BufferedReader<std::old_io::fs::File>, options: &getopts::Matches) {
    let mut printempty: bool = false;
    let mut linenum = 1u32;
    for line in file.lines() {
        let (a, b) = handle_line(line, &mut printempty, &mut linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn handle_line<'a>(
    line: IoResult<String>,
    printempty: &'a mut bool,
    linenum: &'a mut u32,
    options: &getopts::Matches) -> (bool, u32) {
    let linestr = line.unwrap();
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            *linenum = *print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        *linenum = *print_string(&linestr, linenum, options);
    }
    (*printempty, *linenum)
}

fn print_string<'a>(s: &String, linenum: &'a mut u32, options: &getopts::Matches) -> &'a mut u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            *linenum = *linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        *linenum = *linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: &'a mut u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if *b > 31 || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print!("^{}", (*b + 64) as char);
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        print!("^{}", (*b + 64) as char);
    }
}

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

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }
}
<|endoftext|>


<commit_before>//! # ODBC
//! Open Database Connectivity or short ODBC is a low level high performance interface
//! introduced by Microsoft to access relational data stores. This crate wraps the raw C interface
//! and is intended to be usable in safe and idiomatic Rust.
//!
//! [What is ODBC?](https://docs.microsoft.com/en-us/sql/odbc/reference/what-is-odbc)
//!
//! [ODBC Programmer's Reference]
//! (https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-programmer-s-reference)
//!
//! # Internal Desgin
//!
//! While designed as a relatively low level wrapper around ODBC this crate tries to prevent many
//! errors at compile time. The borrow checker and the RAII (Resource Acquisition Is
//! Initialization) idiom should prevent any occurence of `SQL_INVALID_HANDLE` in safe code.
//!
//! Using the type system and the borrow checker this crate ensures that each method call happens
//! in a valid state and state transitions are modeled in the type system. This should eliminate
//! the possibility of function sequence errors in safe code.
//!
//! [Basic ODBC Application Steps]
//! (https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/basic-odbc-application-steps)
//!
//! [ODBC State Transitions]
//! (https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/appendix-b-odbc-state-transition-tables)

#[macro_use]
extern crate log;
extern crate odbc_safe;

pub mod ffi;

pub use diagnostics::{DiagnosticRecord, GetDiagRec};
pub use result::Result;
pub use environment::*;
pub use connection::Connection;
pub use statement::*;

use odbc_object::OdbcObject;
use raii::Raii;
use result::{Return, into_result, try_into_option};
use odbc_safe as safe;

mod odbc_object;
mod raii;
mod diagnostics;
mod result;
mod environment;
mod connection;
mod statement;

/// Reflects the ability of a type to expose a valid handle
pub trait Handle {
    type To;
    /// Returns a valid handle to the odbc type.
    unsafe fn handle(&self) -> *mut Self::To;
}
<commit_msg>Update lib.rs<commit_after>//! # ODBC
//! Open Database Connectivity or short ODBC is a low level high performance interface
//! introduced by Microsoft to access relational data stores. This crate wraps the raw C interface
//! and is intended to be usable in safe and idiomatic Rust.
//!
//! [What is ODBC?](https://docs.microsoft.com/en-us/sql/odbc/reference/what-is-odbc)
//!
//! [ODBC Programmer's Reference]
//! (https://docs.microsoft.com/en-us/sql/odbc/reference/odbc-programmer-s-reference)
//!
//! # Internal Design
//!
//! While designed as a relatively low level wrapper around ODBC this crate tries to prevent many
//! errors at compile time. The borrow checker and the RAII (Resource Acquisition Is
//! Initialization) idiom should prevent any occurence of `SQL_INVALID_HANDLE` in safe code.
//!
//! Using the type system and the borrow checker this crate ensures that each method call happens
//! in a valid state and state transitions are modeled in the type system. This should eliminate
//! the possibility of function sequence errors in safe code.
//!
//! [Basic ODBC Application Steps]
//! (https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/basic-odbc-application-steps)
//!
//! [ODBC State Transitions]
//! (https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/appendix-b-odbc-state-transition-tables)

#[macro_use]
extern crate log;
extern crate odbc_safe;

pub mod ffi;

pub use diagnostics::{DiagnosticRecord, GetDiagRec};
pub use result::Result;
pub use environment::*;
pub use connection::Connection;
pub use statement::*;

use odbc_object::OdbcObject;
use raii::Raii;
use result::{Return, into_result, try_into_option};
use odbc_safe as safe;

mod odbc_object;
mod raii;
mod diagnostics;
mod result;
mod environment;
mod connection;
mod statement;

/// Reflects the ability of a type to expose a valid handle
pub trait Handle {
    type To;
    /// Returns a valid handle to the odbc type.
    unsafe fn handle(&self) -> *mut Self::To;
}
<|endoftext|>


<commit_before>#[crate_id = "github.com/lfairy/rose"];
#[license = "MIT"];
#[comment = "Super simple regular expression library"];

//!
//! ~~~
//! extern mod rose;
//!
//! let names = rose::compile(r"Bon Bon|Lyra");
//! match names.exec("Lyra Heartstrings") {
//!     Some(result) => println!("Found: {}", result.group(0)),
//!     None => fail!("Oh noes!")
//! }
//! ~~~
//!
//!
//! # A simple regular expression engine
//!
//! Rose is a library that executes regular expressions.  A subset of
//! PCRE notation is supported, excluding backreferences and lookaround
//! which cannot be implemented efficiently.
//!
//! To get started, prepare a pattern using [compile](fn.compile.html).
//! This creates a [Regex](struct.Regex.html) object, which can then be
//! run using its `exec` and `search` methods.
//!

#[feature(macro_rules)];

extern crate collections = "collections#0.10-pre";

pub mod compile;
pub mod parse;
pub mod vm;
mod charclass;

/// A compiled regular expression.  Use [compile](fn.compile.html) to
/// create one of these.
pub struct Regex {
    priv program: vm::Program
}

impl Regex {
    /// Create a `Regex` from a code block.
    pub fn from_program(program: vm::Program) -> Regex {
        Regex {
            program: program
        }
    }

    /// Check if the regex matches the given string.
    pub fn matches(&self, s: &str) -> bool {
        let mut vm = vm::VM::new(&self.program);
        for c in s.chars() {
            vm.feed(c);
            if vm.is_match() {
                return true;
            }
        }
        false
    }
}

/// Compile a regular expression.  Fails on invalid syntax.
pub fn compile(regex: &str) -> Regex {
    Regex::from_program(compile::compile(&parse::parse(regex)))
}
<commit_msg>Update lib.rs<commit_after>#[crate_id = "github.com/lfairy/rose"];
#[license = "MIT"];
#[comment = "Super simple regular expression library"];

//!
//! ~~~
//! extern crate rose;
//!
//! let names = rose::compile(r"Bon Bon|Lyra");
//! match names.exec("Lyra Heartstrings") {
//!     Some(result) => println!("Found: {}", result.group(0)),
//!     None => fail!("Oh noes!")
//! }
//! ~~~
//!
//!
//! # A simple regular expression engine
//!
//! Rose is a library that executes regular expressions.  A subset of
//! PCRE notation is supported, excluding backreferences and lookaround
//! which cannot be implemented efficiently.
//!
//! To get started, prepare a pattern using [compile](fn.compile.html).
//! This creates a [Regex](struct.Regex.html) object, which can then be
//! run using its `exec` and `search` methods.
//!

#[feature(macro_rules)];

extern crate collections = "collections#0.10-pre";

pub mod compile;
pub mod parse;
pub mod vm;
mod charclass;

/// A compiled regular expression.  Use [compile](fn.compile.html) to
/// create one of these.
pub struct Regex {
    priv program: vm::Program
}

impl Regex {
    /// Create a `Regex` from a code block.
    pub fn from_program(program: vm::Program) -> Regex {
        Regex {
            program: program
        }
    }

    /// Check if the regex matches the given string.
    pub fn matches(&self, s: &str) -> bool {
        let mut vm = vm::VM::new(&self.program);
        for c in s.chars() {
            vm.feed(c);
            if vm.is_match() {
                return true;
            }
        }
        false
    }
}

/// Compile a regular expression.  Fails on invalid syntax.
pub fn compile(regex: &str) -> Regex {
    Regex::from_program(compile::compile(&parse::parse(regex)))
}
<|endoftext|>