<commit_before>use errors::crypto::CryptoError;
use services::crypto::anoncreds::constants::{
    LARGE_MASTER_SECRET,
    LARGE_PRIME,
    LARGE_VPRIME_PRIME
};
use services::crypto::anoncreds::types::{
    Attribute,
    ByteOrder,
    PublicKey,
    Schema,
    SecretKey
};
use services::crypto::helpers::{
    random_qr,
    bitwise_or_big_int,
    get_hash_as_int
};
use services::crypto::wrappers::bn::BigNumber;

use std::collections::HashMap;

pub struct Issuer {

}

impl Issuer {
    pub fn new() -> Issuer {
        Issuer {}
    }
    pub fn generate_keys(&self, schema: &Schema) -> Result<((PublicKey, SecretKey)), CryptoError> {
        //(Issuer::_generate_keys(&schema));
        unimplemented!();
    }

    pub fn create_claim() {

    }

    fn _generate_keys(schema: &Schema) -> Result<(PublicKey, SecretKey), CryptoError> {
        let bn = try!(BigNumber::new());
        let p = try!(bn.generate_safe_prime(LARGE_PRIME));
        let q = try!(bn.generate_safe_prime(LARGE_PRIME));

        let mut p_prime = try!(p.sub(&try!(BigNumber::from_u32(1))));
        try!(p_prime.div_word(2));

        let mut q_prime = try!(q.sub(&try!(BigNumber::from_u32(1))));
        try!(q_prime.div_word(2));

        let n = try!(p.mul(&q, None));
        let s = try!(random_qr(&n));
        let xz = try!(Issuer::_gen_x(&p_prime, &q_prime));
        let mut r: HashMap<String, BigNumber> = HashMap::new();

        for attribute in &schema.attribute_names {
            let random = try!(Issuer::_gen_x(&p_prime, &q_prime));
            r.insert(attribute.to_string(), try!(s.mod_exp(&random, &n, None)));
        }

        let z = try!(s.mod_exp(&xz, &n, None));

        let rms = try!(s.mod_exp(&try!(Issuer::_gen_x(&p_prime, &q_prime)), &n, None));
        let rctxt = try!(s.mod_exp(&try!(Issuer::_gen_x(&p_prime, &q_prime)), &n, None));
        Ok((
            PublicKey {
                n: n,
                rms: rms,
                rctxt: rctxt,
                r: r,
                s: s,
                z: z
            },
            SecretKey {
                p: p_prime,
                q: q_prime
            }
        ))
    }

    fn _generate_revocation_keys() {

    }

    fn _issuer_primary_claim(&self) {

    }

    //    fn issue_primary_claim(attributes: &Vec<AttributeType>, u: &BigNum, accumulator_id: &str, user_id: &str) {
    //        let mut ctx = BigNumContext::new().unwrap();
    //        let vprimeprime = AnoncredsService::generate_vprimeprime();
    //        let (mut e_start, mut e_end) = (BigNum::new().unwrap(), BigNum::new().unwrap());
    //        e_start.exp(&BigNum::from_u32(2).unwrap(), &BigNum::from_u32(LARGE_E_START as u32).unwrap(), &mut ctx);
    //        e_end.exp(&BigNum::from_u32(2).unwrap(), &BigNum::from_u32(LARGE_E_END_RANGE as u32).unwrap(), &mut ctx);
    //        e_end = &e_start + &e_end;
    //        let e = AnoncredsService::generate_prime_in_range(&e_start, &e_end).unwrap();
    //        let encoded_attributes = AnoncredsService::encode_attributes(attributes);
    //        let m2 = AnoncredsService::generate_context(accumulator_id, user_id);
    //    }

    fn _generate_context_attribute(accumulator_id: &String, user_id: &String) -> Result<BigNumber, CryptoError> {
        let accumulator_id_encoded = try!(Issuer::_encode_attribute(&accumulator_id, ByteOrder::Little));
        let user_id_encoded = try!(Issuer::_encode_attribute(&user_id, ByteOrder::Little));
        let mut s = vec![try!(bitwise_or_big_int(
            &try!(BigNumber::from_dec(&accumulator_id_encoded)),
            &try!(BigNumber::from_dec(&user_id_encoded))
        ))];
        let mut h = try!(get_hash_as_int(&mut s));
        let mut pow_2 = try!(BigNumber::from_u32(2));
        pow_2 = try!(pow_2.exp(&try!(BigNumber::from_u32(LARGE_MASTER_SECRET as u32)), None));
        h = try!(h.modulus(&pow_2, None));
        Ok(h)
    }

    fn _sign() {
        unimplemented!()
    }

    fn _encode_attribute(attribute: &str, byte_order: ByteOrder) -> Result<String, CryptoError> {
        let mut result = try!(BigNumber::hash(&attribute.as_bytes()));
        let index = result.iter().position(|&value| value == 0);
        if let Some(position) = index {
            result.truncate(position);
        }
        if let ByteOrder::Little = byte_order {
            result.reverse();
        }
        let encoded_attribute = try!(BigNumber::from_bytes(&result));
        Ok(try!(encoded_attribute.to_dec()).to_string())
    }

    fn _encode_attributes(attributes: &Vec<Attribute>) -> Result<HashMap<String, String>, CryptoError> {
        let mut encoded_attributes: HashMap<String, String> = HashMap::new();
        for i in attributes {
            if i.encode {
                encoded_attributes.insert(i.name.clone(), try!(Issuer::_encode_attribute(&i.value, ByteOrder::Big)));
            }
                else {
                    encoded_attributes.insert(i.name.clone(), i.value.clone());
                }
        }
        Ok(encoded_attributes)
    }

    fn _gen_x(p: &BigNumber, q: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut value = try!(p.mul(&q, None));
        try!(value.sub_word(3));

        let mut result = try!(value.rand_range());
        try!(result.add_word(2));
        Ok(result)
    }

    fn _generate_v_prime_prime() -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNumber::new());
        let a = try!(bn.rand(LARGE_VPRIME_PRIME));
        let mut b = try!(BigNumber::from_u32(2));
        b = try!(b.exp(&try!(BigNumber::from_u32((LARGE_VPRIME_PRIME - 1) as u32)), None));
        let v_prime_prime = try!(bitwise_or_big_int(&a, &b));
        Ok(v_prime_prime)
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn encode_attribute_works_short_hash() {
        let test_str = "Alexer5435";
        let test_answer = "62794";
        assert_eq!(test_answer, Issuer::_encode_attribute(test_str, ByteOrder::Big).unwrap());
    }

    #[test]
    fn encode_attribute_works_long_hash() {
        let test_str = "Alexer";
        let test_answer = "93838255634171043313693932530283701522875554780708470423762684802192372035729";
        assert_eq!(test_answer, Issuer::_encode_attribute(test_str, ByteOrder::Big).unwrap());
    }

    #[test]
    fn encode_attributes_works() {
        assert_eq!(mocks::get_encoded_attributes(), Issuer::_encode_attributes(&mocks::get_attributes()).unwrap());
    }

    #[test]
    fn generate_context_attribute_works() {
        let accumulator_id = "110".to_string();
        let user_id = "111".to_string();
        let answer = BigNumber::from_dec("59059690488564137142247698318091397258460906844819605876079330034815387295451").unwrap();
        let result = Issuer::_generate_context_attribute(&accumulator_id, &user_id).unwrap();
        assert_eq!(result, answer);
    }
}

mod mocks {
    use super::*;

    pub fn get_attributes() -> Vec<Attribute> {
        let attributes: Vec<Attribute> = vec![
            Attribute {
                name: "name".to_string(),
                value: "Alex".to_string(),
                encode: true
            },
            Attribute {
                name: "age".to_string(),
                value: "28".to_string(),
                encode: false
            },
            Attribute {
                name: "sex".to_string(),
                value: "male".to_string(),
                encode: true
            },
            Attribute {
                name: "height".to_string(),
                value: "175".to_string(),
                encode: false
            }
        ];
        attributes
    }

    pub fn get_encoded_attributes() -> HashMap<String, String> {
        let mut encoded_attributes: HashMap<String, String> = HashMap::new();
        encoded_attributes.insert("name".to_string(),
                                  "1139481716457488690172217916278103335".to_string());
        encoded_attributes.insert("age".to_string(), "28".to_string());
        encoded_attributes.insert(
            "sex".to_string(),
            "5944657099558967239210949258394887428692050081607692519917050011144233115103".to_string());
        encoded_attributes.insert("height".to_string(), "175".to_string());
        encoded_attributes
    }
}<commit_msg>added test for sign<commit_after>use errors::crypto::CryptoError;
use services::crypto::anoncreds::constants::{
    LARGE_MASTER_SECRET,
    LARGE_PRIME,
    LARGE_VPRIME_PRIME
};
use services::crypto::anoncreds::types::{
    Attribute,
    ByteOrder,
    PublicKey,
    Schema,
    SecretKey
};
use services::crypto::helpers::{
    random_qr,
    bitwise_or_big_int,
    get_hash_as_int
};
use services::crypto::wrappers::bn::BigNumber;

use std::collections::HashMap;

pub struct Issuer {

}

impl Issuer {
    pub fn new() -> Issuer {
        Issuer {}
    }
    pub fn generate_keys(&self, schema: &Schema) -> Result<((PublicKey, SecretKey)), CryptoError> {
        //(Issuer::_generate_keys(&schema));
        unimplemented!();
    }

    pub fn create_claim() {

    }

    fn _generate_keys(schema: &Schema) -> Result<(PublicKey, SecretKey), CryptoError> {
        let bn = try!(BigNumber::new());
        let p = try!(bn.generate_safe_prime(LARGE_PRIME));
        let q = try!(bn.generate_safe_prime(LARGE_PRIME));

        let mut p_prime = try!(p.sub(&try!(BigNumber::from_u32(1))));
        try!(p_prime.div_word(2));

        let mut q_prime = try!(q.sub(&try!(BigNumber::from_u32(1))));
        try!(q_prime.div_word(2));

        let n = try!(p.mul(&q, None));
        let s = try!(random_qr(&n));
        let xz = try!(Issuer::_gen_x(&p_prime, &q_prime));
        let mut r: HashMap<String, BigNumber> = HashMap::new();

        for attribute in &schema.attribute_names {
            let random = try!(Issuer::_gen_x(&p_prime, &q_prime));
            r.insert(attribute.to_string(), try!(s.mod_exp(&random, &n, None)));
        }

        let z = try!(s.mod_exp(&xz, &n, None));

        let rms = try!(s.mod_exp(&try!(Issuer::_gen_x(&p_prime, &q_prime)), &n, None));
        let rctxt = try!(s.mod_exp(&try!(Issuer::_gen_x(&p_prime, &q_prime)), &n, None));
        Ok((
            PublicKey {
                n: n,
                rms: rms,
                rctxt: rctxt,
                r: r,
                s: s,
                z: z
            },
            SecretKey {
                p: p_prime,
                q: q_prime
            }
        ))
    }

