<commit_before>#![feature(mpsc_select)]
#![feature(scoped)]
extern crate time;
extern crate byteorder;
extern crate uuid;

use std::option::Option;
use std::cmp::Ordering;
use std::io::Write;
use std::io::Read;
use std::io;
use std::net::TcpStream;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::thread;
use std::thread::{JoinHandle, sleep_ms, Thread};
use std::sync::{Mutex, Condvar, Arc};
use std::sync::mpsc::channel;
use std::sync::mpsc::{Receiver, Sender, RecvError};

use byteorder::{BigEndian, WriteBytesExt};
use byteorder::ReadBytesExt;
use uuid::Uuid;

pub mod constants;
use constants::*;

#[test]
fn constructor() {
    let c = Connection::new("localhost", 4730);

    assert!(c.host == "localhost");
    assert!(c.port == 4730);
    assert!(c.state == ConnectionState::INIT);

    let now = time::now_utc();
    match c.state_time {
        Some(c_time) => {
            let result = now.cmp(&c_time);  // Could fail if no nanoseconds
            assert_eq!(Ordering::Greater, result);
        },
        None => assert!(false)
    }
}

#[test]
fn change_state() {
    let mut c = Connection::new("localhost", 4730);

    c.change_state(ConnectionState::INIT);
    assert!(c.state == ConnectionState::INIT);
}

#[test]
fn packet_constructor() {
    let data: Box<[u8]> = Box::new([0x00u8]);
    let p = Packet::new(PacketCode::REQ, ECHO_REQ, data);
    assert!(p.code == PacketCode::REQ);
    assert!(p.ptype == ECHO_REQ);
    assert!(p.data.len() == 1);
}

#[test]
#[should_panic]
fn send_packet() {
    let mut conn = Connection::new("localost", 4730);
    let data: Box<[u8]> = Box::new([0x00u8]);
    let p = Packet::new(PacketCode::REQ, ECHO_REQ, data);
    match conn.sendPacket(p) {
        Ok(_) => {},
        Err(_) => panic!("Error in sendPacket."),
    }
}

#[test]
#[should_panic]
fn echo() {
    let mut test: Vec<u8> = Vec::new();
    test.extend("abc123".to_string().bytes());
    let mut conn = Connection::new("localhost", 4730);
    let result = String::from_utf8(conn.echo(test, 0)).unwrap();
    assert_eq!("abc123", result);
    let mut test2: Vec<u8> = Vec::new();
    let mut output = String::from_utf8(conn.echo(test2, 0)).unwrap();
    println!("UUID = {}", output);
}

#[test]
fn bcs_constructor() {
    let bcs = BaseClientServer::new("clientid".to_string().into_bytes());
}

#[derive(PartialEq)]
enum ConnectionState {
    INIT,
}

struct Connection {
    host: String,
    port: u16,
    conn: Option<TcpStream>,
    connect_time: Option<time::Tm>,
    state: ConnectionState,
    state_time: Option<time::Tm>,
    echo_conditions: HashMap<Vec<u8>, Arc<(Mutex<bool>, Condvar)>>,
}

struct Packet {
    code: PacketCode,
    ptype: u32,
    data: Box<[u8]>,
}

impl Connection {
    fn new(host: &str, port: u16) -> Connection {
        let mut c = Connection {
            host: host.to_string(),
            port: port,
            conn: None,
            connect_time: None,
            state: ConnectionState::INIT,
            state_time: None,
            echo_conditions: HashMap::new(),
        };
        c.change_state(ConnectionState::INIT);
        return c
    }

    fn change_state(&mut self, state: ConnectionState) {
        self.state_time = Some(time::now_utc());
        self.state = state;
    }

    fn connect(&mut self) -> io::Result<()> {
        match self.conn {
            None => {
                self.conn = Some(try!(TcpStream::connect((&self.host as &str, self.port))));
                self.connect_time = Some(time::now_utc());
            },
            Some(_) => { /* log debug "already connected" */ },
        }
        return Ok(());
    }

    fn disconnect(&mut self) {
        match self.conn {
            Some(_) => self.conn = None,
            None => { /* log debug "already disconnected" */ },
        }
    }

    fn reconnect(&mut self) -> io::Result<()> {
        self.disconnect();
        try!(self.connect());
        return Ok(());
    }

    fn sendPacket(&mut self, packet: Packet) -> io::Result<()> {
        match self.conn {
            Some(ref mut c) => {
                match packet.code {
                    PacketCode::REQ => { try!(c.write(&REQ)); }
                    PacketCode::RES => { try!(c.write(&RES)); }
                }
                try!(c.write_u32::<BigEndian>(packet.ptype));
                try!(c.write_u32::<BigEndian>(packet.data.len() as u32));
                try!(c.write_all(&packet.data));
                Ok(())
            },
            None => panic!("Attempted to send packet on disconnected socket")
        }
    }

    fn _code_from_vec(code: Vec<u8>) -> Result<PacketCode, &'static str> {
        if code[..] == REQ {
            return Ok(PacketCode::REQ);
        } else if code[..] == RES {
            return Ok(PacketCode::RES);
        }
        return Err("Invalid packet code");
    }

    fn readPacket(&mut self) -> io::Result<Packet> {
        match self.conn {
            Some(ref mut c) => {
                let mut code: Vec<u8> = Vec::new();
                {
                    let mut codestream = c.take(4);
                    try!(codestream.read_to_end(&mut code));
                }
                let code: PacketCode = Connection::_code_from_vec(code).unwrap();
                let ptype   = try!(c.read_u32::<BigEndian>());
                let datalen = try!(c.read_u32::<BigEndian>());
                let mut datastream = c.take(datalen as u64);
                let mut buf: Vec<u8> = Vec::new();
                try!(datastream.read_to_end(&mut buf));
                Ok(
                    Packet {
                        code: code,
                        ptype: ptype,
                        data: buf.into_boxed_slice(),
                    })
            },
            None => panic!("Attempted to read packet on disconnected socket")
        }
    }

    fn echo(&mut self, mut data: Vec<u8>, timeout: u32) -> Vec<u8> {
        if data.len() == 0 {
            data.extend(Uuid::new_v4().to_simple_string().bytes());
        }
        let lock_cond = Arc::new((Mutex::new(false), Condvar::new()));
        let &(ref lock, ref cond) = &*lock_cond;
        let mut handled_echo = lock.lock().unwrap();
        self.sendEchoReq(data.clone());
        self.echo_conditions.insert(data.clone(), lock_cond.clone());
        if !*cond.wait_timeout_ms(handled_echo, timeout * 1000).unwrap().0 {
            panic!("Timed out waiting for response from echo.");
        };
        self.echo_conditions.remove(&data);
        data
    }

    fn sendEchoReq(&mut self, mut data: Vec<u8>) -> io::Result<()> {
        let p = Packet::new(PacketCode::REQ, ECHO_REQ, data.into_boxed_slice());
        try!(self.sendPacket(p));
        Ok(())
    }

    fn handleEchoRes(&mut self, mut data: Vec<u8>) {
        if let Some(mutexlock) = self.echo_conditions.get_mut(&data) {
            let lock = &mutexlock.0;
            let cond = &mutexlock.1;
            let mut handled_echo = lock.lock().unwrap();
            *handled_echo = true;

            cond.notify_one();
        }
    }
}

struct BaseClientServer {
    client_id: Vec<u8>,
    running: bool,
    active_connections: HashMap<(String, u16), Arc<Mutex<Box<Connection>>>>,
    host_io: (Sender<Arc<Mutex<Box<(String, u16)>>>>, Receiver<Arc<Mutex<Box<(String, u16)>>>>),
    conn_io: (Sender<Arc<Mutex<Box<Connection>>>>, Receiver<Arc<Mutex<Box<Connection>>>>),
    hosts: Vec<String>,
}

impl BaseClientServer {

    fn new(client_id: Vec<u8>) -> BaseClientServer {
        BaseClientServer {
            client_id: client_id,
            running: true,
            active_connections: HashMap::new(),
            host_io: channel(),
            conn_io: channel(),
            hosts: Vec::new(),
        }
    }

    /*
    fn start(mut self) {
        let mut bcs_poll_handle = Arc::new(Mutex::new(&mut self));
        let mut bcs_conn_handle = bcs_poll_handle.clone();
        let poll_join_handle = Some(thread::scoped(move || BaseClientServer::_doPollLoop(bcs_poll_handle)));
        let connect_join_handle = Some(thread::scoped(move || BaseClientServer::_doConnectLoop(bcs_conn_handle)));
        // implicit join
    }
    */

    #[allow(unstable)]
    fn connectionManager(&mut self) {
        /* Run as a dedicated thread to manage the list of active/inactive connections */
        let (_, ref mut rx) = self.host_io;
        let (ref mut tx, _) = self.conn_io;
        let (new_tx, new_rx) = channel();
        let ac = &mut self.active_connections;
        while self.running {
            let container: Result<Arc<Mutex<Box<Connection>>>, RecvError>;
            /* either a new conn is requested, or a new conn is connected */
            select!(
                container = rx.recv() => {
                    let container = match container {
                        Ok(container) => container,
                        Err(_) => panic!("Could not receive in connection manager"),
                    };
                    let (ref host, port) = **container.lock().unwrap();
                    let mut insert = false;
                    let tx = tx.clone();
                    let new_tx = new_tx.clone();
                    match ac.get(&(host.clone(), port)) {
                        Some(conn) => {
                            thread::scoped(move || {
                                let mut real_conn = conn.lock().unwrap();
                                while true {
                                    match real_conn.reconnect() {
                                        Ok(_) => break,
                                        Err(_) => {
                                            /* log warning about reconnecting */
                                            thread::sleep_ms(1000);
                                        },
                                    }
                                };
                                tx.send(conn.clone());
                            });
                        },
                        None => {
                            thread::scoped(move || {
                                let conn: Arc<Mutex<Box<Connection>>> = Arc::new(Mutex::new(Box::new(Connection::new(&host, port)))).clone();
                                {
                                    let mut real_conn = conn.lock().unwrap();
                                    while true {
                                        match real_conn.connect() {
                                            Ok(_) => break,
                                            Err(_) => {
                                                /* log warning */
                                                thread::sleep_ms(1000);
                                            }
                                        }
                                    };
                                }
                                new_tx.send(conn.clone());
                            });
                        }
                    };
                },
                conn = new_rx.recv() => {
                    let conn = match conn {
                        Ok(conn) => conn,
                        Err(_) => panic!("Could not receive in connection manager"),
                    };
                    {
                        let ref real_conn = **conn.lock().unwrap();
                        let host = real_conn.host.clone();
                        ac.insert((host, real_conn.port), conn.clone());
                    }
                    tx.send(conn.clone());
                }
            )
        }
        for (_, conn) in ac.iter() {
            let mut conn = conn.lock().unwrap();
            conn.disconnect();
        }
    }