    fn _generate_revocation_keys() {

    }

    fn _issuer_primary_claim() {

    }

    //    fn issue_primary_claim(attributes: &Vec<AttributeType>, u: &BigNum, accumulator_id: &str, user_id: &str) {
    //        let mut ctx = BigNumContext::new().unwrap();
    //        let vprimeprime = AnoncredsService::generate_vprimeprime();
    //        let (mut e_start, mut e_end) = (BigNum::new().unwrap(), BigNum::new().unwrap());
    //        e_start.exp(&BigNum::from_u32(2).unwrap(), &BigNum::from_u32(LARGE_E_START as u32).unwrap(), &mut ctx);
    //        e_end.exp(&BigNum::from_u32(2).unwrap(), &BigNum::from_u32(LARGE_E_END_RANGE as u32).unwrap(), &mut ctx);
    //        e_end = &e_start + &e_end;
    //        let e = AnoncredsService::generate_prime_in_range(&e_start, &e_end).unwrap();
    //        let encoded_attributes = AnoncredsService::encode_attributes(attributes);
    //        let m2 = AnoncredsService::generate_context(accumulator_id, user_id);
    //    }

    fn _generate_context_attribute(accumulator_id: &String, user_id: &String) -> Result<BigNumber, CryptoError> {
        let accumulator_id_encoded = try!(Issuer::_encode_attribute(&accumulator_id, ByteOrder::Little));
        let user_id_encoded = try!(Issuer::_encode_attribute(&user_id, ByteOrder::Little));
        let mut s = vec![try!(bitwise_or_big_int(
            &try!(BigNumber::from_dec(&accumulator_id_encoded)),
            &try!(BigNumber::from_dec(&user_id_encoded))
        ))];
        let mut h = try!(get_hash_as_int(&mut s));
        let mut pow_2 = try!(BigNumber::from_u32(2));
        pow_2 = try!(pow_2.exp(&try!(BigNumber::from_u32(LARGE_MASTER_SECRET as u32)), None));
        h = try!(h.modulus(&pow_2, None));
        Ok(h)
    }

    fn _sign(public_key: &PublicKey, secret_key: &SecretKey, context_attribute: &BigNumber,
             attributes: &HashMap<String, String>, v: &BigNumber, u: &BigNumber, e: &BigNumber) {
        unimplemented!()
    }

    fn _encode_attribute(attribute: &str, byte_order: ByteOrder) -> Result<String, CryptoError> {
        let mut result = try!(BigNumber::hash(&attribute.as_bytes()));
        let index = result.iter().position(|&value| value == 0);
        if let Some(position) = index {
            result.truncate(position);
        }
        if let ByteOrder::Little = byte_order {
            result.reverse();
        }
        let encoded_attribute = try!(BigNumber::from_bytes(&result));
        Ok(try!(encoded_attribute.to_dec()).to_string())
    }

    fn _encode_attributes(attributes: &Vec<Attribute>) -> Result<HashMap<String, String>, CryptoError> {
        let mut encoded_attributes: HashMap<String, String> = HashMap::new();
        for i in attributes {
            if i.encode {
                encoded_attributes.insert(i.name.clone(), try!(Issuer::_encode_attribute(&i.value, ByteOrder::Big)));
            }
                else {
                    encoded_attributes.insert(i.name.clone(), i.value.clone());
                }
        }
        Ok(encoded_attributes)
    }

    fn _gen_x(p: &BigNumber, q: &BigNumber) -> Result<BigNumber, CryptoError> {
        let mut value = try!(p.mul(&q, None));
        try!(value.sub_word(3));

        let mut result = try!(value.rand_range());
        try!(result.add_word(2));
        Ok(result)
    }

    fn _generate_v_prime_prime() -> Result<BigNumber, CryptoError> {
        let bn = try!(BigNumber::new());
        let a = try!(bn.rand(LARGE_VPRIME_PRIME));
        let mut b = try!(BigNumber::from_u32(2));
        b = try!(b.exp(&try!(BigNumber::from_u32((LARGE_VPRIME_PRIME - 1) as u32)), None));
        let v_prime_prime = try!(bitwise_or_big_int(&a, &b));
        Ok(v_prime_prime)
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn encode_attribute_works_short_hash() {
        let test_str = "Alexer5435";
        let test_answer = "62794";
        assert_eq!(test_answer, Issuer::_encode_attribute(test_str, ByteOrder::Big).unwrap());
    }

    #[test]
    fn encode_attribute_works_long_hash() {
        let test_str = "Alexer";
        let test_answer = "93838255634171043313693932530283701522875554780708470423762684802192372035729";
        assert_eq!(test_answer, Issuer::_encode_attribute(test_str, ByteOrder::Big).unwrap());
    }

    #[test]
    fn encode_attributes_works() {
        assert_eq!(mocks::get_encoded_attributes(), Issuer::_encode_attributes(&mocks::get_attributes()).unwrap());
    }

    #[test]
    fn generate_context_attribute_works() {
        let accumulator_id = "110".to_string();
        let user_id = "111".to_string();
        let answer = BigNumber::from_dec("59059690488564137142247698318091397258460906844819605876079330034815387295451").unwrap();
        let result = Issuer::_generate_context_attribute(&accumulator_id, &user_id).unwrap();
        assert_eq!(result, answer);
    }

    #[test]
    fn sign_works() {
        //let public_key =
        //let secret_key =
        let context_attribute = BigNumber::from_dec("59059690488564137142247698318091397258460906844819605876079330034815387295451").unwrap();
        let attributes = mocks::get_encoded_attributes();
        let v = BigNumber::from_dec("5237513942984418438429595379849430501110274945835879531523435677101657022026899212054747703201026332785243221088006425007944260107143086435227014329174143861116260506019310628220538205630726081406862023584806749693647480787838708606386447727482772997839699379017499630402117304253212246286800412454159444495341428975660445641214047184934669036997173182682771745932646179140449435510447104436243207291913322964918630514148730337977117021619857409406144166574010735577540583316493841348453073326447018376163876048624924380855323953529434806898415857681702157369526801730845990252958130662749564283838280707026676243727830151176995470125042111348846500489265328810592848939081739036589553697928683006514398844827534478669492201064874941684905413964973517155382540340695991536826170371552446768460042588981089470261358687308").unwrap();
        let u = BigNumber::from_dec("72637991796589957272144423539998982864769854130438387485781642285237707120228376409769221961371420625002149758076600738245408098270501483395353213773728601101770725294535792756351646443825391806535296461087756781710547778467803194521965309091287301376623972321639262276779134586366620773325502044026364814032821517244814909708610356590687571152567177116075706850536899272749781370266769562695357044719529245223811232258752001942940813585440938291877640445002571323841625932424781535818087233087621479695522263178206089952437764196471098717335358765920438275944490561172307673744212256272352897964947435086824617146019").unwrap();
        let e = BigNumber::from_dec("259344723055062059907025491480697571938277889515152306249728583105665800713306759149981690559193987143012367913206299323899696942213235956742930214202955935602153431795703076242907").unwrap();
    }
}

mod mocks {
    use super::*;

    pub fn get_attributes() -> Vec<Attribute> {
        let attributes: Vec<Attribute> = vec![
            Attribute {
                name: "name".to_string(),
                value: "Alex".to_string(),
                encode: true
            },
            Attribute {
                name: "age".to_string(),
                value: "28".to_string(),
                encode: false
            },
            Attribute {
                name: "sex".to_string(),
                value: "male".to_string(),
                encode: true
            },
            Attribute {
                name: "height".to_string(),
                value: "175".to_string(),
                encode: false
            }
        ];
        attributes
    }

    pub fn get_encoded_attributes() -> HashMap<String, String> {
        let mut encoded_attributes: HashMap<String, String> = HashMap::new();
        encoded_attributes.insert("name".to_string(),
                                  "1139481716457488690172217916278103335".to_string());
        encoded_attributes.insert("age".to_string(), "28".to_string());
        encoded_attributes.insert(
            "sex".to_string(),
            "5944657099558967239210949258394887428692050081607692519917050011144233115103".to_string());
        encoded_attributes.insert("height".to_string(), "175".to_string());
        encoded_attributes
    }
}<|endoftext|>


<commit_before>extern crate mio;
use getopts::{Options,Matches};
use std::net::{SocketAddr,lookup_host,IpAddr};
use std::io::{BufStream,Write};
use std::old_io;

use self::mio::*;
use self::mio::net::tcp::*;
use self::mio::buf::{ByteBuf};
use self::mio::net::*;
use std::str::FromStr;
use std::net::ToSocketAddrs;

use std::thread;

const CLIENT: Token = Token(1);

struct ClientHandler {
    sock: NonBlock<TcpStream>
}

impl Handler for ClientHandler {
    type Timeout = usize;
    type Message = String;