    fn addServer(&self, host: String, port: u16) {
        let (ref tx, _) = self.host_io;
        tx.send(Arc::new(Mutex::new(Box::new((host, port)))));
    }

    fn pollingManager(&self) {
        let (_, ref rx) = self.conn_io;
        let (ref tx, _) = self.host_io;
        let mut threads: Vec<JoinHandle<()>> = Vec::new();
        while self.running {
            let conn = rx.recv().unwrap();
            let tx = tx.clone();
            // poll this conn
            threads.push(thread::spawn(move || {
                let mut conn = conn.lock().unwrap();
                match conn.readPacket() {
                    Ok(p) => { /* handle packet */ },
                    Err(e) => {
                        /* Log failure */
                        tx.send(Arc::new(Mutex::new(Box::new((conn.host.clone(), conn.port)))));
                    }
                }
            }));
        };
        // scoped threads all joined here
        for mut thread in threads {
            thread.join();
        }
    }
}

impl PartialEq for Packet {
    fn eq(&self, other: &Packet) -> bool {
        self.code == other.code &&
        self.ptype == other.ptype &&
        self.data == other.data
    }
}

impl Packet {
    fn new(code: PacketCode, ptype: u32, data: Box<[u8]>) -> Packet {
        Packet {
            code: code,
            ptype: ptype,
            data: data,
        }
    }
}
<commit_msg>Poll connection until it has an error.<commit_after>#![feature(mpsc_select)]
#![feature(scoped)]
extern crate time;
extern crate byteorder;
extern crate uuid;

use std::option::Option;
use std::cmp::Ordering;
use std::io::Write;
use std::io::Read;
use std::io;
use std::net::TcpStream;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::thread;
use std::thread::{JoinHandle, sleep_ms, Thread};
use std::sync::{Mutex, Condvar, Arc};
use std::sync::mpsc::channel;
use std::sync::mpsc::{Receiver, Sender, RecvError};

use byteorder::{BigEndian, WriteBytesExt};
use byteorder::ReadBytesExt;
use uuid::Uuid;

pub mod constants;
use constants::*;

#[test]
fn constructor() {
    let c = Connection::new("localhost", 4730);

    assert!(c.host == "localhost");
    assert!(c.port == 4730);
    assert!(c.state == ConnectionState::INIT);

    let now = time::now_utc();
    match c.state_time {
        Some(c_time) => {
            let result = now.cmp(&c_time);  // Could fail if no nanoseconds
            assert_eq!(Ordering::Greater, result);
        },
        None => assert!(false)
    }
}

#[test]
fn change_state() {
    let mut c = Connection::new("localhost", 4730);

    c.change_state(ConnectionState::INIT);
    assert!(c.state == ConnectionState::INIT);
}

#[test]
fn packet_constructor() {
    let data: Box<[u8]> = Box::new([0x00u8]);
    let p = Packet::new(PacketCode::REQ, ECHO_REQ, data);
    assert!(p.code == PacketCode::REQ);
    assert!(p.ptype == ECHO_REQ);
    assert!(p.data.len() == 1);
}

#[test]
#[should_panic]
fn send_packet() {
    let mut conn = Connection::new("localost", 4730);
    let data: Box<[u8]> = Box::new([0x00u8]);
    let p = Packet::new(PacketCode::REQ, ECHO_REQ, data);
    match conn.sendPacket(p) {
        Ok(_) => {},
        Err(_) => panic!("Error in sendPacket."),
    }
}

#[test]
#[should_panic]
fn echo() {
    let mut test: Vec<u8> = Vec::new();
    test.extend("abc123".to_string().bytes());
    let mut conn = Connection::new("localhost", 4730);
    let result = String::from_utf8(conn.echo(test, 0)).unwrap();
    assert_eq!("abc123", result);
    let mut test2: Vec<u8> = Vec::new();
    let mut output = String::from_utf8(conn.echo(test2, 0)).unwrap();
    println!("UUID = {}", output);
}

#[test]
fn bcs_constructor() {
    let bcs = BaseClientServer::new("clientid".to_string().into_bytes());
}

#[derive(PartialEq)]
enum ConnectionState {
    INIT,
}

struct Connection {
    host: String,
    port: u16,
    conn: Option<TcpStream>,
    connect_time: Option<time::Tm>,
    state: ConnectionState,
    state_time: Option<time::Tm>,
    echo_conditions: HashMap<Vec<u8>, Arc<(Mutex<bool>, Condvar)>>,
}

struct Packet {
    code: PacketCode,
    ptype: u32,
    data: Box<[u8]>,
}

impl Connection {
    fn new(host: &str, port: u16) -> Connection {
        let mut c = Connection {
            host: host.to_string(),
            port: port,
            conn: None,
            connect_time: None,
            state: ConnectionState::INIT,
            state_time: None,
            echo_conditions: HashMap::new(),
        };
        c.change_state(ConnectionState::INIT);
        return c
    }

    fn change_state(&mut self, state: ConnectionState) {
        self.state_time = Some(time::now_utc());
        self.state = state;
    }

    fn connect(&mut self) -> io::Result<()> {
        match self.conn {
            None => {
                self.conn = Some(try!(TcpStream::connect((&self.host as &str, self.port))));
                self.connect_time = Some(time::now_utc());
            },
            Some(_) => { /* log debug "already connected" */ },
        }
        return Ok(());
    }

    fn disconnect(&mut self) {
        match self.conn {
            Some(_) => self.conn = None,
            None => { /* log debug "already disconnected" */ },
        }
    }

    fn reconnect(&mut self) -> io::Result<()> {
        self.disconnect();
        try!(self.connect());
        return Ok(());
    }

    fn sendPacket(&mut self, packet: Packet) -> io::Result<()> {
        match self.conn {
            Some(ref mut c) => {
                match packet.code {
                    PacketCode::REQ => { try!(c.write(&REQ)); }
                    PacketCode::RES => { try!(c.write(&RES)); }
                }
                try!(c.write_u32::<BigEndian>(packet.ptype));
                try!(c.write_u32::<BigEndian>(packet.data.len() as u32));
                try!(c.write_all(&packet.data));
                Ok(())
            },
            None => panic!("Attempted to send packet on disconnected socket")
        }
    }

    fn _code_from_vec(code: Vec<u8>) -> Result<PacketCode, &'static str> {
        if code[..] == REQ {
            return Ok(PacketCode::REQ);
        } else if code[..] == RES {
            return Ok(PacketCode::RES);
        }
        return Err("Invalid packet code");
    }

    fn readPacket(&mut self) -> io::Result<Packet> {
        match self.conn {
            Some(ref mut c) => {
                let mut code: Vec<u8> = Vec::new();
                {
                    let mut codestream = c.take(4);
                    try!(codestream.read_to_end(&mut code));
                }
                let code: PacketCode = Connection::_code_from_vec(code).unwrap();
                let ptype   = try!(c.read_u32::<BigEndian>());
                let datalen = try!(c.read_u32::<BigEndian>());
                let mut datastream = c.take(datalen as u64);
                let mut buf: Vec<u8> = Vec::new();
                try!(datastream.read_to_end(&mut buf));
                Ok(
                    Packet {
                        code: code,
                        ptype: ptype,
                        data: buf.into_boxed_slice(),
                    })
            },
            None => panic!("Attempted to read packet on disconnected socket")
        }
    }

    fn echo(&mut self, mut data: Vec<u8>, timeout: u32) -> Vec<u8> {
        if data.len() == 0 {
            data.extend(Uuid::new_v4().to_simple_string().bytes());
        }
        let lock_cond = Arc::new((Mutex::new(false), Condvar::new()));
        let &(ref lock, ref cond) = &*lock_cond;
        let mut handled_echo = lock.lock().unwrap();
        self.sendEchoReq(data.clone());
        self.echo_conditions.insert(data.clone(), lock_cond.clone());
        if !*cond.wait_timeout_ms(handled_echo, timeout * 1000).unwrap().0 {
            panic!("Timed out waiting for response from echo.");
        };
        self.echo_conditions.remove(&data);
        data
    }

    fn sendEchoReq(&mut self, mut data: Vec<u8>) -> io::Result<()> {
        let p = Packet::new(PacketCode::REQ, ECHO_REQ, data.into_boxed_slice());
        try!(self.sendPacket(p));
        Ok(())
    }

    fn handleEchoRes(&mut self, mut data: Vec<u8>) {
        if let Some(mutexlock) = self.echo_conditions.get_mut(&data) {
            let lock = &mutexlock.0;
            let cond = &mutexlock.1;
            let mut handled_echo = lock.lock().unwrap();
            *handled_echo = true;

            cond.notify_one();
        }
    }
}

struct BaseClientServer {
    client_id: Vec<u8>,
    running: bool,
    active_connections: HashMap<(String, u16), Arc<Mutex<Box<Connection>>>>,
    host_io: (Sender<Arc<Mutex<Box<(String, u16)>>>>, Receiver<Arc<Mutex<Box<(String, u16)>>>>),
    conn_io: (Sender<Arc<Mutex<Box<Connection>>>>, Receiver<Arc<Mutex<Box<Connection>>>>),
    hosts: Vec<String>,
}

impl BaseClientServer {

    fn new(client_id: Vec<u8>) -> BaseClientServer {
        BaseClientServer {
            client_id: client_id,
            running: true,
            active_connections: HashMap::new(),
            host_io: channel(),
            conn_io: channel(),
            hosts: Vec::new(),
        }
    }

    /*
    fn start(mut self) {
        let mut bcs_poll_handle = Arc::new(Mutex::new(&mut self));
        let mut bcs_conn_handle = bcs_poll_handle.clone();
        let poll_join_handle = Some(thread::scoped(move || BaseClientServer::_doPollLoop(bcs_poll_handle)));
        let connect_join_handle = Some(thread::scoped(move || BaseClientServer::_doConnectLoop(bcs_conn_handle)));
        // implicit join
    }
    */

    #[allow(unstable)]
    fn connectionManager(&mut self) {
        /* Run as a dedicated thread to manage the list of active/inactive connections */
        let (_, ref mut rx) = self.host_io;
        let (ref mut tx, _) = self.conn_io;
        let (new_tx, new_rx) = channel();
        let ac = &mut self.active_connections;
        while self.running {
            let container: Result<Arc<Mutex<Box<Connection>>>, RecvError>;
            /* either a new conn is requested, or a new conn is connected */
            select!(
                container = rx.recv() => {
                    let container = match container {
                        Ok(container) => container,
                        Err(_) => panic!("Could not receive in connection manager"),
                    };
                    let (ref host, port) = **container.lock().unwrap();
                    let mut insert = false;
                    let tx = tx.clone();
                    let new_tx = new_tx.clone();
                    match ac.get(&(host.clone(), port)) {
                        Some(conn) => {
                            thread::scoped(move || {
                                let mut real_conn = conn.lock().unwrap();
                                while true {
                                    match real_conn.reconnect() {
                                        Ok(_) => break,
                                        Err(_) => {
                                            /* log warning about reconnecting */
                                            thread::sleep_ms(1000);
                                        },
                                    }
                                };
                                tx.send(conn.clone());
                            });
                        },
                        None => {
                            thread::scoped(move || {
                                let conn: Arc<Mutex<Box<Connection>>> = Arc::new(Mutex::new(Box::new(Connection::new(&host, port)))).clone();
                                {
                                    let mut real_conn = conn.lock().unwrap();
                                    while true {
                                        match real_conn.connect() {
                                            Ok(_) => break,
                                            Err(_) => {
                                                /* log warning */
                                                thread::sleep_ms(1000);
                                            }
                                        }
                                    };
                                }
                                new_tx.send(conn.clone());
                            });
                        }
                    };
                },
                conn = new_rx.recv() => {
                    let conn = match conn {
                        Ok(conn) => conn,
                        Err(_) => panic!("Could not receive in connection manager"),
                    };
                    {
                        let ref real_conn = **conn.lock().unwrap();
                        let host = real_conn.host.clone();
                        ac.insert((host, real_conn.port), conn.clone());
                    }
                    tx.send(conn.clone());
                }
            )
        }
        for (_, conn) in ac.iter() {
            let mut conn = conn.lock().unwrap();
            conn.disconnect();
        }
    }

    fn addServer(&self, host: String, port: u16) {
        let (ref tx, _) = self.host_io;
        tx.send(Arc::new(Mutex::new(Box::new((host, port)))));
    }

    fn pollingManager(&self) {
        let (_, ref rx) = self.conn_io;
        let (ref tx, _) = self.host_io;
        let mut threads: Vec<JoinHandle<()>> = Vec::new();
        while self.running {
            let conn = rx.recv().unwrap();
            let tx = tx.clone();
            // poll this conn
            threads.push(thread::spawn(move || {
                while true {
                    let mut conn = conn.lock().unwrap();
                    match conn.readPacket() {
                        Ok(p) => { /* handle packet */ },
                        Err(e) => {
                            /* Log failure */
                            tx.send(Arc::new(Mutex::new(Box::new((conn.host.clone(), conn.port)))));
                            break;
                        }
                    }
                }
            }));
        };
        // scoped threads all joined here
        for mut thread in threads {
            thread.join();
        }
    }
}

impl PartialEq for Packet {
    fn eq(&self, other: &Packet) -> bool {
        self.code == other.code &&
        self.ptype == other.ptype &&
        self.data == other.data
    }
}

impl Packet {
    fn new(code: PacketCode, ptype: u32, data: Box<[u8]>) -> Packet {
        Packet {
            code: code,
            ptype: ptype,
            data: data,
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

// LDAPString ::= OCTET STRING -- UTF-8 encoded,
//                             -- [ISO10646] characters

#[derive(Debug)]
struct Asn1Type {
  name: String,
  assign: String
}

named!(type_name <&[u8], String>, chain!(
  s: take_while!(nom::is_alphanumeric),
  || String::from_utf8(Vec::from(s)).unwrap()
));

named!(type_assignment <&[u8], Asn1Type>, chain!(
  opt!(nom::multispace) ~
  name: type_name ~
  take_until_and_consume!("::=") ~
  opt!(nom::multispace) ~
  assign: type_name,
  || Asn1Type {
    name: name,
    assign: assign,
  }
));

fn main() {
  println!("{:#?}", type_assignment("test ::= hi".as_bytes()));
}
<commit_msg>Expand types<commit_after>#[macro_use]
extern crate nom;

// LDAPString ::= OCTET STRING -- UTF-8 encoded,
//                             -- [ISO10646] characters

#[derive(Debug)]
enum Asn1Type {
  Type(String),
  Seq(Asn1Seq),
}

#[derive(Debug)]
struct Asn1Def {
  name: String,
  assign: Asn1Type,
}

#[derive(Debug)]
struct Asn1Seq {
  fields: Vec<Asn1Def>,
}

named!(type_name <&[u8], String>, chain!(
  s: take_while!(nom::is_alphanumeric),
  || String::from_utf8(Vec::from(s)).unwrap()
));

named!(type_assignment <&[u8], Asn1Def>, chain!(
  opt!(nom::multispace) ~
  name: type_name ~
  take_until_and_consume!("::=") ~
  opt!(nom::multispace) ~
  assign: type_name,
  || Asn1Def {
    name: name,
    assign: Asn1Type::Type(assign),
  }
));

named!(type_sequence <&[u8], Asn1Seq>, chain!(
  tag!("SEQUNECE"),
  || Asn1Seq {
    fields: Vec::new(),
  }
));

fn main() {
  println!("{:#?}", type_assignment("test ::= hi".as_bytes()));
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate libc;

#[cfg(target_os = "android")]
#[phase(plugin, link)]
extern crate android_glue;

#[phase(plugin)]
extern crate gl_generator;

extern crate glutin;

mod gl {
    generate_gl_bindings! {
        api: "gles2",
        profile: "core",
        version: "2.0",
        generator: "static_struct",
    }
}

static mut COLOR_COUNTER: i32 = 0;

pub fn main() {
    let window = glutin::Window::new().unwrap();
    unsafe {
        window.make_current();
    };
    let gl = gl::Gles2::load_with(|s| window.get_proc_address(s));
    while !window.is_closed() {
        unsafe {
            match COLOR_COUNTER {
                0 => gl.ClearColor(0.3, 0.0, 0.0, 1.0),
                30 => gl.ClearColor(0.0, 0.3, 0.0, 1.0),
                60 => gl.ClearColor(0.0, 0.0, 0.3, 1.0),
                _ => if COLOR_COUNTER > 90 { COLOR_COUNTER = -1; }
            }
            COLOR_COUNTER += 1;
        }
        unsafe {
            assert!(gl.GetError() == 0);
        }
        unsafe {
            gl.Clear(gl::COLOR_BUFFER_BIT);
        }
        window.swap_buffers();
        let events = window.wait_events().collect::<Vec<_>>();
        if !events.is_empty() {
            println!("{}", events);
        }
    }
}

#[cfg(target_os = "android")]
#[no_mangle]
pub fn rust_android_main(app: *mut()) {
    android_glue::android_main2(app, proc() main());
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>visualizer struct, wait_events -> poll_events<commit_after>#![feature(phase)]

extern crate libc;

#[cfg(target_os = "android")]
#[phase(plugin, link)]
extern crate android_glue;

#[phase(plugin)]
extern crate gl_generator;

extern crate glutin;

use glutin::{Event, VirtualKeyCode};

mod gl {
    generate_gl_bindings! {
        api: "gles2",
        profile: "core",
        version: "2.0",
        generator: "static_struct",
    }
}

static mut COLOR_COUNTER: i32 = 0; // TODO

struct Visualizer {
    gl: gl::Gles2,
    window: glutin::Window,
    should_close: bool,
}

impl Visualizer {
    fn new() -> Visualizer {
        let window = glutin::Window::new().unwrap();
        unsafe {
            window.make_current();
        };
        let gl = gl::Gles2::load_with(|s| window.get_proc_address(s));
        Visualizer {
            gl: gl,
            window: window,
            should_close: false,
        }
    }

    fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if !events.is_empty() {
            println!("{}", events);
        }
        for event in events.iter() {
            match *event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape))
                    | Event::Closed =>
                {
                    self.should_close = true;
                },
                _ => {},
            }
        }
    }

    fn draw(&self) {
        unsafe {
            match COLOR_COUNTER {
                0 => self.gl.ClearColor(0.3, 0.0, 0.0, 1.0),
                30 => self.gl.ClearColor(0.0, 0.3, 0.0, 1.0),
                60 => self.gl.ClearColor(0.0, 0.0, 0.3, 1.0),
                _ => if COLOR_COUNTER > 90 { COLOR_COUNTER = -1; }
            }
            COLOR_COUNTER += 1;
            assert!(self.gl.GetError() == 0);
            self.gl.Clear(gl::COLOR_BUFFER_BIT);
        }
        self.window.swap_buffers();
    }

    fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.draw();
        // self.update_time();
    }
}

pub fn main() {
    let mut visualizer = Visualizer::new();
    while visualizer.is_running() {
        visualizer.tick();
    }
}

#[cfg(target_os = "android")]
#[no_mangle]
pub fn rust_android_main(app: *mut()) {
    android_glue::android_main2(app, proc() main());
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(custom_derive)]
#![feature(rustc_private)]

#[macro_use] extern crate log;

extern crate serde;
extern crate serde_json;

extern crate byteorder;

pub mod message;
pub mod discovery;
pub mod cdr;

pub use cdr::ser::*;
pub use message::*;
<commit_msg>comment out nightly-only stuff to see if matrix gets further<commit_after>#![allow(dead_code)]
// #![feature(custom_derive)]
// #![feature(rustc_private)]

//#[macro_use] extern crate log;

extern crate serde;
extern crate serde_json;

extern crate byteorder;

pub mod message;
pub mod discovery;
pub mod cdr;

pub use cdr::ser::*;
pub use message::*;
<|endoftext|>


<commit_before>#![feature(zero_one)]

#![cfg_attr(test, feature(test))]
#[cfg(test)] extern crate test;

pub mod math;
pub mod search;
pub mod matrix;
pub mod graph;
<commit_msg>removed graph<commit_after>#![feature(zero_one)]

#![cfg_attr(test, feature(test))]
#[cfg(test)] extern crate test;

pub mod math;
pub mod search;
pub mod matrix;
<|endoftext|>


<commit_before>//! `simd` offers a basic interface to the SIMD functionality of CPUs.
//!
//! **Warning** This is an actively developed work-in-progress, and
//! may/will break from commit to commit.
//!
//! # Installation
//!
//! Via git:
//!
//! ```toml
//! simd = { git = "https://github.com/huonw/simd" }
//! ```
//!
//! This is **not** currently the `simd` crate on crates.io.

#![cfg_attr(feature = "serde", feature(plugin, custom_derive))]
#![cfg_attr(feature = "serde", plugin(serde_macros))]

#![feature(cfg_target_feature, repr_simd, platform_intrinsics, const_fn)]
#![allow(non_camel_case_types)]

#[cfg(feature = "serde")]
extern crate serde;

/// Boolean type for 8-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool8i(i8);
/// Boolean type for 16-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool16i(i16);
/// Boolean type for 32-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool32i(i32);
/// Boolean type for 32-bit floats.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool32f(i32);