    fn readable(&mut self, event_loop: &mut EventLoop<ClientHandler>, token: Token, _: ReadHint) {
        match token {
            CLIENT => {
                let mut read_buf = ByteBuf::mut_with_capacity(2048);
                match self.sock.read(&mut read_buf) {
                    Ok(None) => {
                        panic!("Read operation would block, bailing cuz this shouldn't happen.");
                    }
                    Ok(Some(r)) => {
                        // `_` would be the number of bytes read.
                        // `flip` will return a `ByteBuf` on which we can call
                        // `read_slice` to get the data available to be read.
                        // See http://carllerche.github.io/bytes/bytes/struct.ByteBuf.html
                        let mut buf = read_buf.flip();
                        let mut sl = [0; 2048];
                        buf.read_slice(&mut sl);
                        // Assuming what was written was encoded as UTF8, print what
                        // was read to STDOUT.
                        print!("{}", String::from_utf8(sl.to_vec()).unwrap());
                    }
                    Err(e) => {
                        // Probably because connection could not be established.
                        event_loop.shutdown();
                        panic!(e.to_string());
                    }
                }
            },
            _ => {
                panic!("unepxected token!".to_string());
            }
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<ClientHandler>, token: Token) {
        match token {
            CLIENT => {
                println!("should write");
            },
            _ => {
                panic!("unepxected token!".to_string());
            }
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<ClientHandler>, msg: String) {
        println!("got message: {}", msg);
    }
}

pub fn nc_connect(matches: &Matches) {
    let addr = parse_addr(matches);
    let sock = match addr.ip() {
        IpAddr::V4(..) => v4(),
        IpAddr::V6(..) => v6()
    }.unwrap();

    let mut event_loop = EventLoop::new().unwrap();

    match sock.connect(&addr) {
        Ok((stream, _)) => {
            let mut client = ClientHandler { sock: stream };
            event_loop.register(&client.sock, CLIENT).unwrap();
            let sender = event_loop.channel();
            thread::spawn(move || {
                readwrite_chan(&sender);
            });
            let _ = event_loop.run(&mut client);
        },
        Err(f) => {
            println!("exiting");
            // just exit
        }
    }
}

fn readwrite_chan(channel: &EventLoopSender<String>) {
    let mut stdin_reader = old_io::stdin();
    let mut read_buf = [0; 4096];
    println!("readwritechan");
    loop {
        // Have to block here, so we can't immediately terminate if server closes socket.
        match stdin_reader.read(&mut read_buf) {
            Ok(n) => {
                println!("read");
                let read = read_buf.slice_to(n);
                let byte_vec: Vec<u8> = read.to_vec();
                let message = String::from_utf8(byte_vec).unwrap();
                channel.send(message).unwrap();
            },
            Err(f) => {
                panic!(f.to_string());
            }
        }
    }
}

fn readwrite(stream: &TcpStream) {
    let mut buf_stream = BufStream::new(stream);
    let mut stdin_reader = old_io::stdin();
    let mut read_buf = [0, 4096];
    loop {
        // Have to block here, so we can't immediately terminate if server closes socket.
        match stdin_reader.read(&mut read_buf) {
            Ok(n) => {
                buf_stream.write_all(&read_buf.slice_to(n)).unwrap();
                match buf_stream.flush() {
                    Ok(_) => { /* */ },
                    Err(f) => {
                        println!("closed");
                        // other end closed socket
                        return;
                    }
                }
            },
            Err(f) => {
                panic!(f.to_string());
            }
        }
    }
}

// pretty ugly...
fn parse_addr(matches: &Matches) -> SocketAddr {
    let host = matches.free.get(0).unwrap();
    let port_string = matches.free.get(1).unwrap();
    let port: u16 = FromStr::from_str(port_string.as_slice()).unwrap();
    return (host.as_slice(), port).to_socket_addrs().unwrap().next().unwrap();
}
<commit_msg>writable handler not necessary -- writing to sock works, seemingly<commit_after>extern crate mio;
use getopts::{Options,Matches};
use std::net::{SocketAddr,lookup_host,IpAddr};
use std::io::{BufStream,Write};
use std::old_io;

use self::mio::*;
use self::mio::net::tcp::*;
use self::mio::buf::{ByteBuf};
use self::mio::net::*;
use std::str::FromStr;
use std::net::ToSocketAddrs;

use std::thread;

const CLIENT: Token = Token(1);

struct ClientHandler {
    sock: NonBlock<TcpStream>
}

impl Handler for ClientHandler {
    type Timeout = usize;
    type Message = String;

    fn readable(&mut self, event_loop: &mut EventLoop<ClientHandler>, token: Token, _: ReadHint) {
        match token {
            CLIENT => {
                let mut read_buf = ByteBuf::mut_with_capacity(2048);
                match self.sock.read(&mut read_buf) {
                    Ok(None) => {
                        panic!("Read operation would block, bailing cuz this shouldn't happen.");
                    }
                    Ok(Some(r)) => {
                        // `_` would be the number of bytes read.
                        // `flip` will return a `ByteBuf` on which we can call
                        // `read_slice` to get the data available to be read.
                        // See http://carllerche.github.io/bytes/bytes/struct.ByteBuf.html
                        let mut buf = read_buf.flip();
                        let mut sl = [0; 2048];
                        buf.read_slice(&mut sl);
                        // Assuming what was written was encoded as UTF8, print what
                        // was read to STDOUT.
                        print!("{}", String::from_utf8(sl.to_vec()).unwrap());
                    }
                    Err(e) => {
                        // Probably because connection could not be established.
                        event_loop.shutdown();
                        panic!(e.to_string());
                    }
                }
            },
            _ => {
                panic!("unepxected token!".to_string());
            }
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<ClientHandler>, msg: String) {
        self.sock.write_slice(msg.as_bytes()).unwrap();
    }
}

pub fn nc_connect(matches: &Matches) {
    let addr = parse_addr(matches);
    let sock = match addr.ip() {
        IpAddr::V4(..) => v4(),
        IpAddr::V6(..) => v6()
    }.unwrap();

    let mut event_loop = EventLoop::new().unwrap();

    match sock.connect(&addr) {
        Ok((stream, _)) => {
            let mut client = ClientHandler { sock: stream };
            event_loop.register(&client.sock, CLIENT).unwrap();
            let sender = event_loop.channel();
            thread::spawn(move || {
                readwrite_chan(&sender);
            });
            let _ = event_loop.run(&mut client);
        },
        Err(f) => {
            println!("exiting");
            // just exit
        }
    }
}

fn readwrite_chan(channel: &EventLoopSender<String>) {
    let mut stdin_reader = old_io::stdin();
    let mut read_buf = [0; 4096];
    println!("readwritechan");
    loop {
        // Have to block here, so we can't immediately terminate if server closes socket.
        match stdin_reader.read(&mut read_buf) {
            Ok(n) => {
                println!("read");
                let read = read_buf.slice_to(n);
                let byte_vec: Vec<u8> = read.to_vec();
                let message = String::from_utf8(byte_vec).unwrap();
                channel.send(message).unwrap();
            },
            Err(f) => {
                panic!(f.to_string());
            }
        }
    }
}

fn readwrite(stream: &TcpStream) {
    let mut buf_stream = BufStream::new(stream);
    let mut stdin_reader = old_io::stdin();
    let mut read_buf = [0, 4096];
    loop {
        // Have to block here, so we can't immediately terminate if server closes socket.
        match stdin_reader.read(&mut read_buf) {
            Ok(n) => {
                buf_stream.write_all(&read_buf.slice_to(n)).unwrap();
                match buf_stream.flush() {
                    Ok(_) => { /* */ },
                    Err(f) => {
                        println!("closed");
                        // other end closed socket
                        return;
                    }
                }
            },
            Err(f) => {
                panic!(f.to_string());
            }
        }
    }
}

// pretty ugly...
fn parse_addr(matches: &Matches) -> SocketAddr {
    let host = matches.free.get(0).unwrap();
    let port_string = matches.free.get(1).unwrap();
    let port: u16 = FromStr::from_str(port_string.as_slice()).unwrap();
    return (host.as_slice(), port).to_socket_addrs().unwrap().next().unwrap();
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! CSV Reader
//!
//! This CSV reader allows CSV files to be read into the Arrow memory model. Records are loaded in
//! batches and are then converted from row-based data to columnar data.
//!
//! Example:
//!
//! ```
//! use arrow::csv;
//! use arrow::datatypes::{DataType, Field, Schema};
//! use std::fs::File;
//! use std::sync::Arc;
//!
//! let schema = Schema::new(vec![
//!   Field::new("city", DataType::Utf8, false),
//!   Field::new("lat", DataType::Float64, false),
//!   Field::new("lng", DataType::Float64, false),
//! ]);
//!
//! let file = File::open("test/data/uk_cities.csv").unwrap();
//!
//! let mut csv = csv::Reader::new(file, Arc::new(schema), false, 1024, None);
//! let batch = csv.next().unwrap().unwrap();
//!```

use std::fs::File;
use std::io::BufReader;
use std::sync::Arc;

use array::{ArrayRef, BinaryArray};
use builder::{ArrayBuilder, ListArrayBuilder, PrimitiveArrayBuilder};
use datatypes::{DataType, Schema};
use error::{ArrowError, Result};
use record_batch::RecordBatch;

use csv_crate::{StringRecord, StringRecordsIntoIter};

/// CSV file reader
pub struct Reader {
    /// Explicit schema for the CSV file
    schema: Arc<Schema>,
    /// Optional projection for which columns to load (zero-based column indices)
    projection: Option<Vec<usize>>,
    /// File reader
    record_iter: StringRecordsIntoIter<BufReader<File>>,
    /// Batch size (number of records to load each time)
    batch_size: usize,
}

impl Reader {
    /// Create a new CsvReader
    pub fn new(
        file: File,
        schema: Arc<Schema>,
        has_headers: bool,
        batch_size: usize,
        projection: Option<Vec<usize>>,
    ) -> Self {
        let csv_reader = csv::ReaderBuilder::new()
            .has_headers(has_headers)
            .from_reader(BufReader::new(file));

        let record_iter = csv_reader.into_records();
        Reader {
            schema: schema.clone(),
            projection,
            record_iter,
            batch_size,
        }
    }
}

macro_rules! build_primitive_array {
    ($ROWS:expr, $COL_INDEX:expr, $TY:ty) => {{
        let mut builder = PrimitiveArrayBuilder::<$TY>::new($ROWS.len() as i64);
        for row_index in 0..$ROWS.len() {
            match $ROWS[row_index].get(*$COL_INDEX) {
                Some(s) if s.len() > 0 => builder.push(s.parse::<$TY>().unwrap()).unwrap(),
                _ => builder.push_null().unwrap(),
            }
        }
        Ok(Arc::new(builder.finish()) as ArrayRef)
    }};
}

impl Reader {
    /// Read the next batch of rows
    pub fn next(&mut self) -> Option<Result<RecordBatch>> {
        // read a batch of rows into memory
        let mut rows: Vec<StringRecord> = Vec::with_capacity(self.batch_size);
        for _ in 0..self.batch_size {
            match self.record_iter.next() {
                Some(Ok(r)) => {
                    rows.push(r);
                }
                Some(Err(_)) => {
                    return Some(Err(ArrowError::ParseError(
                        "Error reading CSV file".to_string(),
                    )));
                }
                None => break,
            }
        }

        // return early if no data was loaded
        if rows.is_empty() {
            return None;
        }

        let projection: Vec<usize> = match self.projection {
            Some(ref v) => v.clone(),
            None => self
                .schema
                .fields()
                .iter()
                .enumerate()
                .map(|(i, _)| i)
                .collect(),
        };

        let arrays: Result<Vec<ArrayRef>> = projection
            .iter()
            .map(|i| {
                let field = self.schema.field(*i);

                match field.data_type() {
                    &DataType::Boolean => build_primitive_array!(rows, i, bool),
                    &DataType::Int8 => build_primitive_array!(rows, i, i8),
                    &DataType::Int16 => build_primitive_array!(rows, i, i16),
                    &DataType::Int32 => build_primitive_array!(rows, i, i32),
                    &DataType::Int64 => build_primitive_array!(rows, i, i64),
                    &DataType::UInt8 => build_primitive_array!(rows, i, u8),
                    &DataType::UInt16 => build_primitive_array!(rows, i, u16),
                    &DataType::UInt32 => build_primitive_array!(rows, i, u32),
                    &DataType::UInt64 => build_primitive_array!(rows, i, u64),
                    &DataType::Float32 => build_primitive_array!(rows, i, f32),
                    &DataType::Float64 => build_primitive_array!(rows, i, f64),
                    &DataType::Utf8 => {
                        let mut values_builder: PrimitiveArrayBuilder<u8> =
                            PrimitiveArrayBuilder::<u8>::new(rows.len() as i64);
                        let mut list_builder = ListArrayBuilder::new(values_builder);
                        for row_index in 0..rows.len() {
                            match rows[row_index].get(*i) {
                                Some(s) => {
                                    list_builder.values().push_slice(s.as_bytes()).unwrap();
                                    list_builder.append(true).unwrap();
                                }
                                _ => {
                                    list_builder.append(false).unwrap();
                                }
                            }
                        }
                        Ok(Arc::new(BinaryArray::from(list_builder.finish())) as ArrayRef)
                    }
                    other => Err(ArrowError::ParseError(format!(
                        "Unsupported data type {:?}",
                        other
                    ))),
                }
            })
            .collect();

        match arrays {
            Ok(arr) => Some(Ok(RecordBatch::new(self.schema.clone(), arr))),
            Err(e) => Some(Err(e)),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use array::PrimitiveArray;
    use datatypes::Field;

    #[test]
    fn test_csv() {
        let schema = Schema::new(vec![
            Field::new("city", DataType::Utf8, false),
            Field::new("lat", DataType::Float64, false),
            Field::new("lng", DataType::Float64, false),
        ]);

        let file = File::open("test/data/uk_cities.csv").unwrap();

        let mut csv = Reader::new(file, Arc::new(schema), false, 1024, None);
        let batch = csv.next().unwrap().unwrap();
        assert_eq!(37, batch.num_rows());
        assert_eq!(3, batch.num_columns());

        // access data from a primitive array
        let lat = batch
            .column(1)
            .as_any()
            .downcast_ref::<PrimitiveArray<f64>>()
            .unwrap();
        assert_eq!(57.653484, lat.value(0));

        // access data from a string array (ListArray<u8>)
        let city = batch
            .column(0)
            .as_any()
            .downcast_ref::<BinaryArray>()
            .unwrap();

        let city_name: String = String::from_utf8(city.get_value(13).to_vec()).unwrap();

        assert_eq!("Aberdeen, Aberdeen City, UK", city_name);
    }

    #[test]
    fn test_csv_with_projection() {
        let schema = Schema::new(vec![
            Field::new("city", DataType::Utf8, false),
            Field::new("lat", DataType::Float64, false),
            Field::new("lng", DataType::Float64, false),
        ]);

        let file = File::open("test/data/uk_cities.csv").unwrap();

        let mut csv = Reader::new(file, Arc::new(schema), false, 1024, Some(vec![0, 1]));
        let batch = csv.next().unwrap().unwrap();
        assert_eq!(37, batch.num_rows());
        assert_eq!(2, batch.num_columns());
    }

    #[test]
    fn test_nulls() {
        let schema = Schema::new(vec![
            Field::new("c_int", DataType::UInt64, false),
            Field::new("c_float", DataType::Float32, false),
            Field::new("c_string", DataType::Utf8, false),
        ]);

        let file = File::open("test/data/null_test.csv").unwrap();

        let mut csv = Reader::new(file, Arc::new(schema), true, 1024, None);
        let batch = csv.next().unwrap().unwrap();

        assert_eq!(false, batch.column(1).is_null(0));
        assert_eq!(false, batch.column(1).is_null(1));
        assert_eq!(true, batch.column(1).is_null(2));
        assert_eq!(false, batch.column(1).is_null(3));
        assert_eq!(false, batch.column(1).is_null(4));
    }

}
<commit_msg>ARROW-3895: [Rust] csv::Reader now returns Result<Option> instead of Option<Result><commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! CSV Reader
//!
//! This CSV reader allows CSV files to be read into the Arrow memory model. Records are loaded in
//! batches and are then converted from row-based data to columnar data.
//!
//! Example:
//!
//! ```
//! use arrow::csv;
//! use arrow::datatypes::{DataType, Field, Schema};
//! use std::fs::File;
//! use std::sync::Arc;
//!
//! let schema = Schema::new(vec![
//!   Field::new("city", DataType::Utf8, false),
//!   Field::new("lat", DataType::Float64, false),
//!   Field::new("lng", DataType::Float64, false),
//! ]);
//!
//! let file = File::open("test/data/uk_cities.csv").unwrap();
//!
//! let mut csv = csv::Reader::new(file, Arc::new(schema), false, 1024, None);
//! let batch = csv.next().unwrap().unwrap();
//!```

use std::fs::File;
use std::io::BufReader;
use std::sync::Arc;

use array::{ArrayRef, BinaryArray};
use builder::{ArrayBuilder, ListArrayBuilder, PrimitiveArrayBuilder};
use datatypes::{DataType, Schema};
use error::{ArrowError, Result};
use record_batch::RecordBatch;

use csv_crate::{StringRecord, StringRecordsIntoIter};

/// CSV file reader
pub struct Reader {
    /// Explicit schema for the CSV file
    schema: Arc<Schema>,
    /// Optional projection for which columns to load (zero-based column indices)
    projection: Option<Vec<usize>>,
    /// File reader
    record_iter: StringRecordsIntoIter<BufReader<File>>,
    /// Batch size (number of records to load each time)
    batch_size: usize,
}

impl Reader {
    /// Create a new CsvReader
    pub fn new(
        file: File,
        schema: Arc<Schema>,
        has_headers: bool,
        batch_size: usize,
        projection: Option<Vec<usize>>,
    ) -> Self {
        let csv_reader = csv::ReaderBuilder::new()
            .has_headers(has_headers)
            .from_reader(BufReader::new(file));

        let record_iter = csv_reader.into_records();
        Reader {
            schema: schema.clone(),
            projection,
            record_iter,
            batch_size,
        }
    }
}

macro_rules! build_primitive_array {
    ($ROWS:expr, $COL_INDEX:expr, $TY:ty) => {{
        let mut builder = PrimitiveArrayBuilder::<$TY>::new($ROWS.len() as i64);
        for row_index in 0..$ROWS.len() {
            match $ROWS[row_index].get(*$COL_INDEX) {
                Some(s) if s.len() > 0 => builder.push(s.parse::<$TY>().unwrap()).unwrap(),
                _ => builder.push_null().unwrap(),
            }
        }
        Ok(Arc::new(builder.finish()) as ArrayRef)
    }};
}

impl Reader {
    /// Read the next batch of rows
    pub fn next(&mut self) -> Result<Option<RecordBatch>> {
        // read a batch of rows into memory
        let mut rows: Vec<StringRecord> = Vec::with_capacity(self.batch_size);
        for _ in 0..self.batch_size {
            match self.record_iter.next() {
                Some(Ok(r)) => {
                    rows.push(r);
                }
                Some(Err(_)) => {
                    return Err(ArrowError::ParseError("Error reading CSV file".to_string()));
                }
                None => break,
            }
        }

        // return early if no data was loaded
        if rows.is_empty() {
            return Ok(None);
        }

        let projection: Vec<usize> = match self.projection {
            Some(ref v) => v.clone(),
            None => self
                .schema
                .fields()
                .iter()
                .enumerate()
                .map(|(i, _)| i)
                .collect(),
        };

        let arrays: Result<Vec<ArrayRef>> = projection
            .iter()
            .map(|i| {
                let field = self.schema.field(*i);

                match field.data_type() {
                    &DataType::Boolean => build_primitive_array!(rows, i, bool),
                    &DataType::Int8 => build_primitive_array!(rows, i, i8),
                    &DataType::Int16 => build_primitive_array!(rows, i, i16),
                    &DataType::Int32 => build_primitive_array!(rows, i, i32),
                    &DataType::Int64 => build_primitive_array!(rows, i, i64),
                    &DataType::UInt8 => build_primitive_array!(rows, i, u8),
                    &DataType::UInt16 => build_primitive_array!(rows, i, u16),
                    &DataType::UInt32 => build_primitive_array!(rows, i, u32),
                    &DataType::UInt64 => build_primitive_array!(rows, i, u64),
                    &DataType::Float32 => build_primitive_array!(rows, i, f32),
                    &DataType::Float64 => build_primitive_array!(rows, i, f64),
                    &DataType::Utf8 => {
                        let mut values_builder: PrimitiveArrayBuilder<u8> =
                            PrimitiveArrayBuilder::<u8>::new(rows.len() as i64);
                        let mut list_builder = ListArrayBuilder::new(values_builder);
                        for row_index in 0..rows.len() {
                            match rows[row_index].get(*i) {
                                Some(s) => {
                                    list_builder.values().push_slice(s.as_bytes()).unwrap();
                                    list_builder.append(true).unwrap();
                                }
                                _ => {
                                    list_builder.append(false).unwrap();
                                }
                            }
                        }
                        Ok(Arc::new(BinaryArray::from(list_builder.finish())) as ArrayRef)
                    }
                    other => Err(ArrowError::ParseError(format!(
                        "Unsupported data type {:?}",
                        other
                    ))),
                }
            })
            .collect();

        match arrays {
            Ok(arr) => Ok(Some(RecordBatch::new(self.schema.clone(), arr))),
            Err(e) => Err(e),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use array::PrimitiveArray;
    use datatypes::Field;

    #[test]
    fn test_csv() {
        let schema = Schema::new(vec![
            Field::new("city", DataType::Utf8, false),
            Field::new("lat", DataType::Float64, false),
            Field::new("lng", DataType::Float64, false),
        ]);

        let file = File::open("test/data/uk_cities.csv").unwrap();

        let mut csv = Reader::new(file, Arc::new(schema), false, 1024, None);
        let batch = csv.next().unwrap().unwrap();
        assert_eq!(37, batch.num_rows());
        assert_eq!(3, batch.num_columns());

        // access data from a primitive array
        let lat = batch
            .column(1)
            .as_any()
            .downcast_ref::<PrimitiveArray<f64>>()
            .unwrap();
        assert_eq!(57.653484, lat.value(0));

        // access data from a string array (ListArray<u8>)
        let city = batch
            .column(0)
            .as_any()
            .downcast_ref::<BinaryArray>()
            .unwrap();

        let city_name: String = String::from_utf8(city.get_value(13).to_vec()).unwrap();

        assert_eq!("Aberdeen, Aberdeen City, UK", city_name);
    }

    #[test]
    fn test_csv_with_projection() {
        let schema = Schema::new(vec![
            Field::new("city", DataType::Utf8, false),
            Field::new("lat", DataType::Float64, false),
            Field::new("lng", DataType::Float64, false),
        ]);

        let file = File::open("test/data/uk_cities.csv").unwrap();

        let mut csv = Reader::new(file, Arc::new(schema), false, 1024, Some(vec![0, 1]));
        let batch = csv.next().unwrap().unwrap();
        assert_eq!(37, batch.num_rows());
        assert_eq!(2, batch.num_columns());
    }

    #[test]
    fn test_nulls() {
        let schema = Schema::new(vec![
            Field::new("c_int", DataType::UInt64, false),
            Field::new("c_float", DataType::Float32, false),
            Field::new("c_string", DataType::Utf8, false),
        ]);

        let file = File::open("test/data/null_test.csv").unwrap();

        let mut csv = Reader::new(file, Arc::new(schema), true, 1024, None);
        let batch = csv.next().unwrap().unwrap();

        assert_eq!(false, batch.column(1).is_null(0));
        assert_eq!(false, batch.column(1).is_null(1));
        assert_eq!(true, batch.column(1).is_null(2));
        assert_eq!(false, batch.column(1).is_null(3));
        assert_eq!(false, batch.column(1).is_null(4));
    }

}
<|endoftext|>


<commit_before>pub fn gcd(x: i64, y: i64) -> i64 {
    if y == 0 {
        x.abs()
    } else {
        gcd(y, x % y)
    }
}

/// Finds a solution of Bézout's identity ``s * x + t * y = d``
/// where `d` is the greatest common divisor of `x`, `y`.
pub fn gcd_ext(x: i64, y: i64) -> (i64, i64, i64) {
    if y == 0 {
        (x.abs(), x.signum(), 0)
    } else {
        let (d, s, t) = gcd_ext(y, x % y);
        (d, t, s - x / y * t)
    }
}

#[cfg(test)]
mod tests {
    use super::{gcd, gcd_ext};

    #[test]
    fn test_gcd() {
        fn case(x: i64, y: i64, d: i64) {
            assert_eq!(gcd(x, y), d, "{:?}", (x, y, d));
            assert_eq!(gcd(y, x), d, "{:?}", (y, x, d));
        }

        case(1, 1, 1);
        case(3, 5, 1);
        case(2, 2, 2);
        case(4, 6, 2);
        case(18, 24, 6);
        case(-1, -1, 1);
        case(4, -6, 2);
    }

    #[test]
    fn test_gcd_ext() {
        fn case(x: i64, y: i64, (d, s, t): (i64, i64, i64)) {
            assert_eq!(gcd_ext(x, y), (d, s, t), "{:?}", (x, y));
            assert_eq!(s * x + t * y, d);
        }

        case(3, 7, (1, -2, 1));
        case(4, 6, (2, -1, 1));
        case(360 * 5 * 5 * 11, 360 * 7 * 7 * 13, (360, -227, 98));
        case(4, -6, (2, -1, -1));
        case(-9, -12, (3, 1, -1));
    }
}
<commit_msg>Add lcm<commit_after>pub fn gcd(x: i64, y: i64) -> i64 {
    if y == 0 {
        x.abs()
    } else {
        gcd(y, x % y)
    }
}

/// Finds a solution of Bézout's identity ``s * x + t * y = d``
/// where `d` is the greatest common divisor of `x`, `y`.
pub fn gcd_ext(x: i64, y: i64) -> (i64, i64, i64) {
    if y == 0 {
        (x.abs(), x.signum(), 0)
    } else {
        let (d, s, t) = gcd_ext(y, x % y);
        (d, t, s - x / y * t)
    }
}

pub fn lcm(x: i64, y: i64) -> i64 {
    x / gcd(x, y) * y
}

#[cfg(test)]
mod tests {
    use super::{gcd, gcd_ext, lcm};

    #[test]
    fn test_gcd() {
        fn case(x: i64, y: i64, d: i64) {
            assert_eq!(gcd(x, y), d, "{:?}", (x, y, d));
            assert_eq!(gcd(y, x), d, "{:?}", (y, x, d));
        }

        case(1, 1, 1);
        case(3, 5, 1);
        case(2, 2, 2);
        case(4, 6, 2);
        case(18, 24, 6);
        case(-1, -1, 1);
        case(4, -6, 2);
    }

    #[test]
    fn test_gcd_ext() {
        fn case(x: i64, y: i64, (d, s, t): (i64, i64, i64)) {
            assert_eq!(gcd_ext(x, y), (d, s, t), "{:?}", (x, y));
            assert_eq!(s * x + t * y, d);
        }

        case(3, 7, (1, -2, 1));
        case(4, 6, (2, -1, 1));
        case(360 * 5 * 5 * 11, 360 * 7 * 7 * 13, (360, -227, 98));
        case(4, -6, (2, -1, -1));
        case(-9, -12, (3, 1, -1));
    }

    #[test]
    fn test_lcm() {
        assert_eq!(lcm(1, 1), 1);
        assert_eq!(lcm(12, 18), 36);
    }
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use shannon::Shannon;
use std::io;
use tokio_core::io::{Codec, EasyBuf};

const HEADER_SIZE: usize = 3;
const MAC_SIZE: usize = 4;

#[derive(Debug)]
enum DecodeState {
    Header,
    Payload(u8, usize),
}

pub struct APCodec {
    encode_nonce: u32,
    encode_cipher: Shannon,

    decode_nonce: u32,
    decode_cipher: Shannon,
    decode_state: DecodeState,
}

impl APCodec {
    pub fn new(send_key: &[u8], recv_key: &[u8]) -> APCodec {
        APCodec {
            encode_nonce: 0,
            encode_cipher: Shannon::new(send_key),

            decode_nonce: 0,
            decode_cipher: Shannon::new(recv_key),
            decode_state: DecodeState::Header,
        }
    }
}

impl Codec for APCodec {
    type Out = (u8, Vec<u8>);
    type In = (u8, EasyBuf);

    fn encode(&mut self, item: (u8, Vec<u8>), buf: &mut Vec<u8>) -> io::Result<()> {
        let (cmd, payload) = item;
        let offset = buf.len();

        buf.write_u8(cmd).unwrap();
        buf.write_u16::<BigEndian>(payload.len() as u16).unwrap();
        buf.extend_from_slice(&payload);

        self.encode_cipher.nonce_u32(self.encode_nonce);
        self.encode_nonce += 1;

        self.encode_cipher.encrypt(&mut buf[offset..]);

        let mac = [0u8; MAC_SIZE];
        self.encode_cipher.finish(&mut mac);
        buf.extend_from_slice(&mac);

        Ok(())
    }

    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<(u8, EasyBuf)>> {
        if let DecodeState::Header = self.decode_state {
            if buf.len() >= HEADER_SIZE {
                let mut header = [0u8; HEADER_SIZE];
                header.copy_from_slice(buf.drain_to(HEADER_SIZE).as_slice());

                self.decode_cipher.nonce_u32(self.decode_nonce);
                self.decode_nonce += 1;

                self.decode_cipher.decrypt(&mut header);

                let cmd = header[0];
                let size = BigEndian::read_u16(&header[1..]) as usize;
                self.decode_state = DecodeState::Payload(cmd, size);
            }
        }

        if let DecodeState::Payload(cmd, size) = self.decode_state {
            if buf.len() >= size + MAC_SIZE {
                self.decode_state = DecodeState::Header;

                let mut payload = buf.drain_to(size + MAC_SIZE);

                self.decode_cipher.decrypt(&mut payload.get_mut()[..size]);
                let mac = payload.split_off(size);
                self.decode_cipher.check_mac(mac.as_slice())?;

                return Ok(Some((cmd, payload)));
            }
        }

        Ok(None)
    }
}
<commit_msg>Fix compiling error<commit_after>use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
use shannon::Shannon;
use std::io;
use tokio_core::io::{Codec, EasyBuf};

const HEADER_SIZE: usize = 3;
const MAC_SIZE: usize = 4;

#[derive(Debug)]
enum DecodeState {
    Header,
    Payload(u8, usize),
}

pub struct APCodec {
    encode_nonce: u32,
    encode_cipher: Shannon,

    decode_nonce: u32,
    decode_cipher: Shannon,
    decode_state: DecodeState,
}

impl APCodec {
    pub fn new(send_key: &[u8], recv_key: &[u8]) -> APCodec {
        APCodec {
            encode_nonce: 0,
            encode_cipher: Shannon::new(send_key),

            decode_nonce: 0,
            decode_cipher: Shannon::new(recv_key),
            decode_state: DecodeState::Header,
        }
    }
}

impl Codec for APCodec {
    type Out = (u8, Vec<u8>);
    type In = (u8, EasyBuf);

    fn encode(&mut self, item: (u8, Vec<u8>), buf: &mut Vec<u8>) -> io::Result<()> {
        let (cmd, payload) = item;
        let offset = buf.len();

        buf.write_u8(cmd).unwrap();
        buf.write_u16::<BigEndian>(payload.len() as u16).unwrap();
        buf.extend_from_slice(&payload);

        self.encode_cipher.nonce_u32(self.encode_nonce);
        self.encode_nonce += 1;

        self.encode_cipher.encrypt(&mut buf[offset..]);

        let mut mac = [0u8; MAC_SIZE];
        self.encode_cipher.finish(&mut mac);
        buf.extend_from_slice(&mac);

        Ok(())
    }

    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<(u8, EasyBuf)>> {
        if let DecodeState::Header = self.decode_state {
            if buf.len() >= HEADER_SIZE {
                let mut header = [0u8; HEADER_SIZE];
                header.copy_from_slice(buf.drain_to(HEADER_SIZE).as_slice());

                self.decode_cipher.nonce_u32(self.decode_nonce);
                self.decode_nonce += 1;

                self.decode_cipher.decrypt(&mut header);

                let cmd = header[0];
                let size = BigEndian::read_u16(&header[1..]) as usize;
                self.decode_state = DecodeState::Payload(cmd, size);
            }
        }

        if let DecodeState::Payload(cmd, size) = self.decode_state {
            if buf.len() >= size + MAC_SIZE {
                self.decode_state = DecodeState::Header;

                let mut payload = buf.drain_to(size + MAC_SIZE);

                self.decode_cipher.decrypt(&mut payload.get_mut()[..size]);
                let mac = payload.split_off(size);
                self.decode_cipher.check_mac(mac.as_slice())?;

                return Ok(Some((cmd, payload)));
            }
        }

        Ok(None)
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
# ears

__ears__ is a simple library for play Audio in Rust.

__ears__ is build on the top of OpenAL and libsndfile.

* Provide an acces to the OpenAL spatialization functionnality in a simple way.
* Accept a lot of audio format thanks to libsndfile.

# A simple example

```Rust
extern mod ears;
use ears::Sound;

fn main() -> {
	// Create a new Sound.
	let snd = Sound::new(~"path/to/my/sound.ogg").unwrap();

	// Play the Sound
	snd.play();

	// Wait until the end of the sound
	while snd.is_playing() {}
}
```

# Use ears

As said before, __ears__ require OpenAL and libsndfile, you need to install these two libraries in your system.

__ears__ compile against the last Rust compiler, so if it doesn't work on your computer you may need to update your compiler.

__ears__ work fully with `rustpkg`, so just install __ears__ in your project workspace like this :

```Shell
> rustpkg install github.com/JeremyLetang/ears
```

then import stuff from __ears__ in your project :

```Rust
extern mod ears;
use ears::*;
```

*/

#[feature(globs)];

#[link(name = "ears",
       vers = "0.0.1",
       author = "letang.jeremy@gmail.com",
       uuid = "D0271EC6-5F27-4C72-BBEA-1341DC665F34",
       url = "https://github.com/JeremyLetang/ears")];

#[desc = "Easy Api in Rust for Sounds"];
#[license = "MIT"];
#[crate_type = "lib"];

extern mod extra;
extern mod sndfile;

pub use sound::Sound;
pub use sound_data::{SoundData, SoundTags};
pub use states::{State, Initial, Playing, Paused, Stopped};

#[doc(hidden)]
mod internal;

pub mod listener;
pub mod sound;
pub mod sound_data;
pub mod states;

#[doc(hidden)]
mod openal;
<commit_msg>update doc again...<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/*!
# ears

__ears__ is a simple library for play Audio in Rust.

__ears__ is build on the top of OpenAL and libsndfile.

* Provide an acces to the OpenAL spatialization functionnality in a simple way.
* Accept a lot of audio format thanks to libsndfile.

# A simple example

```Rust
extern mod ears;
use ears::Sound;

fn main() -> {
	// Create a new Sound.
	let snd = Sound::new(~"path/to/my/sound.ogg").unwrap();

	// Play the Sound
	snd.play();

	// Wait until the end of the sound
	while snd.is_playing() {}
}
```

# Functionnality

__ears__ provide two way for play audio files.

* The Sound class, which represent light sounds who can share a buffer of samples with another Sound.
* The Music class, which is a bigger sound and who can't share sample buffer.

# Use ears

As said before, __ears__ require OpenAL and libsndfile, you need to install these two libraries in your system.

__ears__ compile against the last Rust compiler, so if it doesn't work on your computer you may need to update your compiler.

__ears__ work fully with `rustpkg`, so just install __ears__ in your project workspace like this :

```Shell
> rustpkg install github.com/JeremyLetang/ears
```

then import stuff from __ears__ in your project :

```Rust
extern mod ears;
use ears::*;
```

*/

#[feature(globs)];

#[link(name = "ears",
       vers = "0.0.1",
       author = "letang.jeremy@gmail.com",
       uuid = "D0271EC6-5F27-4C72-BBEA-1341DC665F34",
       url = "https://github.com/JeremyLetang/ears")];

#[desc = "Easy Api in Rust for Sounds"];
#[license = "MIT"];
#[crate_type = "lib"];

extern mod extra;
extern mod sndfile;

pub use sound::Sound;
pub use sound_data::{SoundData, SoundTags};
pub use states::{State, Initial, Playing, Paused, Stopped};

#[doc(hidden)]
mod internal;

pub mod listener;
pub mod sound;
pub mod sound_data;
pub mod states;

#[doc(hidden)]
mod openal;
<|endoftext|>


<commit_before>//! The `expressionparser` module parses every expression
//! to an [AST (abstract syntax tree)](../ast/index.html).
//! The idea is explained here: http://programmers.stackexchange.com/questions/254074/

use config::Config;
use frontend::ast::{ASTNode, NodeDefault};
use frontend::lexer::Token;
use frontend::lexer::Token::*;

/// The errors that can occur in the ExpressionParser.
#[derive(Debug)]
#[allow(missing_docs)]
pub enum ExpressionParserError {
    /// The operator stack is empty
    OperStackIsEmpty,

    /// The sub-expression is not parseable
    NoParseableSubExpression,

    /// There can't be more than one expression root
    MoreThanOneRootExpression { count: usize, stack: Vec<ASTNode> },

    /// Stack underflow
    NotEnoughElementsOnStack,

    /// Missing a Node
    MissingNodeForBinaryNode,

    /// Operator is unkown / invalid
    DisallowedOperator { op: Token },

    /// Operator is not implemented
    NotImplementedOperator { op: String },
}

/// Parses an expression and ASTNodes.
pub struct ExpressionParser<'a> {
    /// The stack for the expressions
    expr_stack: Vec<ASTNode>,

    /// The stack for the operators for precedence
    oper_stack: Vec<Token>,

    /// The zwreec Config
    cfg: &'a Config,
}

impl<'a> ExpressionParser<'a> {

    /// Gets node (with an expression) and starts the parsing.
    pub fn parse(node: &mut NodeDefault, cfg: &'a Config) {
        let mut expr_parser = ExpressionParser {
            expr_stack: Vec::new(),
            oper_stack: Vec::new(),
            cfg: cfg,
        };
        expr_parser.parse_expressions(node);
    }

    /// Parse the expression node and creates mutliple ast nodes.
    fn parse_expressions(&mut self, node: &mut NodeDefault) {
        node.childs.reverse();
        while let Some(top) = node.childs.pop() {
            match top.category() {
                tok @ TokBoolean  { .. } |
                tok @ TokInt      { .. } |
                tok @ TokString   { .. } |
                tok @ TokFunction { .. } |
                tok @ TokArrayLength { .. } |
                tok @ TokArrayAccess { .. } |
                tok @ TokVariable { .. } => {
                    let childs_copy = top.as_default().childs.to_vec();
                    self.expr_stack.push( ASTNode::Default(NodeDefault { category: tok.clone(), childs: childs_copy }) );
                },
                tok @ TokNumOp      { .. } |
                tok @ TokCompOp     { .. } |
                tok @ TokLogOp      { .. } |
                tok @ TokUnaryMinus { .. } => {
                    let length = self.oper_stack.len();

                    // cycle through the oper_stack stack backwards
                    // if the rank of the current operator is <= the top of the
                    // stack, we create a new node
                    // if anybody is good in rust, please refactor this. it
                    // should be:
                    // while(is_ranking_not_higher(oper_stack.top(), tok.clone())) { ...
                    for i in 0..length {
                        let i_rev = length - i - 1;
                        let token: Token = match self.oper_stack.get(i_rev) {
                            Some(tok) => tok.clone(),
                            None      => {
                                error_panic!(self.cfg => ExpressionParserError::OperStackIsEmpty);
                                return
                            }
                        };
                        if self.is_ranking_not_higher(token.clone(), tok.clone()) {
                            self.new_operator_node();
                        }

                    }

                    self.oper_stack.push(tok.clone());
                },
                tok @ TokExpression => {
                    // more ugly code.
                    // an expression-node is a child of an expression, if there
                    // where parentheses in the expression. but we don't want
                    // them, so we parse the subexpression in the parentheses

                    // make a copy of the top-node. (becouse node is borrowed)
                    // and then parse it again
                    let childs_copy = top.as_default().childs.to_vec();
                    let mut ast_node = NodeDefault { category: tok.clone(), childs: childs_copy };
                    ExpressionParser::parse(&mut ast_node, self.cfg);

                    if let Some(temp) = ast_node.childs.get(0) {
                        self.expr_stack.push(temp.clone());
                    } else {
                        error_panic!(self.cfg => ExpressionParserError::NoParseableSubExpression);
                    }
                },
                _ => ()
            }
        }

        // Parse the last elements of the stacks.
        // To avoid an endless loop we try max until stack.len()
        for _ in 0..self.expr_stack.len() {
            if self.expr_stack.len() > 0 {
                self.new_operator_node();
            }
        }

        // Multiple operators could be on the stack because of the unary operators
        for _ in 0..self.oper_stack.len() {
            if self.oper_stack.len() > 0 {
                self.new_operator_node();
            }
        }

        if self.expr_stack.len() != 1 {
            error_panic!(self.cfg => ExpressionParserError::MoreThanOneRootExpression { count: self.expr_stack.len(),
                stack: self.expr_stack.clone() });
        }

        // We are finished parsing the expression
        // Add the root of the expressions as child to the AST
        if let Some(root) = self.expr_stack.pop() {
            node.childs.push(root);
        }
    }

    /// Creates a node with an operator as the root.
    fn new_operator_node(&mut self) {
        if let Some(top_op) = self.oper_stack.pop() {

            let is_unary: bool = match top_op.clone() {
                TokLogOp { op_name: op, .. } => match &*op {
                    "not" => true,
                    "!"   => true,
                    _     => false
                },
                TokUnaryMinus { .. } => true,
                _  => false
            };

            if self.expr_stack.len() > 0 {
                let e2: ASTNode = match self.expr_stack.pop() {
                    Some(tok) => tok,
                    None      => {
                        error_panic!(self.cfg => ExpressionParserError::NotEnoughElementsOnStack);
                        return
                    }
                };

                let mut new_node: ASTNode;

                if is_unary {
                    new_node = ASTNode::Default(NodeDefault { category: top_op.clone(), childs: vec![e2] });
                } else {
                    let e1: ASTNode = match self.expr_stack.pop() {
                        Some(tok) => tok,
                        None      => {
                            error_panic!(self.cfg => ExpressionParserError::MissingNodeForBinaryNode);
                            return
                        }
                    };
                    new_node = ASTNode::Default(NodeDefault { category: top_op.clone(), childs: vec![e1, e2] });
                }

                self.expr_stack.push( new_node );
            } else {
                // multiple unary operators in a row like "not not true"
                self.oper_stack.push(top_op.clone());
            }
        }
    }

    /// Checks the operator precedence of two Tokens.
    ///
    /// Returns true if the operator of token1 is stronger than operator of token2.
    /// The ranking is specified in the function `operator_rank`.
    fn is_ranking_not_higher(&self, token1: Token, token2: Token) -> bool {
        let op1: String = match token1 {
            TokUnaryMinus{ .. } => "_".to_string(),
            TokNumOp     { op_name, .. } |
            TokCompOp    { op_name, .. } |
            TokLogOp     { op_name, .. } => {
                op_name.clone()
            },
            _ => {
                error_panic!(self.cfg => ExpressionParserError::DisallowedOperator { op: token1.clone() });
                return false
            }
        };
        let op2: String = match token2 {
            TokUnaryMinus{ .. } => "_".to_string(),
            TokNumOp     { op_name, .. } |
            TokCompOp    { op_name, .. } |
            TokLogOp     { op_name, .. } => {
                op_name.clone()
            },
            _ => {
                error_panic!(self.cfg => ExpressionParserError::DisallowedOperator { op: token2.clone() });
                return false
            }
        };

        // Special handling for the unary operators (two unary operators in a row)
        if (op1 == "_" || op1 == "not" || op1 == "!") &&
            self.operator_rank(op1.clone()) == self.operator_rank(op2.clone()) {

            return false
        }

        self.operator_rank(op1) >= self.operator_rank(op2)
    }

    /// Specifies the ranking of the operators.
    fn operator_rank(&self, op: String) -> u8 {
        match op.as_ref() {
            "or" | "||"         => 1,
            "and" | "&&"        => 2,
            "is" | "==" | "eq" | "!=" | "neq" | ">" | "gt" | ">=" | "gte" | "<" | "lt" | "<=" | "lte"
                                => 3,
            "+" | "-"           => 4,
            "*" | "/" | "%"     => 5,
            "_" | "not" | "!"   => 6, // _ is unary minus
            _                   => {
                error_panic!(self.cfg => ExpressionParserError::NotImplementedOperator { op: op });
                0
            }
        }
    }
}
<commit_msg>Remove warning about unused mutability.<commit_after>//! The `expressionparser` module parses every expression
//! to an [AST (abstract syntax tree)](../ast/index.html).
//! The idea is explained here: http://programmers.stackexchange.com/questions/254074/

use config::Config;
use frontend::ast::{ASTNode, NodeDefault};
use frontend::lexer::Token;
use frontend::lexer::Token::*;

/// The errors that can occur in the ExpressionParser.
#[derive(Debug)]
#[allow(missing_docs)]
pub enum ExpressionParserError {
    /// The operator stack is empty
    OperStackIsEmpty,

    /// The sub-expression is not parseable
    NoParseableSubExpression,

    /// There can't be more than one expression root
    MoreThanOneRootExpression { count: usize, stack: Vec<ASTNode> },

    /// Stack underflow
    NotEnoughElementsOnStack,

    /// Missing a Node
    MissingNodeForBinaryNode,

    /// Operator is unkown / invalid
    DisallowedOperator { op: Token },

    /// Operator is not implemented
    NotImplementedOperator { op: String },
}

/// Parses an expression and ASTNodes.
pub struct ExpressionParser<'a> {
    /// The stack for the expressions
    expr_stack: Vec<ASTNode>,

    /// The stack for the operators for precedence
    oper_stack: Vec<Token>,

    /// The zwreec Config
    cfg: &'a Config,
}

impl<'a> ExpressionParser<'a> {

    /// Gets node (with an expression) and starts the parsing.
    pub fn parse(node: &mut NodeDefault, cfg: &'a Config) {
        let mut expr_parser = ExpressionParser {
            expr_stack: Vec::new(),
            oper_stack: Vec::new(),
            cfg: cfg,
        };
        expr_parser.parse_expressions(node);
    }

    /// Parse the expression node and creates mutliple ast nodes.
    fn parse_expressions(&mut self, node: &mut NodeDefault) {
        node.childs.reverse();
        while let Some(top) = node.childs.pop() {
            match top.category() {
                tok @ TokBoolean  { .. } |
                tok @ TokInt      { .. } |
                tok @ TokString   { .. } |
                tok @ TokFunction { .. } |
                tok @ TokArrayLength { .. } |
                tok @ TokArrayAccess { .. } |
                tok @ TokVariable { .. } => {
                    let childs_copy = top.as_default().childs.to_vec();
                    self.expr_stack.push( ASTNode::Default(NodeDefault { category: tok.clone(), childs: childs_copy }) );
                },
                tok @ TokNumOp      { .. } |
                tok @ TokCompOp     { .. } |
                tok @ TokLogOp      { .. } |
                tok @ TokUnaryMinus { .. } => {
                    let length = self.oper_stack.len();

                    // cycle through the oper_stack stack backwards
                    // if the rank of the current operator is <= the top of the
                    // stack, we create a new node
                    // if anybody is good in rust, please refactor this. it
                    // should be:
                    // while(is_ranking_not_higher(oper_stack.top(), tok.clone())) { ...
                    for i in 0..length {
                        let i_rev = length - i - 1;
                        let token: Token = match self.oper_stack.get(i_rev) {
                            Some(tok) => tok.clone(),
                            None      => {
                                error_panic!(self.cfg => ExpressionParserError::OperStackIsEmpty);
                                return
                            }
                        };
                        if self.is_ranking_not_higher(token.clone(), tok.clone()) {
                            self.new_operator_node();
                        }

                    }

                    self.oper_stack.push(tok.clone());
                },
                tok @ TokExpression => {
                    // more ugly code.
                    // an expression-node is a child of an expression, if there
                    // where parentheses in the expression. but we don't want
                    // them, so we parse the subexpression in the parentheses

                    // make a copy of the top-node. (becouse node is borrowed)
                    // and then parse it again
                    let childs_copy = top.as_default().childs.to_vec();
                    let mut ast_node = NodeDefault { category: tok.clone(), childs: childs_copy };
                    ExpressionParser::parse(&mut ast_node, self.cfg);

                    if let Some(temp) = ast_node.childs.get(0) {
                        self.expr_stack.push(temp.clone());
                    } else {
                        error_panic!(self.cfg => ExpressionParserError::NoParseableSubExpression);
                    }
                },
                _ => ()
            }
        }

        // Parse the last elements of the stacks.
        // To avoid an endless loop we try max until stack.len()
        for _ in 0..self.expr_stack.len() {
            if self.expr_stack.len() > 0 {
                self.new_operator_node();
            }
        }

        // Multiple operators could be on the stack because of the unary operators
        for _ in 0..self.oper_stack.len() {
            if self.oper_stack.len() > 0 {
                self.new_operator_node();
            }
        }

        if self.expr_stack.len() != 1 {
            error_panic!(self.cfg => ExpressionParserError::MoreThanOneRootExpression { count: self.expr_stack.len(),
                stack: self.expr_stack.clone() });
        }

        // We are finished parsing the expression
        // Add the root of the expressions as child to the AST
        if let Some(root) = self.expr_stack.pop() {
            node.childs.push(root);
        }
    }

    /// Creates a node with an operator as the root.
    fn new_operator_node(&mut self) {
        if let Some(top_op) = self.oper_stack.pop() {

            let is_unary: bool = match top_op.clone() {
                TokLogOp { op_name: op, .. } => match &*op {
                    "not" => true,
                    "!"   => true,
                    _     => false
                },
                TokUnaryMinus { .. } => true,
                _  => false
            };

            if self.expr_stack.len() > 0 {
                let e2: ASTNode = match self.expr_stack.pop() {
                    Some(tok) => tok,
                    None      => {
                        error_panic!(self.cfg => ExpressionParserError::NotEnoughElementsOnStack);
                        return
                    }
                };

                let new_node: ASTNode;

                if is_unary {
                    new_node = ASTNode::Default(NodeDefault { category: top_op.clone(), childs: vec![e2] });
                } else {
                    let e1: ASTNode = match self.expr_stack.pop() {
                        Some(tok) => tok,
                        None      => {
                            error_panic!(self.cfg => ExpressionParserError::MissingNodeForBinaryNode);
                            return
                        }
                    };
                    new_node = ASTNode::Default(NodeDefault { category: top_op.clone(), childs: vec![e1, e2] });
                }

                self.expr_stack.push( new_node );
            } else {
                // multiple unary operators in a row like "not not true"
                self.oper_stack.push(top_op.clone());
            }
        }
    }

    /// Checks the operator precedence of two Tokens.
    ///
    /// Returns true if the operator of token1 is stronger than operator of token2.
    /// The ranking is specified in the function `operator_rank`.
    fn is_ranking_not_higher(&self, token1: Token, token2: Token) -> bool {
        let op1: String = match token1 {
            TokUnaryMinus{ .. } => "_".to_string(),
            TokNumOp     { op_name, .. } |
            TokCompOp    { op_name, .. } |
            TokLogOp     { op_name, .. } => {
                op_name.clone()
            },
            _ => {
                error_panic!(self.cfg => ExpressionParserError::DisallowedOperator { op: token1.clone() });
                return false
            }
        };
        let op2: String = match token2 {
            TokUnaryMinus{ .. } => "_".to_string(),
            TokNumOp     { op_name, .. } |
            TokCompOp    { op_name, .. } |
            TokLogOp     { op_name, .. } => {
                op_name.clone()
            },
            _ => {
                error_panic!(self.cfg => ExpressionParserError::DisallowedOperator { op: token2.clone() });
                return false
            }
        };

        // Special handling for the unary operators (two unary operators in a row)
        if (op1 == "_" || op1 == "not" || op1 == "!") &&
            self.operator_rank(op1.clone()) == self.operator_rank(op2.clone()) {

            return false
        }

        self.operator_rank(op1) >= self.operator_rank(op2)
    }

    /// Specifies the ranking of the operators.
    fn operator_rank(&self, op: String) -> u8 {
        match op.as_ref() {
            "or" | "||"         => 1,
            "and" | "&&"        => 2,
            "is" | "==" | "eq" | "!=" | "neq" | ">" | "gt" | ">=" | "gte" | "<" | "lt" | "<=" | "lte"
                                => 3,
            "+" | "-"           => 4,
            "*" | "/" | "%"     => 5,
            "_" | "not" | "!"   => 6, // _ is unary minus
            _                   => {
                error_panic!(self.cfg => ExpressionParserError::NotImplementedOperator { op: op });
                0
            }
        }
    }
}
<|endoftext|>


<commit_before>use getopts::{optflag,optopt,getopts,usage};
use std::os;
use std::collections::HashMap;
use std::io;
use std::io::fs::PathExtensions;

use item::parse_item;

macro_rules! main_try {
    ($result: expr, $errmsg: expr) => (
        match $result {
            Ok(m) => m,
            Err(e) => {
                println!("{}: {}", $errmsg, e);
                os::set_exit_status(1);
                return;
            }
        }
    )
}

fn get_env() -> HashMap<String, String> {
    let mut env = HashMap::new();
    env.extend(os::env().into_iter().filter(|&(ref key, ref value)| {
        key.as_slice().starts_with("MATES_") && value.len() > 0
    }));
    env
}

fn from_env<'a>(env: &'a HashMap<String, String>, key: &str) -> Option<&'a String> {
    env.find_equiv(&key)
}

fn expect_env<'a>(env: &'a HashMap<String, String>, key: &str) -> &'a String {
    from_env(env, key).expect(
        format!("The {} environment variable must be set.", key).as_slice()
    )
}

fn build_index(outfile: &Path, dir: &Path) -> io::IoResult<()> {
    if !dir.is_dir() {
        return Err(io::IoError {
            kind: io::MismatchedFileTypeForOperation,
            desc: "MATES_DIR must be a directory.",
            detail: None
        });
    };

    let mut outf = io::File::create(outfile);
    let entries = try!(io::fs::readdir(dir));
    for entry in entries.iter() {
        if !entry.is_file() {
            continue;
        }
        let itemstr = try!(io::File::open(entry).read_to_string());
        let item = parse_item(&itemstr);
        let name = item.single_value(&"FN".into_string());
        match item.all_values(&"EMAIL".into_string()) {
            Some(emails) => {
                for email in emails.iter() {
                    try!(outf.write_str(
                        format!("{}\t{}\n", email.get_raw_value(), name).as_slice()
                    ))
                };
            },
            None => ()
        };
    };
    return Ok(());
}

pub fn cli_main() {
    let args = os::args();

    let program = args[0].as_slice();
    let opts = [
        optflag("i", "index", "Create index."),
        optflag("h", "help", "Print help."),
        optopt("m", "mutt-search", "Search in index, for mutt search.", "")
    ];

    let matches = main_try!(getopts(args.tail(), opts), "Failed to parse arguments");

    let env = get_env();

    let print_usage = || {
        println!("{}", usage(program, opts));
        println!("Environment variables:");
        println!("- MATES_INDEX: Path to index file, which is basically a cache of all");
        println!("               contacts.");
        println!("- MATES_DIR:   The vdir to use.");
        println!("- MATES_GREP:  The grep executable to use.");
    };

    if matches.opt_present("h") {
        print_usage();

    } else if matches.opt_present("index") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let mates_dir = expect_env(&env, "MATES_DIR");
        println!("Rebuilding index file \"{}\"...", index_file);
        main_try!(build_index(
            &Path::new(index_file.as_slice()),
            &Path::new(mates_dir.as_slice())
        ), "Failed to build index");

    } else if matches.opt_present("mutt-search") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let default_grep = "grep".into_string();
        let grep_cmd = match from_env(&env, "MATES_GREP") {
            Some(x) => x,
            None => &default_grep
        };