macro_rules! bool {
    ($($name: ident, $inner: ty;)*) => {
        $(
            impl From<bool> for $name {
                #[inline]
                fn from(b: bool) -> $name {
                    $name(-(b as $inner))
                }
            }
            impl From<$name> for bool {
                #[inline]
                fn from(b: $name) -> bool {
                    b.0 != 0
                }
            }
            )*
    }
}
bool! {
    bool8i, i8;
    bool16i, i16;
    bool32i, i32;
    bool32f, i32;
}

/// Types that are SIMD vectors.
pub unsafe trait Simd {
    /// The corresponding boolean vector type.
    type Bool: Simd;
    /// The element that this vector stores.
    type Elem;
}

/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u32x4(u32, u32, u32, u32);
/// A SIMD vector of 4 `i32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i32x4(i32, i32, i32, i32);
/// A SIMD vector of 4 `f32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct f32x4(f32, f32, f32, f32);
/// A SIMD boolean vector for length-4 vectors of 32-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32ix4(i32, i32, i32, i32);
/// A SIMD boolean vector for length-4 vectors of 32-bit floats.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32fx4(i32, i32, i32, i32);

#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct u32x2(u32, u32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct i32x2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct f32x2(f32, f32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32ix2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32fx2(i32, i32);

/// A SIMD vector of 8 `u16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u16x8(u16, u16, u16, u16,
                 u16, u16, u16, u16);
/// A SIMD vector of 8 `i16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i16x8(i16, i16, i16, i16,
                 i16, i16, i16, i16);
/// A SIMD boolean vector for length-8 vectors of 16-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool16ix8(i16, i16, i16, i16,
                     i16, i16, i16, i16);

/// A SIMD vector of 16 `u8`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8,
                 u8, u8, u8, u8, u8, u8, u8, u8);
/// A SIMD vector of 16 `i8`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
                 i8, i8, i8, i8, i8, i8, i8, i8);
/// A SIMD boolean vector for length-16 vectors of 8-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool8ix16(i8, i8, i8, i8, i8, i8, i8, i8,
                     i8, i8, i8, i8, i8, i8, i8, i8);

macro_rules! simd {
    ($($bool: ty: $($ty: ty = $elem: ty),*;)*) => {
        $($(unsafe impl Simd for $ty {
            type Bool = $bool;
            type Elem = $elem;
        }
            impl Clone for $ty { fn clone(&self) -> Self { *self } }
            )*)*}
}
simd! {
    bool8ix16: i8x16 = i8, u8x16 = u8, bool8ix16 = bool8i;
    bool16ix8: i16x8 = i16, u16x8 = u16, bool16ix8 = bool16i;
    bool32ix4: i32x4 = i32, u32x4 = u32, bool32ix4 = bool32i;
    bool32fx4: f32x4 = f32, bool32fx4 = bool32f;

    bool32ix2: i32x2 = i32, u32x2 = u32, bool32ix2 = bool32i;
    bool32fx2: f32x2 = f32, bool32fx2 = bool32f;
}

#[allow(dead_code)]
#[inline]
fn bitcast<T: Simd, U: Simd>(x: T) -> U {
    assert_eq!(std::mem::size_of::<T>(),
               std::mem::size_of::<U>());
    unsafe {std::mem::transmute_copy(&x)}
}

#[allow(dead_code)]
extern "platform-intrinsic" {
    fn simd_eq<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ne<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_lt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_le<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_gt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ge<T: Simd<Bool = U>, U>(x: T, y: T) -> U;

    fn simd_shuffle2<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 2]) -> U;
    fn simd_shuffle4<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 4]) -> U;
    fn simd_shuffle8<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 8]) -> U;
    fn simd_shuffle16<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 16]) -> U;

    fn simd_insert<T: Simd<Elem = U>, U>(x: T, idx: u32, val: U) -> T;
    fn simd_extract<T: Simd<Elem = U>, U>(x: T, idx: u32) -> U;

    fn simd_cast<T: Simd, U: Simd>(x: T) -> U;

    fn simd_add<T: Simd>(x: T, y: T) -> T;
    fn simd_sub<T: Simd>(x: T, y: T) -> T;
    fn simd_mul<T: Simd>(x: T, y: T) -> T;
    fn simd_div<T: Simd>(x: T, y: T) -> T;
    fn simd_shl<T: Simd>(x: T, y: T) -> T;
    fn simd_shr<T: Simd>(x: T, y: T) -> T;
    fn simd_and<T: Simd>(x: T, y: T) -> T;
    fn simd_or<T: Simd>(x: T, y: T) -> T;
    fn simd_xor<T: Simd>(x: T, y: T) -> T;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone)]
struct Unalign<T>(T);

#[macro_use]
mod common;
mod sixty_four;
mod v256;

#[cfg(any(feature = "doc",
          target_arch = "x86",
          target_arch = "x86_64"))]
pub mod x86;
#[cfg(any(feature = "doc", target_arch = "arm"))]
pub mod arm;
#[cfg(any(feature = "doc", target_arch = "aarch64"))]
pub mod aarch64;
<commit_msg>Inline clone.<commit_after>//! `simd` offers a basic interface to the SIMD functionality of CPUs.
//!
//! **Warning** This is an actively developed work-in-progress, and
//! may/will break from commit to commit.
//!
//! # Installation
//!
//! Via git:
//!
//! ```toml
//! simd = { git = "https://github.com/huonw/simd" }
//! ```
//!
//! This is **not** currently the `simd` crate on crates.io.

#![cfg_attr(feature = "serde", feature(plugin, custom_derive))]
#![cfg_attr(feature = "serde", plugin(serde_macros))]

#![feature(cfg_target_feature, repr_simd, platform_intrinsics, const_fn)]
#![allow(non_camel_case_types)]

#[cfg(feature = "serde")]
extern crate serde;

/// Boolean type for 8-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool8i(i8);
/// Boolean type for 16-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool16i(i16);
/// Boolean type for 32-bit integers.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool32i(i32);
/// Boolean type for 32-bit floats.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct bool32f(i32);

macro_rules! bool {
    ($($name: ident, $inner: ty;)*) => {
        $(
            impl From<bool> for $name {
                #[inline]
                fn from(b: bool) -> $name {
                    $name(-(b as $inner))
                }
            }
            impl From<$name> for bool {
                #[inline]
                fn from(b: $name) -> bool {
                    b.0 != 0
                }
            }
            )*
    }
}
bool! {
    bool8i, i8;
    bool16i, i16;
    bool32i, i32;
    bool32f, i32;
}

/// Types that are SIMD vectors.
pub unsafe trait Simd {
    /// The corresponding boolean vector type.
    type Bool: Simd;
    /// The element that this vector stores.
    type Elem;
}

/// A SIMD vector of 4 `u32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u32x4(u32, u32, u32, u32);
/// A SIMD vector of 4 `i32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i32x4(i32, i32, i32, i32);
/// A SIMD vector of 4 `f32`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct f32x4(f32, f32, f32, f32);
/// A SIMD boolean vector for length-4 vectors of 32-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32ix4(i32, i32, i32, i32);
/// A SIMD boolean vector for length-4 vectors of 32-bit floats.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool32fx4(i32, i32, i32, i32);

#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct u32x2(u32, u32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct i32x2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct f32x2(f32, f32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32ix2(i32, i32);
#[allow(dead_code)]
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
struct bool32fx2(i32, i32);

/// A SIMD vector of 8 `u16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u16x8(u16, u16, u16, u16,
                 u16, u16, u16, u16);
/// A SIMD vector of 8 `i16`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i16x8(i16, i16, i16, i16,
                 i16, i16, i16, i16);
/// A SIMD boolean vector for length-8 vectors of 16-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool16ix8(i16, i16, i16, i16,
                     i16, i16, i16, i16);

/// A SIMD vector of 16 `u8`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8,
                 u8, u8, u8, u8, u8, u8, u8, u8);
/// A SIMD vector of 16 `i8`s.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8,
                 i8, i8, i8, i8, i8, i8, i8, i8);
/// A SIMD boolean vector for length-16 vectors of 8-bit integers.
#[repr(simd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy)]
pub struct bool8ix16(i8, i8, i8, i8, i8, i8, i8, i8,
                     i8, i8, i8, i8, i8, i8, i8, i8);

macro_rules! simd {
    ($($bool: ty: $($ty: ty = $elem: ty),*;)*) => {
        $($(unsafe impl Simd for $ty {
            type Bool = $bool;
            type Elem = $elem;
        }
            impl Clone for $ty { #[inline] fn clone(&self) -> Self { *self } }
            )*)*}
}
simd! {
    bool8ix16: i8x16 = i8, u8x16 = u8, bool8ix16 = bool8i;
    bool16ix8: i16x8 = i16, u16x8 = u16, bool16ix8 = bool16i;
    bool32ix4: i32x4 = i32, u32x4 = u32, bool32ix4 = bool32i;
    bool32fx4: f32x4 = f32, bool32fx4 = bool32f;

    bool32ix2: i32x2 = i32, u32x2 = u32, bool32ix2 = bool32i;
    bool32fx2: f32x2 = f32, bool32fx2 = bool32f;
}

#[allow(dead_code)]
#[inline]
fn bitcast<T: Simd, U: Simd>(x: T) -> U {
    assert_eq!(std::mem::size_of::<T>(),
               std::mem::size_of::<U>());
    unsafe {std::mem::transmute_copy(&x)}
}

#[allow(dead_code)]
extern "platform-intrinsic" {
    fn simd_eq<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ne<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_lt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_le<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_gt<T: Simd<Bool = U>, U>(x: T, y: T) -> U;
    fn simd_ge<T: Simd<Bool = U>, U>(x: T, y: T) -> U;

    fn simd_shuffle2<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 2]) -> U;
    fn simd_shuffle4<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 4]) -> U;
    fn simd_shuffle8<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 8]) -> U;
    fn simd_shuffle16<T: Simd, U: Simd<Elem = T::Elem>>(x: T, y: T, idx: [u32; 16]) -> U;

    fn simd_insert<T: Simd<Elem = U>, U>(x: T, idx: u32, val: U) -> T;
    fn simd_extract<T: Simd<Elem = U>, U>(x: T, idx: u32) -> U;

    fn simd_cast<T: Simd, U: Simd>(x: T) -> U;

    fn simd_add<T: Simd>(x: T, y: T) -> T;
    fn simd_sub<T: Simd>(x: T, y: T) -> T;
    fn simd_mul<T: Simd>(x: T, y: T) -> T;
    fn simd_div<T: Simd>(x: T, y: T) -> T;
    fn simd_shl<T: Simd>(x: T, y: T) -> T;
    fn simd_shr<T: Simd>(x: T, y: T) -> T;
    fn simd_and<T: Simd>(x: T, y: T) -> T;
    fn simd_or<T: Simd>(x: T, y: T) -> T;
    fn simd_xor<T: Simd>(x: T, y: T) -> T;
}
#[repr(packed)]
#[derive(Debug, Copy, Clone)]
struct Unalign<T>(T);