        // FIXME: Better way to write this? We already checked for presence of mutt-search before
        let query = matches.opt_str("mutt-search").expect("This should never happen and yet it did.");
        let mut cmd = io::Command::new(grep_cmd.as_slice());
        cmd.arg(query.as_slice());
        cmd.arg(index_file.as_slice());
        cmd.stdout(io::process::InheritFd(1));
        cmd.stderr(io::process::InheritFd(2));

        let cmd_error = format!("Failed to execute `{}`", cmd);
        let mut process = main_try!(cmd.spawn(), cmd_error);
        let code = main_try!(process.wait(), cmd_error);
        os::set_exit_status(match code {
            io::process::ExitStatus(x) => x,
            io::process::ExitSignal(x) => x,
        });

    } else {
        print_usage();
    };
}
<commit_msg>Fix mutt-query formatting<commit_after>use getopts::{optflag,optopt,getopts,usage};
use std::os;
use std::collections::HashMap;
use std::io;
use std::io::fs::PathExtensions;

use item::parse_item;

macro_rules! main_try {
    ($result: expr, $errmsg: expr) => (
        match $result {
            Ok(m) => m,
            Err(e) => {
                println!("{}: {}", $errmsg, e);
                os::set_exit_status(1);
                return;
            }
        }
    )
}