#[macro_use]
mod common;
mod sixty_four;
mod v256;

#[cfg(any(feature = "doc",
          target_arch = "x86",
          target_arch = "x86_64"))]
pub mod x86;
#[cfg(any(feature = "doc", target_arch = "arm"))]
pub mod arm;
#[cfg(any(feature = "doc", target_arch = "aarch64"))]
pub mod aarch64;
<|endoftext|>


<commit_before>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::io::{Error, ErrorKind, Result};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

#[derive(Debug)]
/// `Discover` type
///
/// Used for discovering sonos devices in the local network via the simple service discovery protocol (ssdp).
/// The ssd-protocol works via udp sockets. First a certain search-message is sent to the multicast address (239.255.255.250:1900).
///
/// All answer from upnp (universal plug and play) ready devices are processed and filtered ("Sonos" is in the reply).
pub struct Discover {
    /// Multicast address in the local network
    multicast_addr: SocketAddr,
    /// Socket implementation
    /// INFO: The socket type will likely change in the future due to cross platform compatability
    socket: Arc<Socket>
}

impl Discover {
    /// Creates a new `Discovery`. Uses the default socket on the default ipv4 multicast address (239.255.255.250:1900).
    ///
    /// # Examples
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let discovery: Discovery = Discovery::new().unwrap();
    /// ```
    pub fn new() -> Result<Self> {
        let multicast_address = match SocketAddr::from_str("239.255.255.250:1900") {
            Ok(address) => address,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Couldn't parse socket address"))
        };

        Discover::with_address(multicast_address)
    }

    /// Creates a new `Discovery` with a custom multicast address.
    pub fn with_address(address: SocketAddr) -> Result<Self> {
        let socket = Discover::create_default_socket()?;
        Ok(Discover {
            multicast_addr: address,
            socket: socket
        })
    }

    /// Create a default socket
    /// socket option: AF_INET - SOCK_DGRAM - 0 // Automatically discover the protocol (IPPROTO_UDP)
    /// socket option: IPPROTO_IP - IP_MULTICAST_TTL - 4 // UPnP 1.0 needs a TTL of 4
    fn create_default_socket() -> Result<Arc<Socket>> {
        let socket_family = AF_INET;
        let socket_level = SOCK_DGRAM;
        let protocol = 0; // auto discover
        let socket_options = vec![(IPPROTO_IP, IP_MULTICAST_TTL, 4)];

        Discover::create_socket(socket_family, socket_level, protocol, &socket_options)
    }

    fn create_socket(socket_family: i32, socket_type: i32, protocol: i32, socket_options: &Vec<(i32, i32, i32)>) -> Result<Arc<Socket>> {
        let socket = Socket::new(socket_family, socket_type, protocol)?;
        for socket_option in socket_options {
            // TODO: Use result, allow to fail, panic or return a result?
            socket.setsockopt(socket_option.0, socket_option.1, socket_option.2)?
        }

        Ok(Arc::new(socket))
    }

    /// Sends the search message to the defined socket.
    /// Message can't have leading/trailing whitespaces (\s).
    ///
    /// # Message
    /// ```
    /// M-SEARCH * HTTP/1.1
    /// HOST: 239.255.255.250:1900
    /// MAN: "ssdp:discover"
    /// MX: 1
    /// ST: urn:schemas-upnp-org:device:ZonePlayer:1```
    fn send_search(&self) -> Result<usize> {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();

        self.socket.sendto(player_search, 0, &self.multicast_addr)
    }

    /// Start discovering devices.
    ///
    /// # Examples
    /// In this example the search will stop if3 devices have been discovered or the default timeout (5s) is reached.
    /// This is useful if you know the amount of speakers you have and want to reduce the search time.
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let devices: HashSet<IpAddr> = Discovery::new().unwrap().start(None, Some(3)).unwrap();
    /// ```
    pub fn start(&self, timeout: Option<u32>, device_count: Option<usize>) -> Result<HashSet<IpAddr>> {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search()?;
        // There's probably a better way than a double clone
        let socket = self.socket.clone();
        let mut devices: HashSet<IpAddr> = HashSet::new();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            thread::spawn(move ||
                {
                    // TODO: Add logging
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            // TODO: Add logging, fail on multiple send errors?
                            match sender.send((__addr, _data)) {
                                Ok(_) => {}
                                Err(_) => {}
                            };
                        }
                        Err(_) => {}
                    }
                }
            );

            // TODO: Add logging, change
            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };

            // Skip from_utf8_lossy
            // Due to the usual small size of `devices`, this is faster than decoding a potentially large response
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }

        Ok(devices)
    }
}

/// Drop internal socket on going out of scope
impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        // Log failure for debugging
        let _ = self.socket.close();
    }
}
<commit_msg>Change return type of `start` Closes #2<commit_after>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::io::{Error, ErrorKind, Result};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

#[derive(Debug)]
/// `Discover` type
///
/// Used for discovering sonos devices in the local network via the simple service discovery protocol (ssdp).
/// The ssd-protocol works via udp sockets. First a certain search-message is sent to the multicast address (239.255.255.250:1900).
///
/// All answer from upnp (universal plug and play) ready devices are processed and filtered ("Sonos" is in the reply).
pub struct Discover {
    /// Multicast address in the local network
    multicast_addr: SocketAddr,
    /// Socket implementation
    /// INFO: The socket type will likely change in the future due to cross platform compatability
    socket: Arc<Socket>
}

impl Discover {
    /// Creates a new `Discovery`. Uses the default socket on the default ipv4 multicast address (239.255.255.250:1900).
    ///
    /// # Examples
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let discovery: Discovery = Discovery::new().unwrap();
    /// ```
    pub fn new() -> Result<Self> {
        let multicast_address = match SocketAddr::from_str("239.255.255.250:1900") {
            Ok(address) => address,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Couldn't parse socket address"))
        };

        Discover::with_address(multicast_address)
    }

    /// Creates a new `Discovery` with a custom multicast address.
    pub fn with_address(address: SocketAddr) -> Result<Self> {
        let socket = Discover::create_default_socket()?;
        Ok(Discover {
            multicast_addr: address,
            socket: socket
        })
    }

    /// Create a default socket
    /// socket option: AF_INET - SOCK_DGRAM - 0 // Automatically discover the protocol (IPPROTO_UDP)
    /// socket option: IPPROTO_IP - IP_MULTICAST_TTL - 4 // UPnP 1.0 needs a TTL of 4
    fn create_default_socket() -> Result<Arc<Socket>> {
        let socket_family = AF_INET;
        let socket_level = SOCK_DGRAM;
        let protocol = 0; // auto discover
        let socket_options = vec![(IPPROTO_IP, IP_MULTICAST_TTL, 4)];

        Discover::create_socket(socket_family, socket_level, protocol, &socket_options)
    }

    fn create_socket(socket_family: i32, socket_type: i32, protocol: i32, socket_options: &Vec<(i32, i32, i32)>) -> Result<Arc<Socket>> {
        let socket = Socket::new(socket_family, socket_type, protocol)?;
        for socket_option in socket_options {
            // TODO: Use result, allow to fail, panic or return a result?
            socket.setsockopt(socket_option.0, socket_option.1, socket_option.2)?
        }

        Ok(Arc::new(socket))
    }

    /// Sends the search message to the defined socket.
    /// Message can't have leading/trailing whitespaces (\s).
    ///
    /// # Message
    /// ```
    /// M-SEARCH * HTTP/1.1
    /// HOST: 239.255.255.250:1900
    /// MAN: "ssdp:discover"
    /// MX: 1
    /// ST: urn:schemas-upnp-org:device:ZonePlayer:1```
    fn send_search(&self) -> Result<usize> {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();

        self.socket.sendto(player_search, 0, &self.multicast_addr)
    }

    /// Start discovering devices.
    ///
    /// # Examples
    /// In this example the search will stop if3 devices have been discovered or the default timeout (5s) is reached.
    /// This is useful if you know the amount of speakers you have and want to reduce the search time.
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let devices: Vec<IpAddr> = Discovery::new().unwrap().start(None, Some(3)).unwrap();
    /// ```
    pub fn start(&self, timeout: Option<u32>, device_count: Option<usize>) -> Result<Vec<IpAddr>> {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search()?;
        // There's probably a better way than a double clone
        let socket = self.socket.clone();
        let mut devices: Vec<IpAddr> = Vec::new();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            thread::spawn(move ||
                {
                    // TODO: Add logging
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            // TODO: Add logging, fail on multiple send errors?
                            match sender.send((__addr, _data)) {
                                Ok(_) => {}
                                Err(_) => {}
                            };
                        }
                        Err(_) => {}
                    }
                }
            );

            // TODO: Add logging, change
            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };

            // Skip from_utf8_lossy
            // Due to the usual small size of `devices`, this is faster than decoding a potentially large response
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.push(_addr.ip())
            }
        }

        Ok(devices)
    }
}

/// Drop internal socket on going out of scope
impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        // Log failure for debugging
        let _ = self.socket.close();
    }
}
<|endoftext|>


<commit_before>#![feature(append)]
#![feature(hashmap_hasher)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(split_off)]

#![allow(needless_return)]
#![allow(needless_lifetimes)]
#![deny(unused_features)]
#![deny(deprecated)]
#![warn(unused_variables)]
#![warn(unused_imports)]
#![warn(dead_code)]
#![warn(missing_copy_implementations)]
//#![warn(missing_docs)]

extern crate ansi_term;
extern crate term;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;

#[macro_use] pub mod macros;

pub mod front;
pub mod middle;
pub mod back;
pub mod driver;
pub mod util;<commit_msg>Remove clippy lint arguments<commit_after>#![feature(append)]
#![feature(hashmap_hasher)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(split_off)]

#![deny(unused_features)]
#![deny(deprecated)]
#![warn(unused_variables)]
#![warn(unused_imports)]
#![warn(dead_code)]
#![warn(missing_copy_implementations)]
//#![warn(missing_docs)]

extern crate ansi_term;
extern crate term;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;

#[macro_use] pub mod macros;

pub mod front;
pub mod middle;
pub mod back;
pub mod driver;
pub mod util;<|endoftext|>


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

use std::fmt;
use std::io::Read;

const LF: u8 = b'\n';
const CR: u8 = b'\r';
const QUOTE: u8 = b'"';
const COMMA: u8 = b',';

// Error messages
const UNEXPECTED_EOL: &str = "Unexpected end of line";
const UNEXPECTED_CHAR: &str = "Unexpected character after quote";
const EXPECTED_LF: &str = "Expected linefeed after carriage return";

enum CSVState {
    Start,
    NonQuotedValue,
    QuotedValue,
    QuoteQuote,
    ExpectLF,
    Error,
}

type CSVResult = Result<CSVState, &'static str>;