fn get_env() -> HashMap<String, String> {
    let mut env = HashMap::new();
    env.extend(os::env().into_iter().filter(|&(ref key, ref value)| {
        key.as_slice().starts_with("MATES_") && value.len() > 0
    }));
    env
}

fn from_env<'a>(env: &'a HashMap<String, String>, key: &str) -> Option<&'a String> {
    env.find_equiv(&key)
}

fn expect_env<'a>(env: &'a HashMap<String, String>, key: &str) -> &'a String {
    from_env(env, key).expect(
        format!("The {} environment variable must be set.", key).as_slice()
    )
}

fn build_index(outfile: &Path, dir: &Path) -> io::IoResult<()> {
    if !dir.is_dir() {
        return Err(io::IoError {
            kind: io::MismatchedFileTypeForOperation,
            desc: "MATES_DIR must be a directory.",
            detail: None
        });
    };

    let mut outf = io::File::create(outfile);
    let entries = try!(io::fs::readdir(dir));
    for entry in entries.iter() {
        if !entry.is_file() {
            continue;
        }
        let itemstr = try!(io::File::open(entry).read_to_string());
        let item = parse_item(&itemstr);
        let name = item.single_value(&"FN".into_string());
        match item.all_values(&"EMAIL".into_string()) {
            Some(emails) => {
                for email in emails.iter() {
                    try!(outf.write_str(
                        format!("{}\t{}\n", email.get_raw_value(), name).as_slice()
                    ))
                };
            },
            None => ()
        };
    };
    return Ok(());
}

pub fn cli_main() {
    let args = os::args();

    let program = args[0].as_slice();
    let opts = [
        optflag("i", "index", "Create index."),
        optflag("h", "help", "Print help."),
        optopt("m", "mutt-search", "Search in index, for mutt search.", "")
    ];

    let matches = main_try!(getopts(args.tail(), opts), "Failed to parse arguments");

    let env = get_env();

    let print_usage = || {
        println!("{}", usage(program, opts));
        println!("Environment variables:");
        println!("- MATES_INDEX: Path to index file, which is basically a cache of all");
        println!("               contacts.");
        println!("- MATES_DIR:   The vdir to use.");
        println!("- MATES_GREP:  The grep executable to use.");
    };

    if matches.opt_present("h") {
        print_usage();

    } else if matches.opt_present("index") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let mates_dir = expect_env(&env, "MATES_DIR");
        println!("Rebuilding index file \"{}\"...", index_file);
        main_try!(build_index(
            &Path::new(index_file.as_slice()),
            &Path::new(mates_dir.as_slice())
        ), "Failed to build index");

    } else if matches.opt_present("mutt-search") {
        let index_file = expect_env(&env, "MATES_INDEX");
        let default_grep = "grep".into_string();
        let grep_cmd = match from_env(&env, "MATES_GREP") {
            Some(x) => x,
            None => &default_grep
        };

        // FIXME: Better way to write this? We already checked for presence of mutt-search before
        let query = matches.opt_str("mutt-search").expect("This should never happen and yet it did.");
        let mut cmd = io::Command::new(grep_cmd.as_slice());
        cmd.arg(query.as_slice());
        cmd.arg(index_file.as_slice());
        cmd.stdout(io::process::InheritFd(1));
        cmd.stderr(io::process::InheritFd(2));

        let cmd_error = format!("Failed to execute `{}`", cmd);
        println!("");  // For some reason mutt requires an empty line
        let mut process = main_try!(cmd.spawn(), cmd_error);
        let code = main_try!(process.wait(), cmd_error);
        os::set_exit_status(match code {
            io::process::ExitStatus(x) => x,
            io::process::ExitSignal(x) => x,
        });

    } else {
        print_usage();
    };
}
<|endoftext|>