impl CSVState {
    fn parse_byte(&self, byte: u8) -> CSVResult {
        match (self, byte) {
            (CSVState::Start, QUOTE) => Ok(CSVState::QuotedValue),
            (CSVState::Start, COMMA) => Ok(CSVState::Start),
            (CSVState::Start, _) => Ok(CSVState::NonQuotedValue),

            (CSVState::NonQuotedValue, COMMA) => Ok(CSVState::Start),
            (CSVState::NonQuotedValue, LF) => Ok(CSVState::Start),
            (CSVState::NonQuotedValue, CR) => Ok(CSVState::ExpectLF),
            (CSVState::NonQuotedValue, _) => Ok(CSVState::NonQuotedValue),

            (CSVState::QuotedValue, QUOTE) => Ok(CSVState::QuoteQuote),
            (CSVState::QuotedValue, CR) => Err(UNEXPECTED_EOL),
            (CSVState::QuotedValue, LF) => Err(UNEXPECTED_EOL),
            (CSVState::QuotedValue, _) => Ok(CSVState::QuotedValue),

            (CSVState::QuoteQuote, QUOTE) => Ok(CSVState::QuotedValue),
            (CSVState::QuoteQuote, COMMA) => Ok(CSVState::Start),
            (CSVState::QuoteQuote, LF) => Ok(CSVState::Start),
            (CSVState::QuoteQuote, CR) => Ok(CSVState::ExpectLF),
            (CSVState::QuoteQuote, _) => Err(UNEXPECTED_CHAR),

            (CSVState::ExpectLF, LF) => Ok(CSVState::Start),
            (CSVState::ExpectLF, _) => Err(EXPECTED_LF),

            (CSVState::Error, LF) => Ok(CSVState::Start),
            (CSVState::Error, _) => Ok(CSVState::Error),
        }
    }
}

#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct CSVError {
    pub line: u32,
    pub col: u32,
    pub text: &'static str,
}

impl fmt::Display for CSVError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{} {}", self.line, self.col, self.text)
    }
}

pub fn csv_report(reader: impl Read) -> impl Iterator<Item = CSVError> {
    let mut line = 1;
    let mut col = 0;
    let mut state = CSVState::Start;

    reader.bytes().filter_map(move |b| {
        let byte = b.unwrap();

        match state.parse_byte(byte) {
            Ok(new_state) => {
                state = new_state;
                if byte == LF {
                    line += 1;
                    col = 0;
                } else {
                    col += 1;
                }
                None
            }
            Err(text) => {
                let err = CSVError {line, col, text};
                if byte == LF {
                    line += 1;
                    col = 0;
                } else {
                    col += 1;
                };
                state = match text {
                    UNEXPECTED_EOL => CSVState::Start,
                    _ => CSVState::Error,
                };
                Some(err)
            }
        }
    })
}

#[cfg(test)]
mod tests {
    use super::{csv_report, CSVError, UNEXPECTED_CHAR, UNEXPECTED_EOL};

    #[test]
    fn finds_errors_in_csv() {
        use std::fs::File;

        let mut file = File::open("tests/test.csv").unwrap();

        let mut report = csv_report(&mut file);

        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 2,
                col: 13,
                text: UNEXPECTED_CHAR,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 3,
                col: 28,
                text: UNEXPECTED_EOL,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 5,
                col: 31,
                text: UNEXPECTED_EOL,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 8,
                col: 14,
                text: UNEXPECTED_CHAR,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 11,
                col: 39,
                text: UNEXPECTED_EOL,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 12,
                col: 28,
                text: UNEXPECTED_EOL,
            })
        );
        assert_eq!(report.next(), None);
    }
}
<commit_msg>Use an enum for errors<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fmt;
use std::io::Read;

const LF: u8 = b'\n';
const CR: u8 = b'\r';
const QUOTE: u8 = b'"';
const COMMA: u8 = b',';

#[derive(Debug, PartialEq)]
pub enum ErrorType {
    UnexpectedEOL,
    UnexpectedChar,
    ExpectedLF,
}

impl fmt::Display for ErrorType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let text = match self {
            ErrorType::UnexpectedEOL => "Unexpected EOL",
            ErrorType::UnexpectedChar => "Unexpected char",
            ErrorType::ExpectedLF => "Expected LF",
        };
        write!(f, "{}", text)
    }
}

enum CSVState {
    Start,
    NonQuotedValue,
    QuotedValue,
    QuoteQuote,
    ExpectLF,
    Error,
}

type CSVResult = Result<CSVState, ErrorType>;

impl CSVState {
    fn parse_byte(&self, byte: u8) -> CSVResult {
        match (self, byte) {
            (CSVState::Start, QUOTE) => Ok(CSVState::QuotedValue),
            (CSVState::Start, COMMA) => Ok(CSVState::Start),
            (CSVState::Start, _) => Ok(CSVState::NonQuotedValue),

            (CSVState::NonQuotedValue, COMMA) => Ok(CSVState::Start),
            (CSVState::NonQuotedValue, LF) => Ok(CSVState::Start),
            (CSVState::NonQuotedValue, CR) => Ok(CSVState::ExpectLF),
            (CSVState::NonQuotedValue, _) => Ok(CSVState::NonQuotedValue),

            (CSVState::QuotedValue, QUOTE) => Ok(CSVState::QuoteQuote),
            (CSVState::QuotedValue, CR) => Err(ErrorType::UnexpectedEOL),
            (CSVState::QuotedValue, LF) => Err(ErrorType::UnexpectedEOL),
            (CSVState::QuotedValue, _) => Ok(CSVState::QuotedValue),

            (CSVState::QuoteQuote, QUOTE) => Ok(CSVState::QuotedValue),
            (CSVState::QuoteQuote, COMMA) => Ok(CSVState::Start),
            (CSVState::QuoteQuote, LF) => Ok(CSVState::Start),
            (CSVState::QuoteQuote, CR) => Ok(CSVState::ExpectLF),
            (CSVState::QuoteQuote, _) => Err(ErrorType::UnexpectedChar),

            (CSVState::ExpectLF, LF) => Ok(CSVState::Start),
            (CSVState::ExpectLF, _) => Err(ErrorType::ExpectedLF),

            (CSVState::Error, LF) => Ok(CSVState::Start),
            (CSVState::Error, _) => Ok(CSVState::Error),
        }
    }
}

#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct CSVError {
    pub line: u32,
    pub col: u32,
    pub error_type: ErrorType,
}

impl fmt::Display for CSVError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{} {}", self.line, self.col, self.error_type)
    }
}

pub fn csv_report(reader: impl Read) -> impl Iterator<Item = CSVError> {
    let mut line = 1;
    let mut col = 0;
    let mut state = CSVState::Start;

    reader.bytes().filter_map(move |b| {
        let byte = b.unwrap();

        match state.parse_byte(byte) {
            Ok(new_state) => {
                state = new_state;
                if byte == LF {
                    line += 1;
                    col = 0;
                } else {
                    col += 1;
                }
                None
            }
            Err(error_type) => {
                let err = CSVError {line, col, error_type};
                if byte == LF {
                    line += 1;
                    col = 0;
                } else {
                    col += 1;
                };
                state = match err.error_type {
                    ErrorType::UnexpectedEOL => CSVState::Start,
                    _ => CSVState::Error,
                };
                Some(err)
            }
        }
    })
}

#[cfg(test)]
mod tests {
    use super::{csv_report, CSVError, ErrorType};

    #[test]
    fn finds_errors_in_csv() {
        use std::fs::File;

        let mut file = File::open("tests/test.csv").unwrap();

        let mut report = csv_report(&mut file);

        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 2,
                col: 13,
                error_type: ErrorType::UnexpectedChar,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 3,
                col: 28,
                error_type: ErrorType::UnexpectedEOL,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 5,
                col: 31,
                error_type: ErrorType::UnexpectedEOL,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 8,
                col: 14,
                error_type: ErrorType::UnexpectedChar,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 11,
                col: 39,
                error_type: ErrorType::UnexpectedEOL,
            })
        );
        assert_eq!(
            report.next(),
            Some(CSVError {
                line: 12,
                col: 28,
                error_type: ErrorType::UnexpectedEOL,
            })
        );
        assert_eq!(report.next(), None);
    }
}
<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> usize {
    decompressed_length(input)
}

pub fn decompressed_length(input: &str) -> usize {
    let mut chars = input.chars();
    let mut decompressed_length = 0;

    while let Some(c) = chars.next() {
        if c == '(' {
            let mut num_chars = String::new();
            let mut next_char = chars.next().expect("nothing after open paren");
            while next_char != 'x' {
                num_chars.push(next_char);
                next_char = chars.next().expect("nothing after open paren");
            }
            let num_chars: usize = num_chars.parse().expect("couldn't parse number of chars");

            let mut num_times = String::new();

            next_char = chars.next().expect("nothing after x");
            while next_char != ')' {
                num_times.push(next_char);
                next_char = chars.next().expect("nothing after x");
            }
            let num_times: usize = num_times.parse().expect("couldn't parse number of times");

            for _ in 0..num_chars {
                chars.next();
            }
            decompressed_length += num_chars * num_times;
        }
        else {
            decompressed_length += 1;
        }
    }
    decompressed_length
}

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

    #[test]
    fn no_change() {
        assert_eq!(decompressed_length("ADVENT"), 6);
    }

    #[test]
    fn one_char() {
        assert_eq!(decompressed_length("A(1x5)BC"), 7);
    }

    #[test]
    fn three_chars() {
        assert_eq!(decompressed_length("(3x3)XYZ"), 9);
    }

    #[test]
    fn two_chars_twice() {
        assert_eq!(decompressed_length("A(2x2)BCD(2x2)EFG"), 11);
    }
    #[test]
    fn no_double_processing() {
        assert_eq!(decompressed_length("(6x1)(1x3)A"), 6);
    }
    #[test]
    fn another_no_double_processing() {
        assert_eq!(decompressed_length("X(8x2)(3x3)ABCY"), 18);
    }
}
<commit_msg>Update the tests for part 2<commit_after>
pub fn puzzle(input: &str) -> usize {
    decompressed_length(input)
}

pub fn decompressed_length(input: &str) -> usize {
    let mut chars = input.chars();
    let mut decompressed_length = 0;

    while let Some(c) = chars.next() {
        if c == '(' {
            let mut num_chars = String::new();
            let mut next_char = chars.next().expect("nothing after open paren");
            while next_char != 'x' {
                num_chars.push(next_char);
                next_char = chars.next().expect("nothing after open paren");
            }
            let num_chars: usize = num_chars.parse().expect("couldn't parse number of chars");

            let mut num_times = String::new();

            next_char = chars.next().expect("nothing after x");
            while next_char != ')' {
                num_times.push(next_char);
                next_char = chars.next().expect("nothing after x");
            }
            let num_times: usize = num_times.parse().expect("couldn't parse number of times");

            for _ in 0..num_chars {
                chars.next();
            }
            decompressed_length += num_chars * num_times;
        }
        else {
            decompressed_length += 1;
        }
    }
    decompressed_length
}

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

    #[test]
    fn no_change() {
        assert_eq!(decompressed_length("ADVENT"), 6);
    }

    #[test]
    fn one_char() {
        assert_eq!(decompressed_length("A(1x5)BC"), 7);
    }

    #[test]
    fn three_chars() {
        assert_eq!(decompressed_length("(3x3)XYZ"), 9);
    }

    #[test]
    fn decompressed_twice() {
        assert_eq!(decompressed_length("X(8x2)(3x3)ABCY"), 20);
    }

    #[test]
    fn lots_of_a() {
        assert_eq!(decompressed_length("(27x12)(20x12)(13x14)(7x10)(1x12)A"), 241920);
    }

    #[test]
    fn variety() {
        assert_eq!(decompressed_length("(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"), 445);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate libc;

use std::fmt;
use std::ptr;
use std::str;

type HttpCallback = extern fn(*mut HttpParser) -> *mut libc::c_int;
type HttpDataCallback = extern fn(*mut HttpParser, *const u32, libc::size_t) -> *mut libc::c_int;

#[repr(C)]
#[derive(Clone, Copy)]
enum ParserType {
    HttpRequest,
    HttpResponse,
    HttpBoth
}

#[repr(C)]
struct HttpParser {
    // Private Interface
    _internal_state: libc::uint32_t,
    _nread: libc::uint32_t,
    _content_length: libc::uint64_t,

    // Read-Only
    http_major: libc::c_ushort,
    http_minor: libc::c_ushort,
    _extended_status: libc::uint32_t,

    // Public Interface
    data: *mut libc::c_void
}

impl HttpParser {
    fn new() -> HttpParser {
        HttpParser {
            _internal_state: 0,
            _nread: 0,
            _content_length: 0,
            _extended_status: 0,
            http_major: 0,
            http_minor: 0,
            data: 0 as *mut libc::c_void
        }
    }

    fn status_code(&self) -> u16 {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return (flags & 0xFFFF) as u16;
        }
    }

    fn method_code(&self) -> u8 {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return ((flags >> 16) & 0xFF) as u8;
        }
    }

    fn http_errno(&self) -> u8 {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return ((flags >> 24) & 0x7F) as u8;
        }
    }

    fn upgrade(&self) -> bool {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return ((flags >> 31) & 0x01) == 1;
        }
    }

    fn http_method_str(&self) -> &str {
        unsafe {
            let method_str = http_method_str(self.method_code());
            let buf = std::ffi::CStr::from_ptr(method_str);
            return str::from_utf8(buf.to_bytes()).unwrap();
        }
    }

    fn http_errno_name(&self) -> &str {
        unsafe {
            let method_str = http_errno_name(self.http_errno());
            let buf = std::ffi::CStr::from_ptr(method_str);
            return str::from_utf8(buf.to_bytes()).unwrap();
        }
    }

    fn http_errno_description(&self) -> &str {
        unsafe {
            let method_str = http_errno_description(self.http_errno());
            let buf = std::ffi::CStr::from_ptr(method_str);
            return str::from_utf8(buf.to_bytes()).unwrap();
        }
    }
}

impl fmt::Debug for HttpParser {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        return write!(fmt, "status_code: {}\n\
                            method: 0x{:X}, {}\n\
                            errno: 0x{:X}, {}, {}\n\
                            upgrade: {}\n\
                            http_version: {}.{}",
                      self.status_code(), self.method_code(), self.http_method_str(), self.http_errno(), self.http_errno_name(), self.http_errno_description(), self.upgrade(), self.http_major, self.http_minor);
    }
}

#[repr(C)]
struct HttpParserSettings {
    on_message_begin: HttpCallback,
    on_url: HttpDataCallback,
    on_status: HttpDataCallback,
    on_header_field: HttpDataCallback,
    on_header_value: HttpDataCallback,
    on_headers_complete: HttpCallback,
    on_body: HttpDataCallback,
    on_message_complete: HttpCallback,
    on_chunk_header: HttpCallback,
    on_chunk_complete: HttpCallback
}

#[inline]
unsafe fn unwrap_parser<'a>(http: *mut HttpParser) -> &'a mut Parser<'a> {
    return &mut *((*http).data as *mut Parser);
}

macro_rules! notify_fn_wrapper {
    ( $callback:ident ) => ({
        extern "C" fn $callback(http: *mut HttpParser) -> *mut libc::c_int {
            unsafe {
                unwrap_parser(http).handler.$callback();
            };
            return 0 as *mut libc::c_int;
        };
        $callback
    });
}

macro_rules! data_fn_wrapper {
    ( $callback:ident ) => ({
        extern "C" fn $callback(http: *mut HttpParser, data: *const u32, size: libc::size_t) -> *mut libc::c_int {
            unsafe {
                let mut dst = Vec::<u8>::with_capacity(size as usize);
                dst.set_len(size as usize);
                ptr::copy(data as *const u8, dst.as_mut_ptr(), size as usize);

                let data = String::from_utf8(dst).unwrap();

                unwrap_parser(http).handler.$callback(&data);
            };
            return 0 as *mut libc::c_int;
        };

        $callback
    });
}

static CALLBACK_WRAPPERS: HttpParserSettings = HttpParserSettings {
    on_url: data_fn_wrapper!(on_url),
    on_message_begin: notify_fn_wrapper!(on_message_begin),
    on_status: data_fn_wrapper!(on_status),
    on_header_field: data_fn_wrapper!(on_header_field),
    on_header_value: data_fn_wrapper!(on_header_value),
    on_headers_complete: notify_fn_wrapper!(on_headers_complete),
    on_body: data_fn_wrapper!(on_body),
    on_message_complete: notify_fn_wrapper!(on_message_complete),
    on_chunk_header: notify_fn_wrapper!(on_chunk_header),
    on_chunk_complete: notify_fn_wrapper!(on_chunk_complete)
};

extern "C" {
    fn http_parser_version() -> u32;
    fn http_parser_init(parser: *mut HttpParser, parser_type: ParserType);
    fn http_parser_settings_init(settings: *mut HttpParserSettings);
    fn http_parser_execute(parser: *mut HttpParser, settings: *const HttpParserSettings, data: *const u8, len: libc::size_t) -> libc::size_t;
    fn http_method_str(method_code: u8) -> *const libc::c_char;
    fn http_errno_name(http_errno: u8) -> *const libc::c_char;
    fn http_errno_description(http_errno: u8) -> *const libc::c_char;

    // Helper function to predictably use aligned bit-field struct
    fn http_get_struct_flags(parser: *const HttpParser) -> u32;
    fn http_content_length(parser: *const HttpParser) -> u64;
}

// High level Rust interface
pub trait ParserHandler {
    fn on_url(&self, &String) { }
    fn on_status(&self, &String) { }
    fn on_header_field(&self, &String) { }
    fn on_header_value(&self, &String) { }
    fn on_body(&self, &String) { }
    fn on_message_begin(&self) { }
    fn on_headers_complete(&self) { }
    fn on_message_complete(&self) { }
    fn on_chunk_header(&self) { }
    fn on_chunk_complete(&self) { }
}

pub struct Parser<'a> {
    handler: &'a ParserHandler,
    state: HttpParser,
    parser_type: ParserType
}

impl<'a> Parser<'a> {
    pub fn response(handler: &'a ParserHandler) -> Parser<'a> {
        Parser {
            handler: handler,
            state: HttpParser::new(),
            parser_type: ParserType::HttpResponse
        }
    }

    pub fn request(handler: &'a ParserHandler) -> Parser<'a> {
        Parser {
            handler: handler,
            state: HttpParser::new(),
            parser_type: ParserType::HttpRequest
        }
    }

    pub fn request_and_response(handler: &'a ParserHandler) -> Parser<'a> {
        Parser {
            handler: handler,
            state: HttpParser::new(),
            parser_type: ParserType::HttpBoth
        }
    }

    pub fn http_version(&self) -> (u16, u16) { return (self.state.http_major, self.state.http_minor) }
    pub fn http_status_code(&self) -> u16 { return self.state.status_code(); }
    pub fn is_upgrade(&self) -> bool { return self.state.upgrade() }
    pub fn http_method(&self) -> &str { return self.state.http_method_str(); }
}

pub fn parse(parser: &mut Parser, data: &[u8]) -> usize {
    unsafe {
        http_parser_init(&mut parser.state as *mut _, parser.parser_type);

        parser.state.data = &mut (*parser) as *mut _ as *mut libc::c_void;

        return http_parser_execute(&mut parser.state as *mut _,
                                         &CALLBACK_WRAPPERS as *const _,
                                         data.as_ptr(),
                                         data.len() as u64) as usize;
    }
}

pub fn version() -> String {
    unsafe {
        let v = http_parser_version();

        let major = (v >> 16) & 255;
        let minor = (v >> 8) & 255;
        let patch = v & 255;

        return fmt::format(format_args!("{}.{}.{}", major, minor, patch));
    }
}

#[test]
fn test_version() {
    assert_eq!("2.5.0", version());
}

#[test]
fn test_request_parser() {
    struct TestRequestParser;
    impl ParserHandler for TestRequestParser {
        fn on_url(&self, url: &String) { assert_eq!("/say_hello", url); }
        fn on_header_field(&self, hdr: &String) { assert!(hdr == "Host" || hdr == "Content-Length"); }
        fn on_header_value(&self, val: &String) { assert!(val == "localhost.localdomain" || val == "11"); }
        fn on_body(&self, body: &String) { assert_eq!(body, "Hello world"); }
    }

    let req = "POST /say_hello HTTP/1.1\r\nContent-Length: 11\r\nHost: localhost.localdomain\r\n\r\nHello world";

    let handler = TestRequestParser;
    let mut parser = Parser::request(&handler);
    let parsed = parse(&mut parser, req.as_bytes());

    assert!(parsed > 0);
    assert_eq!((1, 1), parser.http_version());
    assert_eq!("POST", parser.http_method());
}

#[test]
fn test_response_parser() {
    struct TestResponseParser;
    impl ParserHandler for TestResponseParser {
        fn on_status(&self, status: &String) { assert_eq!("OK", status); }
        fn on_header_field(&self, hdr: &String) { assert_eq!("Host", hdr); }
        fn on_header_value(&self, val: &String) { assert_eq!("localhost.localdomain", val); }
    }

    let req = "HTTP/1.1 200 OK\r\nHost: localhost.localdomain\r\n\r\n";

    let handler = TestResponseParser;
    let mut parser = Parser::response(&handler);
    let parsed = parse(&mut parser, req.as_bytes());

    assert!(parsed > 0);
    assert_eq!((1, 1), parser.http_version());
    assert_eq!(200, parser.http_status_code());
}

#[test]
fn test_ws_upgrade() {
    struct DummyHandler;
    impl ParserHandler for DummyHandler {};

    let req = "GET / HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n";

    let handler = DummyHandler;
    let mut parser = Parser::request(&handler);
    parse(&mut parser, req.as_bytes());

    assert_eq!(parser.is_upgrade(), true);
}
<commit_msg>Removed redundant extern func<commit_after>#![allow(dead_code)]
extern crate libc;

use std::fmt;
use std::ptr;
use std::str;

type HttpCallback = extern fn(*mut HttpParser) -> *mut libc::c_int;
type HttpDataCallback = extern fn(*mut HttpParser, *const u32, libc::size_t) -> *mut libc::c_int;

#[repr(C)]
#[derive(Clone, Copy)]
enum ParserType {
    HttpRequest,
    HttpResponse,
    HttpBoth
}

#[repr(C)]
struct HttpParser {
    // Private Interface
    _internal_state: libc::uint32_t,
    _nread: libc::uint32_t,
    _content_length: libc::uint64_t,

    // Read-Only
    http_major: libc::c_ushort,
    http_minor: libc::c_ushort,
    _extended_status: libc::uint32_t,

    // Public Interface
    data: *mut libc::c_void
}

impl HttpParser {
    fn new() -> HttpParser {
        HttpParser {
            _internal_state: 0,
            _nread: 0,
            _content_length: 0,
            _extended_status: 0,
            http_major: 0,
            http_minor: 0,
            data: 0 as *mut libc::c_void
        }
    }

    fn status_code(&self) -> u16 {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return (flags & 0xFFFF) as u16;
        }
    }

    fn method_code(&self) -> u8 {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return ((flags >> 16) & 0xFF) as u8;
        }
    }

    fn http_errno(&self) -> u8 {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return ((flags >> 24) & 0x7F) as u8;
        }
    }

    fn upgrade(&self) -> bool {
        unsafe {
            let flags = http_get_struct_flags(self as *const _);
            return ((flags >> 31) & 0x01) == 1;
        }
    }

    fn http_method_str(&self) -> &str {
        unsafe {
            let method_str = http_method_str(self.method_code());
            let buf = std::ffi::CStr::from_ptr(method_str);
            return str::from_utf8(buf.to_bytes()).unwrap();
        }
    }

    fn http_errno_name(&self) -> &str {
        unsafe {
            let method_str = http_errno_name(self.http_errno());
            let buf = std::ffi::CStr::from_ptr(method_str);
            return str::from_utf8(buf.to_bytes()).unwrap();
        }
    }

    fn http_errno_description(&self) -> &str {
        unsafe {
            let method_str = http_errno_description(self.http_errno());
            let buf = std::ffi::CStr::from_ptr(method_str);
            return str::from_utf8(buf.to_bytes()).unwrap();
        }
    }
}

impl fmt::Debug for HttpParser {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        return write!(fmt, "status_code: {}\n\
                            method: 0x{:X}, {}\n\
                            errno: 0x{:X}, {}, {}\n\
                            upgrade: {}\n\
                            http_version: {}.{}",
                      self.status_code(), self.method_code(), self.http_method_str(), self.http_errno(), self.http_errno_name(), self.http_errno_description(), self.upgrade(), self.http_major, self.http_minor);
    }
}

#[repr(C)]
struct HttpParserSettings {
    on_message_begin: HttpCallback,
    on_url: HttpDataCallback,
    on_status: HttpDataCallback,
    on_header_field: HttpDataCallback,
    on_header_value: HttpDataCallback,
    on_headers_complete: HttpCallback,
    on_body: HttpDataCallback,
    on_message_complete: HttpCallback,
    on_chunk_header: HttpCallback,
    on_chunk_complete: HttpCallback
}

#[inline]
unsafe fn unwrap_parser<'a>(http: *mut HttpParser) -> &'a mut Parser<'a> {
    return &mut *((*http).data as *mut Parser);
}

macro_rules! notify_fn_wrapper {
    ( $callback:ident ) => ({
        extern "C" fn $callback(http: *mut HttpParser) -> *mut libc::c_int {
            unsafe {
                unwrap_parser(http).handler.$callback();
            };
            return 0 as *mut libc::c_int;
        };
        $callback
    });
}

macro_rules! data_fn_wrapper {
    ( $callback:ident ) => ({
        extern "C" fn $callback(http: *mut HttpParser, data: *const u32, size: libc::size_t) -> *mut libc::c_int {
            unsafe {
                let mut dst = Vec::<u8>::with_capacity(size as usize);
                dst.set_len(size as usize);
                ptr::copy(data as *const u8, dst.as_mut_ptr(), size as usize);

                let data = String::from_utf8(dst).unwrap();

                unwrap_parser(http).handler.$callback(&data);
            };
            return 0 as *mut libc::c_int;
        };

        $callback
    });
}

static CALLBACK_WRAPPERS: HttpParserSettings = HttpParserSettings {
    on_url: data_fn_wrapper!(on_url),
    on_message_begin: notify_fn_wrapper!(on_message_begin),
    on_status: data_fn_wrapper!(on_status),
    on_header_field: data_fn_wrapper!(on_header_field),
    on_header_value: data_fn_wrapper!(on_header_value),
    on_headers_complete: notify_fn_wrapper!(on_headers_complete),
    on_body: data_fn_wrapper!(on_body),
    on_message_complete: notify_fn_wrapper!(on_message_complete),
    on_chunk_header: notify_fn_wrapper!(on_chunk_header),
    on_chunk_complete: notify_fn_wrapper!(on_chunk_complete)
};

extern "C" {
    fn http_parser_version() -> u32;
    fn http_parser_init(parser: *mut HttpParser, parser_type: ParserType);
    fn http_parser_settings_init(settings: *mut HttpParserSettings);
    fn http_parser_execute(parser: *mut HttpParser, settings: *const HttpParserSettings, data: *const u8, len: libc::size_t) -> libc::size_t;
    fn http_method_str(method_code: u8) -> *const libc::c_char;
    fn http_errno_name(http_errno: u8) -> *const libc::c_char;
    fn http_errno_description(http_errno: u8) -> *const libc::c_char;

    // Helper function to predictably use aligned bit-field struct
    fn http_get_struct_flags(parser: *const HttpParser) -> u32;
}

// High level Rust interface
pub trait ParserHandler {
    fn on_url(&self, &String) { }
    fn on_status(&self, &String) { }
    fn on_header_field(&self, &String) { }
    fn on_header_value(&self, &String) { }
    fn on_body(&self, &String) { }
    fn on_message_begin(&self) { }
    fn on_headers_complete(&self) { }
    fn on_message_complete(&self) { }
    fn on_chunk_header(&self) { }
    fn on_chunk_complete(&self) { }
}

pub struct Parser<'a> {
    handler: &'a ParserHandler,
    state: HttpParser,
    parser_type: ParserType
}

impl<'a> Parser<'a> {
    pub fn response(handler: &'a ParserHandler) -> Parser<'a> {
        Parser {
            handler: handler,
            state: HttpParser::new(),
            parser_type: ParserType::HttpResponse
        }
    }

    pub fn request(handler: &'a ParserHandler) -> Parser<'a> {
        Parser {
            handler: handler,
            state: HttpParser::new(),
            parser_type: ParserType::HttpRequest
        }
    }

    pub fn request_and_response(handler: &'a ParserHandler) -> Parser<'a> {
        Parser {
            handler: handler,
            state: HttpParser::new(),
            parser_type: ParserType::HttpBoth
        }
    }

    pub fn http_version(&self) -> (u16, u16) { return (self.state.http_major, self.state.http_minor) }
    pub fn http_status_code(&self) -> u16 { return self.state.status_code(); }
    pub fn is_upgrade(&self) -> bool { return self.state.upgrade() }
    pub fn http_method(&self) -> &str { return self.state.http_method_str(); }
}

pub fn parse(parser: &mut Parser, data: &[u8]) -> usize {
    unsafe {
        http_parser_init(&mut parser.state as *mut _, parser.parser_type);

        parser.state.data = &mut (*parser) as *mut _ as *mut libc::c_void;

        return http_parser_execute(&mut parser.state as *mut _,
                                         &CALLBACK_WRAPPERS as *const _,
                                         data.as_ptr(),
                                         data.len() as u64) as usize;
    }
}

pub fn version() -> String {
    unsafe {
        let v = http_parser_version();

        let major = (v >> 16) & 255;
        let minor = (v >> 8) & 255;
        let patch = v & 255;

        return fmt::format(format_args!("{}.{}.{}", major, minor, patch));
    }
}

#[test]
fn test_version() {
    assert_eq!("2.5.0", version());
}

#[test]
fn test_request_parser() {
    struct TestRequestParser;
    impl ParserHandler for TestRequestParser {
        fn on_url(&self, url: &String) { assert_eq!("/say_hello", url); }
        fn on_header_field(&self, hdr: &String) { assert!(hdr == "Host" || hdr == "Content-Length"); }
        fn on_header_value(&self, val: &String) { assert!(val == "localhost.localdomain" || val == "11"); }
        fn on_body(&self, body: &String) { assert_eq!(body, "Hello world"); }
    }

    let req = "POST /say_hello HTTP/1.1\r\nContent-Length: 11\r\nHost: localhost.localdomain\r\n\r\nHello world";

    let handler = TestRequestParser;
    let mut parser = Parser::request(&handler);
    let parsed = parse(&mut parser, req.as_bytes());

    assert!(parsed > 0);
    assert_eq!((1, 1), parser.http_version());
    assert_eq!("POST", parser.http_method());
}

#[test]
fn test_response_parser() {
    struct TestResponseParser;
    impl ParserHandler for TestResponseParser {
        fn on_status(&self, status: &String) { assert_eq!("OK", status); }
        fn on_header_field(&self, hdr: &String) { assert_eq!("Host", hdr); }
        fn on_header_value(&self, val: &String) { assert_eq!("localhost.localdomain", val); }
    }

    let req = "HTTP/1.1 200 OK\r\nHost: localhost.localdomain\r\n\r\n";

    let handler = TestResponseParser;
    let mut parser = Parser::response(&handler);
    let parsed = parse(&mut parser, req.as_bytes());

    assert!(parsed > 0);
    assert_eq!((1, 1), parser.http_version());
    assert_eq!(200, parser.http_status_code());
}

#[test]
fn test_ws_upgrade() {
    struct DummyHandler;
    impl ParserHandler for DummyHandler {};

    let req = "GET / HTTP/1.1\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n";

    let handler = DummyHandler;
    let mut parser = Parser::request(&handler);
    parse(&mut parser, req.as_bytes());

    assert_eq!(parser.is_upgrade(), true);
}
<|endoftext|>