<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

extern crate pest;
extern crate pest_meta;

use std::char;
use std::collections::HashMap;

use pest::{Atomicity, Error, ParserState, Position};
use pest::iterators::Pairs;

use pest_meta::ast::{Expr, Rule, RuleType};

pub struct Vm {
    rules: HashMap<String, Rule>
}

impl Vm {
    pub fn new(rules: Vec<Rule>) -> Vm {
        let rules = rules.into_iter().map(|r| (r.name.clone(), r)).collect();
        Vm { rules }
    }

    pub fn parse<'i>(
        &self,
        rule: &str,
        input: &'i str
    ) -> Option<Result<Pairs<'i, &str>, Error<'i, &str>>> {
        if let Some(rule) = self.rules.get(rule) {
            let result = pest::state(input, |mut state, pos| {
                self.parse_rule(rule, pos, &mut state)
            });

            Some(result)
        } else {
            None
        }
    }

    fn parse_rule<'a, 'i>(
        &self,
        rule: &'a Rule,
        pos: Position<'i>,
        state: &mut ParserState<'i, &'a str>
    ) -> Result<Position<'i>, Position<'i>> {
        if &rule.name == "whitespace" || &rule.name == "comment" {
            match rule.ty {
                RuleType::Normal => state.rule(&rule.name, pos, |state, pos| {
                    state.atomic(Atomicity::Atomic, move |state| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::Silent => state.atomic(Atomicity::Atomic, move |state| {
                    self.parse_expr(&rule.expr, pos, state)
                }),
                RuleType::Atomic => state.rule(&rule.name, pos, |state, pos| {
                    state.atomic(Atomicity::Atomic, move |state| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::CompoundAtomic => state.atomic(Atomicity::CompoundAtomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::NonAtomic => state.atomic(Atomicity::Atomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                })
            }
        } else {
            match rule.ty {
                RuleType::Normal => state.rule(&rule.name, pos, |state, pos| {
                    self.parse_expr(&rule.expr, pos, state)
                }),
                RuleType::Silent => self.parse_expr(&rule.expr, pos, state),
                RuleType::Atomic => state.rule(&rule.name, pos, |state, pos| {
                    state.atomic(Atomicity::Atomic, move |state| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::CompoundAtomic => state.atomic(Atomicity::CompoundAtomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::NonAtomic => state.atomic(Atomicity::NonAtomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                })
            }
        }
    }

    fn parse_expr<'i>(
        &self,
        expr: &Expr,
        pos: Position<'i>,
        state: &mut ParserState<'i, &str>
    ) -> Result<Position<'i>, Position<'i>> {
        unimplemented!()
    }

    fn skip<'a, 'i>(
        &'a self,
        pos: Position<'i>,
        state: &mut ParserState<'i, &'a str>
    ) -> Result<Position<'i>, Position<'i>> {
        match (self.rules.get("whitespace"), self.rules.get("comment")) {
            (None, None) => Ok(pos),
            (Some(whitespace), None) => if state.atomicity == Atomicity::NonAtomic {
                pos.repeat(|pos| {
                    self.parse_rule(whitespace, pos, state)
                })
            } else {
                Ok(pos)
            },
            (None, Some(comment)) => if state.atomicity == Atomicity::NonAtomic {
                pos.repeat(|pos| {
                    self.parse_rule(comment, pos, state)
                })
            } else {
                Ok(pos)
            },
            (Some(whitespace), Some(comment)) => if state.atomicity == Atomicity::NonAtomic {
                state.sequence(move |state| {
                    pos.sequence(|pos| {
                        pos.repeat(|pos| {
                            self.parse_rule(whitespace, pos, state)
                        }).and_then(|pos| {
                            pos.repeat(|pos| {
                                state.sequence(move |state| {
                                    pos.sequence(|pos| {
                                        self.parse_rule(comment, pos, state).and_then(|pos| {
                                            pos.repeat(|pos| {
                                                self.parse_rule(whitespace, pos, state)
                                            })
                                        })
                                    })
                                })
                            })
                        })
                    })
                })
            } else {
                Ok(pos)
            }
        }
    }
}

fn unescape(string: &str) -> Option<String> {
    let mut result = String::new();
    let mut chars = string.chars();

    loop {
        match chars.next() {
            Some('\\') => {
                match chars.next()? {
                    '"' => result.push('"'),
                    '\\' => result.push('\\'),
                    'r' => result.push('\r'),
                    'n' => result.push('\n'),
                    't' => result.push('\t'),
                    '0' => result.push('\0'),
                    '\'' => result.push('\''),
                    'x' => {
                        let string: String = chars.clone().take(2).collect();

                        if string.len() != 2 {
                            return None;
                        }

                        for _ in 0..string.len() { chars.next()?; }

                        let value = u8::from_str_radix(&string, 16).ok()?;

                        result.push(char::from(value));
                    }
                    'u' => {
                        if chars.next()? != '{' {
                            return None;
                        }

                        let string: String = chars.clone().take_while(|c| *c != '}').collect();

                        if string.len() < 2 || 6 < string.len() {
                            return None;
                        }

                        for _ in 0..string.len() + 1 { chars.next()?; }

                        let value = u32::from_str_radix(&string, 16).ok()?;

                        result.push(char::from_u32(value)?);
                    }
                    _ => return None
                }
            }
            Some(c) => result.push(c),
            None => return Some(result)
        };
    }
}

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

    #[test]
    fn unescape_all() {
        let string = r"a\nb\x55c\u{111}d";

        assert_eq!(unescape(string), Some("a\nb\x55c\u{111}d".to_owned()));
    }

    #[test]
    fn unescape_empty_escape() {
        let string = r"\";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_wrong_escape() {
        let string = r"\w";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_wrong_byte() {
        let string = r"\xfg";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_short_byte() {
        let string = r"\xf";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_no_open_brace_unicode() {
        let string = r"\u11";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_no_close_brace_unicode() {
        let string = r"\u{11";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_short_unicode() {
        let string = r"\u{1}";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_long_unicode() {
        let string = r"\u{1111111}";

        assert_eq!(unescape(string), None);
    }
}
<commit_msg>Added expressions.<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

extern crate pest;
extern crate pest_meta;

use std::char;
use std::collections::HashMap;

use pest::{Atomicity, Error, ParserState, Position};
use pest::iterators::Pairs;

use pest_meta::ast::{Expr, Rule, RuleType};

pub struct Vm {
    rules: HashMap<String, Rule>
}

impl Vm {
    pub fn new(rules: Vec<Rule>) -> Vm {
        let rules = rules.into_iter().map(|r| (r.name.clone(), r)).collect();
        Vm { rules }
    }

    pub fn parse<'i>(
        &self,
        rule: &str,
        input: &'i str
    ) -> Option<Result<Pairs<'i, &str>, Error<'i, &str>>> {
        if let Some(rule) = self.rules.get(rule) {
            let result = pest::state(input, |mut state, pos| {
                self.parse_rule(rule, pos, &mut state)
            });

            Some(result)
        } else {
            None
        }
    }

    fn parse_rule<'a, 'i>(
        &'a self,
        rule: &'a Rule,
        pos: Position<'i>,
        state: &mut ParserState<'i, &'a str>
    ) -> Result<Position<'i>, Position<'i>> {
        if &rule.name == "whitespace" || &rule.name == "comment" {
            match rule.ty {
                RuleType::Normal => state.rule(&rule.name, pos, |state, pos| {
                    state.atomic(Atomicity::Atomic, move |state| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::Silent => state.atomic(Atomicity::Atomic, move |state| {
                    self.parse_expr(&rule.expr, pos, state)
                }),
                RuleType::Atomic => state.rule(&rule.name, pos, |state, pos| {
                    state.atomic(Atomicity::Atomic, move |state| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::CompoundAtomic => state.atomic(Atomicity::CompoundAtomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::NonAtomic => state.atomic(Atomicity::Atomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                })
            }
        } else {
            match rule.ty {
                RuleType::Normal => state.rule(&rule.name, pos, |state, pos| {
                    self.parse_expr(&rule.expr, pos, state)
                }),
                RuleType::Silent => self.parse_expr(&rule.expr, pos, state),
                RuleType::Atomic => state.rule(&rule.name, pos, |state, pos| {
                    state.atomic(Atomicity::Atomic, move |state| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::CompoundAtomic => state.atomic(Atomicity::CompoundAtomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                }),
                RuleType::NonAtomic => state.atomic(Atomicity::NonAtomic, move |state| {
                    state.rule(&rule.name, pos, |state, pos| {
                        self.parse_expr(&rule.expr, pos, state)
                    })
                })
            }
        }
    }

    fn parse_expr<'a, 'i>(
        &'a self,
        expr: &Expr,
        pos: Position<'i>,
        state: &mut ParserState<'i, &'a str>
    ) -> Result<Position<'i>, Position<'i>> {
        match *expr {
            Expr::Str(ref string) => {
                pos.match_string(&unescape(string).expect("incorrect string literal"))
            }
            Expr::Insens(ref string) => {
                pos.match_insensitive(&unescape(string).expect("incorrect string literal"))
            }
            Expr::Range(ref start, ref end) => {
                let start = unescape(start)
                    .expect("incorrect char literal")
                    .chars()
                    .next()
                    .expect("empty char literal");
                let end = unescape(end)
                    .expect("incorrect char literal")
                    .chars()
                    .next()
                    .expect("empty char literal");

                pos.match_range(start..end)
            }
            Expr::Ident(ref name) => {
                let rule = self.rules
                    .get(name)
                    .expect(&format!("undefined rule {}", name));
                self.parse_rule(rule, pos, state)
            }
            Expr::PosPred(ref expr) => state.lookahead(true, move |state| {
                pos.lookahead(true, |pos| self.parse_expr(&*expr, pos, state))
            }),
            Expr::NegPred(ref expr) => state.lookahead(false, move |state| {
                pos.lookahead(false, |pos| self.parse_expr(&*expr, pos, state))
            }),
            Expr::Seq(ref lhs, ref rhs) => state.sequence(move |state| {
                pos.sequence(|pos| {
                    self.parse_expr(&*lhs, pos, state)
                        .and_then(|pos| self.skip(pos, state))
                        .and_then(|pos| self.parse_expr(&*rhs, pos, state))
                })
            }),
            Expr::Choice(ref lhs, ref rhs) => self.parse_expr(&*lhs, pos, state)
                .or_else(|pos| self.parse_expr(&*rhs, pos, state)),
            Expr::Opt(ref expr) => pos.optional(|pos| self.parse_expr(&*expr, pos, state)),
            Expr::Rep(ref expr) => state.sequence(move |state| {
                pos.sequence(|pos| {
                    pos.optional(|pos| {
                        self.parse_expr(&*expr, pos, state).and_then(|pos| {
                            pos.repeat(|pos| {
                                state.sequence(move |state| {
                                    pos.sequence(|pos| {
                                        self.skip(pos, state)
                                            .and_then(|pos| self.parse_expr(&*expr, pos, state))
                                    })
                                })
                            })
                        })
                    })
                })
            }),
            Expr::Push(ref expr) => {
                let start = pos.clone();

                match self.parse_expr(&*expr, pos, state) {
                    Ok(end) => {
                        state.stack.push(start.span(&end));
                        Ok(end)
                    }
                    Err(pos) => Err(pos)
                }
            }
            Expr::Skip(ref strings) => strings[1..].iter().fold(
                pos.clone().skip_until(&strings[0]),
                |result, string| match (result, pos.clone().skip_until(string)) {
                    (Ok(lhs), Ok(rhs)) => {
                        if rhs.pos() < lhs.pos() {
                            Ok(rhs)
                        } else {
                            Ok(lhs)
                        }
                    }
                    (Ok(lhs), Err(_)) => Ok(lhs),
                    (Err(_), Ok(rhs)) => Ok(rhs),
                    (Err(lhs), Err(_)) => Err(lhs)
                }
            ),
            _ => unimplemented!()
        }
    }

    fn skip<'a, 'i>(
        &'a self,
        pos: Position<'i>,
        state: &mut ParserState<'i, &'a str>
    ) -> Result<Position<'i>, Position<'i>> {
        match (self.rules.get("whitespace"), self.rules.get("comment")) {
            (None, None) => Ok(pos),
            (Some(whitespace), None) => if state.atomicity == Atomicity::NonAtomic {
                pos.repeat(|pos| {
                    self.parse_rule(whitespace, pos, state)
                })
            } else {
                Ok(pos)
            },
            (None, Some(comment)) => if state.atomicity == Atomicity::NonAtomic {
                pos.repeat(|pos| {
                    self.parse_rule(comment, pos, state)
                })
            } else {
                Ok(pos)
            },
            (Some(whitespace), Some(comment)) => if state.atomicity == Atomicity::NonAtomic {
                state.sequence(move |state| {
                    pos.sequence(|pos| {
                        pos.repeat(|pos| {
                            self.parse_rule(whitespace, pos, state)
                        }).and_then(|pos| {
                            pos.repeat(|pos| {
                                state.sequence(move |state| {
                                    pos.sequence(|pos| {
                                        self.parse_rule(comment, pos, state).and_then(|pos| {
                                            pos.repeat(|pos| {
                                                self.parse_rule(whitespace, pos, state)
                                            })
                                        })
                                    })
                                })
                            })
                        })
                    })
                })
            } else {
                Ok(pos)
            }
        }
    }
}

fn unescape(string: &str) -> Option<String> {
    let mut result = String::new();
    let mut chars = string.chars();

    loop {
        match chars.next() {
            Some('\\') => {
                match chars.next()? {
                    '"' => result.push('"'),
                    '\\' => result.push('\\'),
                    'r' => result.push('\r'),
                    'n' => result.push('\n'),
                    't' => result.push('\t'),
                    '0' => result.push('\0'),
                    '\'' => result.push('\''),
                    'x' => {
                        let string: String = chars.clone().take(2).collect();

                        if string.len() != 2 {
                            return None;
                        }

                        for _ in 0..string.len() { chars.next()?; }

                        let value = u8::from_str_radix(&string, 16).ok()?;

                        result.push(char::from(value));
                    }
                    'u' => {
                        if chars.next()? != '{' {
                            return None;
                        }

                        let string: String = chars.clone().take_while(|c| *c != '}').collect();

                        if string.len() < 2 || 6 < string.len() {
                            return None;
                        }

                        for _ in 0..string.len() + 1 { chars.next()?; }

                        let value = u32::from_str_radix(&string, 16).ok()?;

                        result.push(char::from_u32(value)?);
                    }
                    _ => return None
                }
            }
            Some(c) => result.push(c),
            None => return Some(result)
        };
    }
}

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

    #[test]
    fn unescape_all() {
        let string = r"a\nb\x55c\u{111}d";

        assert_eq!(unescape(string), Some("a\nb\x55c\u{111}d".to_owned()));
    }

    #[test]
    fn unescape_empty_escape() {
        let string = r"\";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_wrong_escape() {
        let string = r"\w";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_wrong_byte() {
        let string = r"\xfg";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_short_byte() {
        let string = r"\xf";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_no_open_brace_unicode() {
        let string = r"\u11";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_no_close_brace_unicode() {
        let string = r"\u{11";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_short_unicode() {
        let string = r"\u{1}";

        assert_eq!(unescape(string), None);
    }

    #[test]
    fn unescape_long_unicode() {
        let string = r"\u{1111111}";

        assert_eq!(unescape(string), None);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::io::{stderr, Write};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

extern crate clap;
use clap::{App, Arg};

extern crate mio;
use mio::{EventLoop, EventSet, Handler, Token};
use mio::tcp::{TcpListener, TcpStream};

extern crate time;

const SERVER: Token = Token(0);

struct EchoHandler {
    connections: BTreeMap<usize, TcpStream>,
    listener: TcpListener,
    next_token: usize,
}

impl EchoHandler {
    fn new(l: TcpListener) -> EchoHandler {
        EchoHandler {
            connections: BTreeMap::new(),
            listener: l,
            next_token: 1
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
        {
            let conn = self.connections.get_mut(&token.as_usize()).unwrap();
            match write!(conn, "{}", time::now_utc().rfc822()) {
                Ok(_) => {
                    event_loop.deregister(conn).unwrap();
                    let addr = conn.peer_addr().unwrap();
                    write!(stderr(), "Sent the time to {} succesfully\n", addr);
                },
                Err(e) => {
                    write!(stderr(), "Error while writing: {}\n", e);
                }
            }
        }
        self.connections.remove(&token.as_usize()).unwrap();
    }
}

impl Handler for EchoHandler {
    type Message = ();
    type Timeout = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            SERVER => {
                let client = match self.listener.accept() {
                    // As per documentation, Ok(None) means WOULDBLOCK.
                    Ok(None) => return,
                    Ok(Some(c)) => {
                        let addr = c.peer_addr().unwrap();
                        write!(stderr(), "Succesful connection from {}\n", addr);
                        c
                    }
                    Err(e) => {
                        write!(stderr(), "Error while accepting: {}\n", e);
                        return;
                    }
                };

                event_loop.register(&client, Token(self.next_token));
                self.connections.insert(self.next_token, client);
                self.next_token += 1;
            }
            _  => {
                if events.is_writable() {
                    self.writable(event_loop, token);
                }
            }
        }
    }
}

fn main() {
    let matches = App::new("daytime")
        .author("Justinas Stankevicius")
        .arg(Arg::with_name("port").short("p").takes_value(true))
        .get_matches();

    let port = matches.value_of("port").unwrap_or("7")
        .parse::<u16>().ok().unwrap_or_else(|| {
            write!(stderr(), "An invalid port number supplied, defaulting to 7.\n");
            7
        });

    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let addr = SocketAddrV4::new(ip, port);
    let listener = TcpListener::bind(&SocketAddr::V4(addr)).unwrap();

    let mut event_loop = EventLoop::new().unwrap();
    event_loop.register(&listener, SERVER).unwrap();
    event_loop.run(&mut EchoHandler::new(listener)).unwrap();
}
<commit_msg>[daytime] Make the panic a bit nicer.<commit_after>use std::collections::BTreeMap;
use std::io::{stderr, Write};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

extern crate clap;
use clap::{App, Arg};

extern crate mio;
use mio::{EventLoop, EventSet, Handler, Token};
use mio::tcp::{TcpListener, TcpStream};

extern crate time;

const SERVER: Token = Token(0);

struct EchoHandler {
    connections: BTreeMap<usize, TcpStream>,
    listener: TcpListener,
    next_token: usize,
}

impl EchoHandler {
    fn new(l: TcpListener) -> EchoHandler {
        EchoHandler {
            connections: BTreeMap::new(),
            listener: l,
            next_token: 1
        }
    }

    fn writable(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
        {
            let conn = self.connections.get_mut(&token.as_usize()).unwrap();
            match write!(conn, "{}", time::now_utc().rfc822()) {
                Ok(_) => {
                    event_loop.deregister(conn).unwrap();
                    let addr = conn.peer_addr().unwrap();
                    write!(stderr(), "Sent the time to {} succesfully\n", addr);
                },
                Err(e) => {
                    write!(stderr(), "Error while writing: {}\n", e);
                }
            }
        }
        self.connections.remove(&token.as_usize()).unwrap();
    }
}

impl Handler for EchoHandler {
    type Message = ();
    type Timeout = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            SERVER => {
                let client = match self.listener.accept() {
                    // As per documentation, Ok(None) means WOULDBLOCK.
                    Ok(None) => return,
                    Ok(Some(c)) => {
                        let addr = c.peer_addr().unwrap();
                        write!(stderr(), "Succesful connection from {}\n", addr);
                        c
                    }
                    Err(e) => {
                        write!(stderr(), "Error while accepting: {}\n", e);
                        return;
                    }
                };

                event_loop.register(&client, Token(self.next_token));
                self.connections.insert(self.next_token, client);
                self.next_token += 1;
            }
            _  => {
                if events.is_writable() {
                    self.writable(event_loop, token);
                }
            }
        }
    }
}

fn main() {
    let matches = App::new("daytime")
        .author("Justinas Stankevicius")
        .arg(Arg::with_name("port").short("p").takes_value(true))
        .get_matches();

    let port = matches.value_of("port").unwrap_or("7")
        .parse::<u16>().ok().unwrap_or_else(|| {
            write!(stderr(), "An invalid port number supplied, defaulting to 7.\n");
            7
        });

    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let addr = SocketAddrV4::new(ip, port);
    let listener = TcpListener::bind(&SocketAddr::V4(addr))
        .unwrap_or_else(|e| { panic!("{}", e)});

    let mut event_loop = EventLoop::new().unwrap();
    event_loop.register(&listener, SERVER).unwrap();
    event_loop.run(&mut EchoHandler::new(listener)).unwrap();
}
<|endoftext|>


<commit_before>use self::streamql::statement;
pub use self::streamql::ParseError;
use super::row_builder::RowBuilder;
use super::schema::Type;

mod integration_tests;

use nom::{IResult,digit};
use nom::IResult::*;

peg_file! streamql("streamql.rustpeg");

pub fn parse_statement(query: &str) -> Result<Statement, ParseError> {
    statement(query)
}

#[derive(Debug)]
pub enum Statement {
    // Stream & Keys
    Insert(String, RowBuilder),
    // name
    DeclareStream(String, Vec<ColumnSpec>),
    DropStream,
    UseDatabase,
    Select,
    Subscribe,
}

#[derive(Debug)]
pub struct ColumnSpec {
    name: String,
//    ftype: Type,
}

impl ColumnSpec {
    fn new(name: String) -> ColumnSpec {
        ColumnSpec{name: name}
    }
}

#[cfg(test)]
mod test {
    use super::parse_statement;
    use super::Statement;
    use super::streamql::*;
    use db::value::Value;

    #[test]
    fn test_basic_insert() {

        let result = parse_statement("INSERT INTO test set k=1;").unwrap();

        if let Statement::Insert(stream, builder) = result {
            assert_eq!(stream, String::from("test"));
        } else {
            panic!("")
        }
        let x = "INSERT INTO test set k=1, v=2;";
        let result = parse_statement(x).unwrap();

    }

    #[test]
    fn test_parsing_with_quoted_string() {
        let result = parse_statement("INSERT INTO test set k='test';").unwrap();
        let result = parse_statement("INSERT INTO test set k='test my ''friend''';").unwrap();

    }

    #[test]
    fn test_int_parsing() {
        let tmp = int_value("42").unwrap();
    }

    #[test]
    fn test_basic_string_parsing() {
        string("hello this is a test").unwrap();
    }

    #[test]
    fn test_escaped_string() {
        let x = string("hello this is a ''test''").unwrap();
        assert_eq!(x, "hello this is a 'test'");
    }

    #[test]
    fn test_quoted_string() {
        let x = "'it''s mine'";
        let p = quoted_string(x).unwrap();
        assert_eq!(p, "it's mine");
    }

    #[test]
    fn value_string_parsing() {
        let x = "'hello'";
        if Value::from(x) == value(x).unwrap() {
            assert_eq!(x, "hello");
        }

    }

    #[test]
    fn declare_stream_parsing() {
        let x = "declare stream readings ( ts int, val int, s text );";
        let p = parse_statement(x).unwrap();
    }

    #[test]
    fn test_basic_parse_column_specification() {
        let x = "ts int";
        let p = column_spec(x).unwrap();

        let x = "ts text";
        let p = column_spec(x).unwrap();
    }

    #[test]
    fn test_column_spec_list() {
        let x = "ts int, val int, s text ";
        let p = column_spec_list(x).unwrap();
        assert_eq!(p.len(), 3);
    }
}

<commit_msg>more tests<commit_after>use self::streamql::statement;
pub use self::streamql::ParseError;
use super::row_builder::RowBuilder;
use super::schema::Type;

mod integration_tests;

use nom::{IResult,digit};
use nom::IResult::*;

peg_file! streamql("streamql.rustpeg");

pub fn parse_statement(query: &str) -> Result<Statement, ParseError> {
    statement(query)
}

#[derive(Debug)]
pub enum Statement {
    // Stream & Keys
    Insert(String, RowBuilder),
    // name
    DeclareStream(String, Vec<ColumnSpec>),
    DropStream,
    UseDatabase,
    Select,
    Subscribe,
}

#[derive(Debug)]
pub struct ColumnSpec {
    name: String,
//    ftype: Type,
}

impl ColumnSpec {
    fn new(name: String) -> ColumnSpec {
        ColumnSpec{name: name}
    }
}

#[cfg(test)]
mod test {
    use super::parse_statement;
    use super::Statement;
    use super::streamql::*;
    use db::value::Value;

    #[test]
    fn test_basic_insert() {

        let result = parse_statement("INSERT INTO test set k=1;").unwrap();

        if let Statement::Insert(stream, builder) = result {
            assert_eq!(stream, String::from("test"));
        } else {
            panic!("")
        }
        let x = "INSERT INTO test set k=1, v=2;";
        let result = parse_statement(x).unwrap();

    }

    #[test]
    fn test_parsing_with_quoted_string() {
        let result = parse_statement("INSERT INTO test set k='test';").unwrap();
        let result = parse_statement("INSERT INTO test set k='test my ''friend''';").unwrap();

    }

    #[test]
    fn test_int_parsing() {
        let tmp = int_value("42").unwrap();
    }

    #[test]
    fn test_basic_string_parsing() {
        string("hello this is a test").unwrap();
    }

    #[test]
    fn test_escaped_string() {
        let x = string("hello this is a ''test''").unwrap();
        assert_eq!(x, "hello this is a 'test'");
    }

    #[test]
    fn test_quoted_string() {
        let x = "'it''s mine'";
        let p = quoted_string(x).unwrap();
        assert_eq!(p, "it's mine");
    }

    #[test]
    fn value_string_parsing() {
        let x = "'hello'";
        if Value::from(x) == value(x).unwrap() {
            assert_eq!(x, "hello");
        }

    }

    #[test]
    fn declare_stream_parsing() {
        let x = "declare stream readings ( ts int, val int, s text );";
        let p = parse_statement(x).unwrap();
    }

    #[test]
    fn test_basic_parse_column_specification() {
        let x = "ts int";
        let p = column_spec(x).unwrap();

        let x = "ts text";
        let p = column_spec(x).unwrap();
    }

    #[test]
    fn test_column_spec_list() {
        let x = "ts int, val int, s text ";
        let p = column_spec_list(x).unwrap();

        assert_eq!(p.len(), 3);

        assert_eq!(p[0].name, "ts");
        assert_eq!(p[1].name, "val");
        assert_eq!(p[2].name, "s");
    }
}

<|endoftext|>


<commit_before>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
    {
      $Docfile:tt, $Alias:ident = $Real:ty;
      $( $Cfg:tt )*
    } => {
        #[doc = include_str!($Docfile)]
        $( $Cfg )*
        #[stable(feature = "raw_os", since = "1.1.0")]
        pub type $Alias = $Real;
    }
}

// To verify that the NonZero types in this file's macro invocations correspond
//
//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
    {
      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
      $( $Cfg:tt )*
    } => {
        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
        $( $Cfg )*
        pub type $NZAlias = $NZReal;
    }
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
#[doc(cfg(all()))]
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
#[doc(cfg(all()))]
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`usize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_size_t = usize;

/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_ssize_t = isize;
<commit_msg>Replace `std::os::raw::c_ssize_t` with `std::os::raw::c_ptrdiff_t`<commit_after>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg(test)]
mod tests;

use core::num::*;

macro_rules! type_alias_no_nz {
    {
      $Docfile:tt, $Alias:ident = $Real:ty;
      $( $Cfg:tt )*
    } => {
        #[doc = include_str!($Docfile)]
        $( $Cfg )*
        #[stable(feature = "raw_os", since = "1.1.0")]
        pub type $Alias = $Real;
    }
}

// To verify that the NonZero types in this file's macro invocations correspond
//
//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
//
// NB this does not check that the main c_* types are right.

macro_rules! type_alias {
    {
      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
      $( $Cfg:tt )*
    } => {
        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }

        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
        $( $Cfg )*
        pub type $NZAlias = $NZReal;
    }
}

type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8;
#[doc(cfg(all()))]
#[cfg(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
))]}
type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8;
#[doc(cfg(all()))]
#[cfg(not(any(
    all(
        target_os = "linux",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "hexagon",
            target_arch = "powerpc",
            target_arch = "powerpc64",
            target_arch = "s390x",
            target_arch = "riscv64",
            target_arch = "riscv32"
        )
    ),
    all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
    all(target_os = "l4re", target_arch = "x86_64"),
    all(
        target_os = "freebsd",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc",
            target_arch = "powerpc64"
        )
    ),
    all(
        target_os = "netbsd",
        any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
    ),
    all(target_os = "openbsd", target_arch = "aarch64"),
    all(
        target_os = "vxworks",
        any(
            target_arch = "aarch64",
            target_arch = "arm",
            target_arch = "powerpc64",
            target_arch = "powerpc"
        )
    ),
    all(target_os = "fuchsia", target_arch = "aarch64")
)))]}
type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
#[doc(cfg(all()))]
#[cfg(any(target_pointer_width = "32", windows))] }
type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
#[doc(cfg(all()))]
#[cfg(all(target_pointer_width = "64", not(windows)))] }
type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
type_alias_no_nz! { "float.md", c_float = f32; }
type_alias_no_nz! { "double.md", c_double = f64; }

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`usize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_size_t = usize;

/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_ptrdiff_t = isize;
<|endoftext|>


<commit_before>// A program that initializes the TUI and adds lines in the file (given as first argument) to it,
// with a draw() call after every line added.
//
// After adding all lines the program just quits.
//
// Useful for benchmarking TUI::draw().

use libtiny_tui::{Colors, TUI};
use libtiny_ui::*;
use std::fs::File;
use std::io::{BufRead, BufReader};
use tokio::runtime::current_thread::Runtime;

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    let file_path = &args[1];
    let file = File::open(file_path).unwrap();
    let file_buffered = BufReader::new(file);
    let lines = file_buffered.lines().map(Result::unwrap).collect();

    let mut executor = Runtime::new().unwrap();
    let (tui, _) = TUI::run(Colors::default(), &mut executor);

    tui.new_server_tab("test");
    tui.draw();

    executor.block_on(bench_task(tui, lines));

    // executor.run();
}

async fn bench_task(tui: TUI, lines: Vec<String>) {
    let msg_target = MsgTarget::Server { serv: "test" };
    let time = time::now();

    for line in &lines {
        tui.add_privmsg("server", line, time, &msg_target, false, false);
        tui.draw();
    }
}
<commit_msg>libtiny_tui: Fix bench example<commit_after>// A program that initializes the TUI and adds lines in the file (given as first argument) to it,
// with a draw() call after every line added.
//
// After adding all lines the program just quits.
//
// Useful for benchmarking TUI::draw().

use libtiny_tui::TUI;
use libtiny_ui::*;
use std::fs::File;
use std::io::{BufRead, BufReader};
use tokio::runtime::current_thread::Runtime;
use std::path::PathBuf;

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    let file_path = &args[1];
    let file = File::open(file_path).unwrap();
    let file_buffered = BufReader::new(file);
    let lines = file_buffered.lines().map(Result::unwrap).collect();

    let mut executor = Runtime::new().unwrap();
    let (tui, _) = TUI::run(PathBuf::from("../tiny/config.yml"), &mut executor);

    tui.new_server_tab("test");
    tui.draw();

    executor.block_on(bench_task(tui, lines));

    // executor.run();
}

async fn bench_task(tui: TUI, lines: Vec<String>) {
    let msg_target = MsgTarget::Server { serv: "test" };
    let time = time::now();

    for line in &lines {
        tui.add_privmsg("server", line, time, &msg_target, false, false);
        tui.draw();
    }
}
<|endoftext|>


<commit_before>extern crate ring;
extern crate udt;

use std::net::{UdpSocket, SocketAddr, IpAddr};
use std::str;
use std::fmt;
use udt::{UdtSocket, UdtError, UdtOpts, SocketType, SocketFamily};

// TODO config
const UDT_BUF_SIZE: i32 = 4096000;
pub const MAX_MESSAGE_SIZE: usize = 1024000;

pub mod crypto {
    use ring::aead;
    use ring::aead::{SealingKey, OpeningKey, Algorithm};
    use ring::rand::SystemRandom;
    static ALGORITHM: &'static Algorithm = &aead::AES_128_GCM;
    lazy_static! {
        static ref RAND: SystemRandom = SystemRandom::new();
    }

    pub struct Key {
        bytes: Vec<u8>,
        opening: OpeningKey,
        sealing: SealingKey,
    }

    impl Key {
        pub fn new(bytes: &[u8]) -> Key {
            Key {
                bytes: bytes.to_owned(),
                opening: OpeningKey::new(ALGORITHM, &bytes).unwrap(),
                sealing: SealingKey::new(ALGORITHM, &bytes).unwrap(),
            }
        }
    }

    impl Clone for Key {
        fn clone(&self) -> Key {
            Key::new(&self.bytes)
        }
    }

    #[derive(Clone)]
    pub struct Handler {
        _working_nonce_buf: [u8; 32],
        _working_seal_buf: Vec<u8>,
        key: Key,
    }

    pub fn gen_key() -> Vec<u8> {
        let rand = SystemRandom::new();
        let mut keybytes = vec![0u8; ALGORITHM.key_len()];
        RAND.fill(&mut keybytes);
        keybytes
    }

    impl Handler {
        pub fn new(key: &[u8]) -> Handler {
            Handler {
                _working_seal_buf: vec![0u8; super::MAX_MESSAGE_SIZE],
                _working_nonce_buf: [0u8; 32],
                key: Key::new(key),
            }
        }

        pub fn seal(&mut self, buf: &mut [u8], len: usize) -> Result<usize, ()> {
            let nonce_len = ALGORITHM.nonce_len();
            let max_suffix_len = ALGORITHM.max_overhead_len();

            assert!(nonce_len < u8::max_value() as usize,
                    "Uh, why is the nonce size this big?");

            assert!(len <= buf.len() - max_suffix_len,
                    "Buffer doesn't have enough suffix padding.");

            let mut nonce = &mut self._working_nonce_buf[..nonce_len];
            RAND.fill(&mut nonce).unwrap();

            let mut sealed = &mut self._working_seal_buf[..len + max_suffix_len];
            sealed[0..len].copy_from_slice(&buf[..len]);
            match aead::seal_in_place(&self.key.sealing,
                                      &nonce,
                                      &mut sealed,
                                      max_suffix_len,
                                      &[]) {
                Ok(seal_len) => {
                    buf[..nonce_len].copy_from_slice(&nonce[..]);
                    buf[nonce_len..nonce_len+seal_len].copy_from_slice(&sealed[..seal_len]);
                    Ok(nonce_len + seal_len)
                }
                Err(_) => {
                    Err(())
                }
            }
        }

        pub fn open(&mut self, buf: &mut [u8]) -> Result<usize, String> {
            let nonce_len = ALGORITHM.nonce_len();

            if buf.len() < nonce_len {
                return Err("msg not long enough to contain nonce".into());
            } else if buf.len() > super::MAX_MESSAGE_SIZE {
                return Err("max message size exceeded".into());
            }

            let nonce = &mut self._working_nonce_buf[..nonce_len];
            nonce.copy_from_slice(&buf[..nonce_len]);

            aead::open_in_place(&self.key.opening, &nonce, nonce_len, buf, &[])
                .map_err(|_| String::from("decrypt failed"))
        }
    }

    // Tests for the crypto module
    #[cfg(test)]
    mod test {

        #[test]
        fn raw_roundtrip() {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            rng.fill(&mut nonce_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; 1350];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];
            aead::seal_in_place(&key, &nonce_bytes,
                                &mut in_out, out_suffix_capacity,
                                &[]).unwrap();

            let opening_key = OpeningKey::new(super::ALGORITHM, &key_bytes).unwrap();
            let len = aead::open_in_place(&opening_key, &nonce_bytes,
                                          0, &mut in_out, &[]).unwrap();

            assert_eq!(len, 1350);
            assert_eq!(&in_out[..len], &data[..]);
        }

        #[test]
        fn roundtrip() {
            use ::rand;
            use ::rand::distributions::{IndependentSample, Range};
            // generate some data, seal it, and then make sure it unseals to the same thing
            let mut rng = rand::thread_rng();
            let between = Range::new(10, 10000);

            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let data_size: usize = between.ind_sample(&mut rng);
            let mut data = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            for i in 0..data_size {
                data[i] = rand::random();
            }

            let orig = data[..data_size].to_owned();

            let cipher_len = handler.seal(&mut data, data_size).unwrap();
            let decrypted_len = handler.open(&mut data[..cipher_len]).unwrap();
            assert_eq!(decrypted_len, data_size);
            assert_eq!(orig, &data[..decrypted_len], "original and decrypted don't match!");
        }

        #[test]
        fn key_sanity() {
            use std::collections::HashSet;

            let mut set: HashSet<Vec<u8>> = HashSet::with_capacity(10000);

            for _ in 0..10000 {
                let key = super::gen_key();
                assert!(set.insert(key));
            }
        }
    }

    #[cfg(all(feature = "nightly", test))]
    mod bench {
        extern crate test;
        const DATA_SIZE: usize = 1300;

        #[bench]
        fn bench_raw_seal(b: &mut test::Bencher) {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; DATA_SIZE];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];

            b.bytes = DATA_SIZE as u64;
            b.iter(|| {
                rng.fill(&mut nonce_bytes).unwrap();
                aead::seal_in_place(&key, &nonce_bytes, &mut in_out,
                                    out_suffix_capacity, &[]).unwrap()
            })
        }

        #[bench]
        fn bench_raw_open(b: &mut test::Bencher) {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            rng.fill(&mut nonce_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();
            let opening_key = OpeningKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; DATA_SIZE];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];

            b.bytes = DATA_SIZE as u64;

            let sealed_len = aead::seal_in_place(&key, &nonce_bytes, &mut in_out,
                                                 out_suffix_capacity, &[]).unwrap();
            b.iter(|| aead::open_in_place(&opening_key, &nonce_bytes,
                                               0, &mut in_out, &[]))
        }

        #[bench]
        fn bench_seal(b: &mut test::Bencher) {
            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let mut buf = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            b.bytes = DATA_SIZE as u64;
            b.iter(|| handler.seal(&mut buf, DATA_SIZE))
        }

        #[bench]
        fn bench_open(b: &mut test::Bencher) {
            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let mut buf = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            let sealed_len = handler.seal(&mut buf, DATA_SIZE).unwrap();
            b.bytes = DATA_SIZE as u64;
            b.iter(|| handler.open(&mut buf[..sealed_len]))
        }
    }
}

fn new_udt_socket() -> UdtSocket {
    udt::init();
    let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
    sock.setsockopt(UdtOpts::UDP_RCVBUF, UDT_BUF_SIZE).unwrap();
    sock.setsockopt(UdtOpts::UDP_SNDBUF, UDT_BUF_SIZE).unwrap();
    sock
}

fn send(sock: &UdtSocket, crypto: &mut crypto::Handler, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
    // FIXME don't unwrap, create an Error struct that can handle everything
    if let Ok(sealed_len) = crypto.seal(buf, len) {
        sock.sendmsg(&buf[..sealed_len]).map(|_| ())
    } else {
        Err(UdtError {
            err_code: -1,
            err_msg: "encryption failure".into(),
        })
    }
}

fn recv(sock: &UdtSocket, crypto: &mut crypto::Handler, buf: &mut [u8]) -> Result<usize, UdtError> {
    let size = try!(sock.recvmsg(buf));
    crypto.open(&mut buf[..size]).map_err(|_| {
        UdtError {
            err_code: -1,
            err_msg: String::from("decryption failure"),
        }
    })
}

#[derive(Copy,Clone)]
pub struct PortRange {
    start: u16,
    end: u16,
}

pub struct Server {
    pub ip_addr: IpAddr,
    pub port: u16,
    crypto: crypto::Handler,
    sock: UdtSocket,
}

pub struct Client {
    addr: SocketAddr,
    sock: UdtSocket,
    crypto: crypto::Handler,
}

pub struct ServerConnection {
    crypto: crypto::Handler,
    sock: UdtSocket,
}

impl Client {
    pub fn new(addr: SocketAddr, key: &[u8]) -> Client {
        let sock = new_udt_socket();
        Client {
            addr: addr,
            sock: sock,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn connect(&self) -> Result<(), UdtError> {
        self.sock.connect(self.addr)
    }
}

pub trait Transceiver {
    fn send(&mut self, buf: &mut [u8], len: usize) -> Result<(), UdtError>;
    fn recv(&mut self, buf: &mut [u8]) -> Result<usize, UdtError>;
    fn close(&self) -> Result<(), UdtError>;
}

impl Transceiver for Client {
    fn send(&mut self, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
        send(&self.sock, &mut self.crypto, buf, len)
    }

    fn recv(&mut self, buf: &mut [u8]) -> Result<usize, UdtError> {
        recv(&self.sock, &mut self.crypto, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl Transceiver for ServerConnection {
    fn send(&mut self, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
        send(&self.sock, &mut self.crypto, buf, len)
    }

    fn recv(&mut self, buf: &mut [u8]) -> Result<usize, UdtError> {
        recv(&self.sock, &mut self.crypto, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl Server {
    pub fn get_open_port(range: &PortRange) -> Result<u16, ()> {
        for p in range.start..range.end {
            if let Ok(_) = UdpSocket::bind(&format!("0.0.0.0:{}", p)[..]) {
                return Ok(p);
            }
        }
        Err(())
    }

    pub fn new(ip_addr: IpAddr, port: u16, key: &[u8]) -> Server {
        let sock = new_udt_socket();
        sock.bind(SocketAddr::new(ip_addr, port)).unwrap();
        Server {
            sock: sock,
            ip_addr: ip_addr,
            port: port,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn listen(&self) -> Result<(), UdtError> {
        self.sock.listen(2)
    }

    pub fn accept(&mut self) -> Result<ServerConnection, UdtError> {
        self.sock.accept().map(move |(sock, _)| {
            ServerConnection {
                crypto: self.crypto.clone(),
                sock: sock,
            }
        })
    }
}

impl ServerConnection {
    pub fn getpeer(&self) -> Result<SocketAddr, UdtError> {
        self.sock.getpeername()
    }
}

impl PortRange {
    fn new(start: u16, end: u16) -> Result<PortRange, String> {
        if start > end {
            Err("range end must be greater than or equal to start".into())
        } else {
            Ok(PortRange {
                start: start,
                end: end,
            })
        }
    }

    pub fn from(s: &str) -> Result<PortRange, String> {
        let sections: Vec<&str> = s.split('-').collect();
        if sections.len() != 2 {
            return Err("Range must be specified in the form of \"<start>-<end>\"".into());
        }
        let (start, end) = (sections[0].parse::<u16>(), sections[1].parse::<u16>());
        if start.is_err() || end.is_err() {
            return Err("improperly formatted port range".into());
        }
        PortRange::new(start.unwrap(), end.unwrap())
    }
}

impl fmt::Display for PortRange {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}-{}", self.start, self.end)
    }
}
<commit_msg>this is going to be fun to debug<commit_after>extern crate ring;
extern crate udt;

use std::net::{UdpSocket, SocketAddr, IpAddr};
use std::str;
use std::fmt;
use udt::{UdtSocket, UdtError, UdtOpts, SocketType, SocketFamily};

// TODO config
const UDT_BUF_SIZE: i32 = 4096000;
pub const MAX_MESSAGE_SIZE: usize = 1024000;

pub mod crypto {
    use ring::aead;
    use ring::aead::{SealingKey, OpeningKey, Algorithm};
    use ring::rand::SystemRandom;
    static ALGORITHM: &'static Algorithm = &aead::AES_128_GCM;
    lazy_static! {
        static ref RAND: SystemRandom = SystemRandom::new();
    }

    pub struct Key {
        bytes: Vec<u8>,
        opening: OpeningKey,
        sealing: SealingKey,
    }

    impl Key {
        pub fn new(bytes: &[u8]) -> Key {
            Key {
                bytes: bytes.to_owned(),
                opening: OpeningKey::new(ALGORITHM, &bytes).unwrap(),
                sealing: SealingKey::new(ALGORITHM, &bytes).unwrap(),
            }
        }
    }

    impl Clone for Key {
        fn clone(&self) -> Key {
            Key::new(&self.bytes)
        }
    }

    #[derive(Clone)]
    pub struct Handler {
        _working_nonce_buf: [u8; 32],
        _working_seal_buf: Vec<u8>,
        key: Key,
    }

    pub fn gen_key() -> Vec<u8> {
        let rand = SystemRandom::new();
        let mut keybytes = vec![0u8; ALGORITHM.key_len()];
        RAND.fill(&mut keybytes);
        keybytes
    }

    impl Handler {
        pub fn new(key: &[u8]) -> Handler {
            Handler {
                _working_seal_buf: vec![0u8; super::MAX_MESSAGE_SIZE],
                _working_nonce_buf: [0u8; 32],
                key: Key::new(key),
            }
        }

        pub fn seal(&mut self, buf: &mut [u8], len: usize) -> Result<usize, ()> {
            let nonce_len = ALGORITHM.nonce_len();
            let max_suffix_len = ALGORITHM.max_overhead_len();

            assert!(nonce_len < u8::max_value() as usize,
                    "Uh, why is the nonce size this big?");

            assert!(len <= buf.len() - max_suffix_len,
                    "Buffer doesn't have enough suffix padding.");

            let mut nonce = &mut self._working_nonce_buf[..nonce_len];
            RAND.fill(&mut nonce).unwrap();

            let mut sealed = &mut self._working_seal_buf[..len + max_suffix_len];
            sealed[0..len].copy_from_slice(&buf[..len]);
            match aead::seal_in_place(&self.key.sealing,
                                      &nonce,
                                      &mut sealed,
                                      max_suffix_len,
                                      &[]) {
                Ok(seal_len) => {
                    buf[..nonce_len].copy_from_slice(&nonce[..]);
                    buf[nonce_len..nonce_len+seal_len].copy_from_slice(&sealed[..seal_len]);
                    Ok(nonce_len + seal_len)
                }
                Err(_) => {
                    Err(())
                }
            }
        }

        pub fn open(&mut self, buf: &mut [u8]) -> Result<usize, String> {
            let nonce_len = ALGORITHM.nonce_len();

            if buf.len() < nonce_len {
                return Err("msg not long enough to contain nonce".into());
            } else if buf.len() > super::MAX_MESSAGE_SIZE {
                return Err("max message size exceeded".into());
            }

            let nonce = &mut self._working_nonce_buf[..nonce_len];
            nonce.copy_from_slice(&buf[..nonce_len]);

            aead::open_in_place(&self.key.opening, &nonce, nonce_len, buf, &[])
                .map_err(|_| String::from("decrypt failed"))
        }
    }

    // Tests for the crypto module
    #[cfg(test)]
    mod test {

        #[test]
        fn raw_roundtrip() {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            rng.fill(&mut nonce_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; 1350];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];
            aead::seal_in_place(&key, &nonce_bytes,
                                &mut in_out, out_suffix_capacity,
                                &[]).unwrap();

            let opening_key = OpeningKey::new(super::ALGORITHM, &key_bytes).unwrap();
            let len = aead::open_in_place(&opening_key, &nonce_bytes,
                                          0, &mut in_out, &[]).unwrap();

            assert_eq!(len, 1350);
            assert_eq!(&in_out[..len], &data[..]);
        }

        #[test]
        fn roundtrip() {
            use ::rand;
            use ::rand::distributions::{IndependentSample, Range};
            // generate some data, seal it, and then make sure it unseals to the same thing
            let mut rng = rand::thread_rng();
            let between = Range::new(10, 10000);

            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let data_size: usize = between.ind_sample(&mut rng);
            let mut data = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            for i in 0..data_size {
                data[i] = rand::random();
            }

            let orig = data[..data_size].to_owned();

            let cipher_len = handler.seal(&mut data, data_size).unwrap();
            let decrypted_len = handler.open(&mut data[..cipher_len]).unwrap();
            assert_eq!(decrypted_len, data_size);
            assert_eq!(orig, &data[..decrypted_len], "original and decrypted don't match!");
        }

        #[test]
        fn key_sanity() {
            use std::collections::HashSet;

            let mut set: HashSet<Vec<u8>> = HashSet::with_capacity(10000);

            for _ in 0..10000 {
                let key = super::gen_key();
                assert!(set.insert(key));
            }
        }
    }

    #[cfg(all(feature = "nightly", test))]
    mod bench {
        extern crate test;
        const DATA_SIZE: usize = 1300;

        #[bench]
        fn bench_raw_seal(b: &mut test::Bencher) {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; DATA_SIZE];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];

            b.bytes = DATA_SIZE as u64;
            b.iter(|| {
                rng.fill(&mut nonce_bytes).unwrap();
                aead::seal_in_place(&key, &nonce_bytes, &mut in_out,
                                    out_suffix_capacity, &[]).unwrap()
            })
        }

        #[bench]
        fn bench_raw_open(b: &mut test::Bencher) {
            use ring::aead;
            use ring::aead::{SealingKey, OpeningKey, Algorithm};
            use ring::rand::{SystemRandom, SecureRandom};

            let rng = SystemRandom::new();
            let mut key_bytes = vec![0u8; super::ALGORITHM.key_len()];
            let mut nonce_bytes = vec![0u8; super::ALGORITHM.nonce_len()];
            rng.fill(&mut key_bytes).unwrap();
            rng.fill(&mut nonce_bytes).unwrap();
            let key = SealingKey::new(super::ALGORITHM, &key_bytes).unwrap();
            let opening_key = OpeningKey::new(super::ALGORITHM, &key_bytes).unwrap();

            let data = [1u8; DATA_SIZE];
            let out_suffix_capacity = super::ALGORITHM.max_overhead_len();
            let mut in_out = vec![1u8; data.len() + out_suffix_capacity];

            b.bytes = DATA_SIZE as u64;

            let sealed_len = aead::seal_in_place(&key, &nonce_bytes, &mut in_out,
                                                 out_suffix_capacity, &[]).unwrap();
            b.iter(|| aead::open_in_place(&opening_key, &nonce_bytes,
                                               0, &mut in_out, &[]))
        }

        #[bench]
        fn bench_seal(b: &mut test::Bencher) {
            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let mut buf = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            b.bytes = DATA_SIZE as u64;
            b.iter(|| handler.seal(&mut buf, DATA_SIZE))
        }

        #[bench]
        fn bench_open(b: &mut test::Bencher) {
            let key = super::gen_key();
            let mut handler = super::Handler::new(&key);
            let mut buf = vec![0u8; super::super::MAX_MESSAGE_SIZE];
            let sealed_len = handler.seal(&mut buf, DATA_SIZE).unwrap();
            b.bytes = DATA_SIZE as u64;
            b.iter(|| handler.open(&mut buf[..sealed_len]))
        }
    }
}

fn new_udt_socket() -> UdtSocket {
    udt::init();
    let sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
    sock.setsockopt(UdtOpts::UDP_RCVBUF, UDT_BUF_SIZE).unwrap();
    sock.setsockopt(UdtOpts::UDP_SNDBUF, UDT_BUF_SIZE).unwrap();
    sock
}

fn send(sock: &UdtSocket, crypto: &mut crypto::Handler, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
    // FIXME don't unwrap, create an Error struct that can handle everything
    if let Ok(sealed_len) = crypto.seal(buf, len) {
        sock.sendmsg(&buf[..sealed_len]).map(|_| ())
    } else {
        Err(UdtError {
            err_code: -1,
            err_msg: "encryption failure".into(),
        })
    }
}

fn recv(sock: &UdtSocket, crypto: &mut crypto::Handler, buf: &mut [u8]) -> Result<usize, UdtError> {
    let size = try!(sock.recvmsg(buf));
    crypto.open(&mut buf[..size]).map_err(|_| {
        UdtError {
            err_code: -1,
            err_msg: String::from("decryption failure"),
        }
    })
}

#[derive(Copy,Clone)]
pub struct PortRange {
    start: u16,
    end: u16,
}

pub struct Server {
    pub ip_addr: IpAddr,
    pub port: u16,
    crypto: crypto::Handler,
    sock: UdtSocket,
}

pub struct Client {
    addr: SocketAddr,
    sock: UdtSocket,
    crypto: crypto::Handler,
}

pub struct ServerConnection {
    crypto: crypto::Handler,
    sock: UdtSocket,
}

impl Client {
    pub fn new(addr: SocketAddr, key: &[u8]) -> Client {
        let sock = new_udt_socket();
        Client {
            addr: addr,
            sock: sock,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn connect(&self) -> Result<(), UdtError> {
        self.sock.connect(self.addr)
    }
}

pub trait Transceiver {
    fn send(&mut self, buf: &mut [u8], len: usize) -> Result<(), UdtError>;
    fn recv(&mut self, buf: &mut [u8]) -> Result<usize, UdtError>;
    fn close(&self) -> Result<(), UdtError>;
}

impl Transceiver for Client {
    fn send(&mut self, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
        send(&self.sock, &mut self.crypto, buf, len)
    }

    fn recv(&mut self, buf: &mut [u8]) -> Result<usize, UdtError> {
        recv(&self.sock, &mut self.crypto, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl Transceiver for ServerConnection {
    fn send(&mut self, buf: &mut [u8], len: usize) -> Result<(), UdtError> {
        send(&self.sock, &mut self.crypto, buf, len)
    }

    fn recv(&mut self, buf: &mut [u8]) -> Result<usize, UdtError> {
        recv(&self.sock, &mut self.crypto, buf)
    }

    fn close(&self) -> Result<(), UdtError> {
        self.sock.close()
    }
}

impl Server {
    pub fn get_open_port(range: &PortRange) -> Result<u16, ()> {
        for p in range.start..range.end {
            if let Ok(_) = UdpSocket::bind(&format!("0.0.0.0:{}", p)[..]) {
                return Ok(p);
            }
        }
        Err(())
    }

    pub fn new(ip_addr: IpAddr, port: u16, key: &[u8]) -> Server {
        let sock = new_udt_socket();
        sock.bind(SocketAddr::new(ip_addr, port)).unwrap();
        Server {
            sock: sock,
            ip_addr: ip_addr,
            port: port,
            crypto: crypto::Handler::new(key),
        }
    }

    pub fn listen(&self) -> Result<(), UdtError> {
        self.sock.listen(1)
    }

    pub fn accept(&mut self) -> Result<ServerConnection, UdtError> {
        self.sock.accept().map(move |(sock, _)| {
            ServerConnection {
                crypto: self.crypto.clone(),
                sock: sock,
            }
        })
    }
}

impl ServerConnection {
    pub fn getpeer(&self) -> Result<SocketAddr, UdtError> {
        self.sock.getpeername()
    }
}

impl PortRange {
    fn new(start: u16, end: u16) -> Result<PortRange, String> {
        if start > end {
            Err("range end must be greater than or equal to start".into())
        } else {
            Ok(PortRange {
                start: start,
                end: end,
            })
        }
    }

    pub fn from(s: &str) -> Result<PortRange, String> {
        let sections: Vec<&str> = s.split('-').collect();
        if sections.len() != 2 {
            return Err("Range must be specified in the form of \"<start>-<end>\"".into());
        }
        let (start, end) = (sections[0].parse::<u16>(), sections[1].parse::<u16>());
        if start.is_err() || end.is_err() {
            return Err("improperly formatted port range".into());
        }
        PortRange::new(start.unwrap(), end.unwrap())
    }
}

impl fmt::Display for PortRange {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}-{}", self.start, self.end)
    }
}
<|endoftext|>


<commit_before>//! An example of using dsp-chain's `Graph` type to create a simple Synthesiser with 3 sine wave
//! oscillators.

use dsp::sample::ToFrameSliceMut;
use dsp::{Frame, FromSample, Graph, Node, Sample, Walker};
use portaudio as pa;

/// SoundStream is currently generic over i8, i32 and f32. Feel free to change it!
type Output = f32;

type Phase = f64;
type Frequency = f64;
type Volume = f32;

const CHANNELS: usize = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;

const A5_HZ: Frequency = 440.0;
const D5_HZ: Frequency = 587.33;
const F5_HZ: Frequency = 698.46;

fn main() -> Result<(), pa::Error> {
    // Construct our dsp graph.
    let mut graph = Graph::new();

    // Construct our fancy Synth and add it to the graph!
    let synth = graph.add_node(DspNode::Synth);

    // Connect a few oscillators to the synth.
    let (_, oscillator_a) = graph.add_input(DspNode::Oscillator(0.0, A5_HZ, 0.2), synth);
    graph.add_input(DspNode::Oscillator(0.0, D5_HZ, 0.1), synth);
    graph.add_input(DspNode::Oscillator(0.0, F5_HZ, 0.15), synth);

    // If adding a connection between two nodes would create a cycle, Graph will return an Err.
    if let Err(err) = graph.add_connection(synth, oscillator_a) {
        println!(
            "Testing for cycle error: {:?}",
            std::error::Error::description(&err)
        );
    }

    // Set the synth as the master node for the graph.
    graph.set_master(Some(synth));

    // We'll use this to count down from three seconds and then break from the loop.
    let mut timer: f64 = 3.0;

    // This will be used to determine the delta time between calls to the callback.
    let mut prev_time = None;

    // The callback we'll use to pass to the Stream. It will request audio from our dsp_graph.
    let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
        let buffer: &mut [[Output; CHANNELS]] = buffer.to_frame_slice_mut().unwrap();
        dsp::slice::equilibrium(buffer);
        graph.audio_requested(buffer, SAMPLE_HZ);

        let last_time = prev_time.unwrap_or(time.current);
        let dt = time.current - last_time;
        timer -= dt;
        prev_time = Some(time.current);

        // Traverse inputs or outputs of a node with the following pattern.
        let mut inputs = graph.inputs(synth);
        while let Some(input_idx) = inputs.next_node(&graph) {
            if let DspNode::Oscillator(_, ref mut pitch, _) = graph[input_idx] {
                // Pitch down our oscillators for fun.
                *pitch -= 0.1;
            }
        }

        if timer >= 0.0 {
            pa::Continue
        } else {
            pa::Complete
        }
    };

    // Construct PortAudio and the stream.
    let pa = pa::PortAudio::new()?;
    let settings =
        pa.default_output_stream_settings::<Output>(CHANNELS as i32, SAMPLE_HZ, FRAMES)?;
    let mut stream = pa.open_non_blocking_stream(settings, callback)?;
    stream.start()?;

    // Wait for our stream to finish.
    while let true = stream.is_active()? {
        std::thread::sleep(::std::time::Duration::from_millis(16));
    }

    Ok(())
}

/// Our type for which we will implement the `Dsp` trait.
#[derive(Debug)]
enum DspNode {
    /// Synth will be our demonstration of a master GraphNode.
    Synth,
    /// Oscillator will be our generator type of node, meaning that we will override
    /// the way it provides audio via its `audio_requested` method.
    Oscillator(Phase, Frequency, Volume),
}

impl Node<[Output; CHANNELS]> for DspNode {
    /// Here we'll override the audio_requested method and generate a sine wave.
    fn audio_requested(&mut self, buffer: &mut [[Output; CHANNELS]], sample_hz: f64) {
        match *self {
            DspNode::Synth => (),
            DspNode::Oscillator(ref mut phase, frequency, volume) => {
                dsp::slice::map_in_place(buffer, |_| {
                    let val = sine_wave(*phase, volume);
                    *phase += frequency / sample_hz;
                    Frame::from_fn(|_| val)
                });
            }
        }
    }
}

/// Return a sine wave for the given phase.
fn sine_wave<S: Sample>(phase: Phase, volume: Volume) -> S
where
    S: Sample + FromSample<f32>,
{
    use std::f64::consts::PI;
    ((phase * PI * 2.0).sin() as f32 * volume).to_sample::<S>()
}
<commit_msg>update synth example<commit_after>//! An example of using dsp-chain's `Graph` type to create a simple Synthesiser with 3 sine wave
//! oscillators.

use sample::ToFrameSliceMut;
use dsp::{Frame, FromSample, Graph, Node, Sample, Walker};
use portaudio as pa;

/// SoundStream is currently generic over i8, i32 and f32. Feel free to change it!
type Output = f32;

type Phase = f64;
type Frequency = f64;
type Volume = f32;

const CHANNELS: usize = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;

const A5_HZ: Frequency = 440.0;
const D5_HZ: Frequency = 587.33;
const F5_HZ: Frequency = 698.46;

fn main() -> Result<(), pa::Error> {
    // Construct our dsp graph.
    let mut graph = Graph::new();

    // Construct our fancy Synth and add it to the graph!
    let synth = graph.add_node(DspNode::Synth);

    // Connect a few oscillators to the synth.
    let (_, oscillator_a) = graph.add_input(DspNode::Oscillator(0.0, A5_HZ, 0.2), synth);
    graph.add_input(DspNode::Oscillator(0.0, D5_HZ, 0.1), synth);
    graph.add_input(DspNode::Oscillator(0.0, F5_HZ, 0.15), synth);

    // If adding a connection between two nodes would create a cycle, Graph will return an Err.
    if let Err(err) = graph.add_connection(synth, oscillator_a) {
        println!(
            "Testing for cycle error: {:?}",
            std::error::Error::description(&err)
        );
    }

    // Set the synth as the master node for the graph.
    graph.set_master(Some(synth));

    // We'll use this to count down from three seconds and then break from the loop.
    let mut timer: f64 = 3.0;

    // This will be used to determine the delta time between calls to the callback.
    let mut prev_time = None;

    // The callback we'll use to pass to the Stream. It will request audio from our dsp_graph.
    let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
        let buffer: &mut [[Output; CHANNELS]] = buffer.to_frame_slice_mut().unwrap();
        dsp::slice::equilibrium(buffer);
        graph.audio_requested(buffer, SAMPLE_HZ);

        let last_time = prev_time.unwrap_or(time.current);
        let dt = time.current - last_time;
        timer -= dt;
        prev_time = Some(time.current);

        // Traverse inputs or outputs of a node with the following pattern.
        let mut inputs = graph.inputs(synth);
        while let Some(input_idx) = inputs.next_node(&graph) {
            if let DspNode::Oscillator(_, ref mut pitch, _) = graph[input_idx] {
                // Pitch down our oscillators for fun.
                *pitch -= 0.1;
            }
        }

        if timer >= 0.0 {
            pa::Continue
        } else {
            pa::Complete
        }
    };

    // Construct PortAudio and the stream.
    let pa = pa::PortAudio::new()?;
    let settings =
        pa.default_output_stream_settings::<Output>(CHANNELS as i32, SAMPLE_HZ, FRAMES)?;
    let mut stream = pa.open_non_blocking_stream(settings, callback)?;
    stream.start()?;

    // Wait for our stream to finish.
    while let true = stream.is_active()? {
        std::thread::sleep(::std::time::Duration::from_millis(16));
    }

    Ok(())
}

/// Our type for which we will implement the `Dsp` trait.
#[derive(Debug)]
enum DspNode {
    /// Synth will be our demonstration of a master GraphNode.
    Synth,
    /// Oscillator will be our generator type of node, meaning that we will override
    /// the way it provides audio via its `audio_requested` method.
    Oscillator(Phase, Frequency, Volume),
}

impl Node<[Output; CHANNELS]> for DspNode {
    /// Here we'll override the audio_requested method and generate a sine wave.
    fn audio_requested(&mut self, buffer: &mut [[Output; CHANNELS]], sample_hz: f64) {
        match *self {
            DspNode::Synth => (),
            DspNode::Oscillator(ref mut phase, frequency, volume) => {
                dsp::slice::map_in_place(buffer, |_| {
                    let val = sine_wave(*phase, volume);
                    *phase += frequency / sample_hz;
                    Frame::from_fn(|_| val)
                });
            }
        }
    }
}

/// Return a sine wave for the given phase.
fn sine_wave<S: Sample>(phase: Phase, volume: Volume) -> S
where
    S: Sample + FromSample<f32>,
{
    use std::f64::consts::PI;
    ((phase * PI * 2.0).sin() as f32 * volume).to_sample::<S>()
}
<|endoftext|>


<commit_before>//! Name resolution algorithm
use std::sync::Arc;

use rustc_hash::FxHashMap;

use ra_syntax::{
    SmolStr, SyntaxKind::{self, *},
    ast::{self, NameOwner, AstNode}
};

use crate::{
    loc2id::{DefId, DefLoc},
    descriptors::{
        DescriptorDatabase,
        module::{ModuleId, ModuleTree},
    },
    syntax_ptr::{LocalSyntaxPtr, SyntaxPtr},
    input::SourceRootId,
};

/// A set of items and imports declared inside a module, without relation to
/// other modules.
///
/// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default)]
struct InputModuleItems {
    items: Vec<ModuleItem>,
    glob_imports: Vec<Path>,
    imports: Vec<Path>,
}

#[derive(Debug, Clone)]
struct Path {
    kind: PathKind,
    segments: Vec<(LocalSyntaxPtr, SmolStr)>,
}

#[derive(Debug, Clone, Copy)]
enum PathKind {
    Abs,
    Self_,
    Super,
    Crate,
}

#[derive(Debug)]
struct ItemMap {
    per_module: FxHashMap<ModuleId, ModuleItems>,
}

#[derive(Debug, Default)]
struct ModuleItems {
    items: FxHashMap<SmolStr, DefId>,
    import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Namespace {
    Types,
    Values,
}

#[derive(Debug)]
struct PerNs<T> {
    types: Option<T>,
    values: Option<T>,
}

#[derive(Debug)]
struct ModuleItem {
    ptr: LocalSyntaxPtr,
    name: SmolStr,
    kind: SyntaxKind,
    vis: Vis,
}

#[derive(Debug)]
enum Vis {
    Priv,
    Other,
}

impl InputModuleItems {
    fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems {
        let mut res = InputModuleItems::default();
        for item in items {
            res.add_item(item);
        }
        res
    }

    fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> {
        match item {
            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::ImplItem(it) => {
                // impls don't define items
            }
            ast::ModuleItem::UseItem(it) => self.add_use_item(it),
            ast::ModuleItem::ExternCrateItem(it) => (),
            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?),
        }
        Some(())
    }

    fn add_use_item(&mut self, item: ast::UseItem) {
        if let Some(tree) = item.use_tree() {
            self.add_use_tree(None, tree);
        }
    }

    fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) {
        if let Some(use_tree_list) = tree.use_tree_list() {
            let prefix = match tree.path() {
                None => prefix,
                Some(path) => match convert_path(prefix, path) {
                    Some(it) => Some(it),
                    None => return, // TODO: report errors somewhere
                },
            };
            for tree in use_tree_list.use_trees() {
                self.add_use_tree(prefix.clone(), tree);
            }
        } else {
            if let Some(path) = tree.path() {
                if let Some(path) = convert_path(prefix, path) {
                    if tree.has_star() {
                        &mut self.glob_imports
                    } else {
                        &mut self.imports
                    }
                    .push(path);
                }
            }
        }
    }
}

fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
    let prefix = if let Some(qual) = path.qualifier() {
        Some(convert_path(prefix, qual)?)
    } else {
        None
    };
    let segment = path.segment()?;
    let res = match segment.kind()? {
        ast::PathSegmentKind::Name(name) => {
            let mut res = prefix.unwrap_or_else(|| Path {
                kind: PathKind::Abs,
                segments: Vec::with_capacity(1),
            });
            let ptr = LocalSyntaxPtr::new(name.syntax());
            res.segments.push((ptr, name.text()));
            res
        }
        ast::PathSegmentKind::CrateKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Crate,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SelfKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Self_,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SuperKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Super,
                segments: Vec::new(),
            }
        }
    };
    Some(res)
}

impl ModuleItem {
    fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
        let name = item.name()?.text();
        let ptr = LocalSyntaxPtr::new(item.syntax());
        let kind = item.syntax().kind();
        let vis = Vis::Other;
        let res = ModuleItem {
            ptr,
            name,
            kind,
            vis,
        };
        Some(res)
    }
}

struct Resolver<'a, DB> {
    db: &'a DB,
    source_root: SourceRootId,
    module_tree: Arc<ModuleTree>,
    input: FxHashMap<ModuleId, InputModuleItems>,
    result: ItemMap,
}

impl<'a, DB> Resolver<'a, DB>
where
    DB: DescriptorDatabase,
{
    fn resolve(&mut self) {
        for (&module_id, items) in self.input.iter() {
            populate_module(
                self.db,
                self.source_root,
                &*self.module_tree,
                &mut self.result,
                module_id,
                items,
            )
        }
    }
}

fn populate_module(
    db: &impl DescriptorDatabase,
    source_root: SourceRootId,
    module_tree: &ModuleTree,
    item_map: &mut ItemMap,
    module_id: ModuleId,
    input: &InputModuleItems,
) {
    let file_id = module_id.source(module_tree).file_id();

    let mut module_items = ModuleItems::default();

    for item in input.items.iter() {
        if item.kind == MODULE {
            // handle submodules separatelly
            continue;
        }
        let ptr = item.ptr.into_global(file_id);
        let def_loc = DefLoc::Item { ptr };
        let def_id = db.id_maps().def_id(def_loc);
        module_items.items.insert(item.name.clone(), def_id);
    }

    for (name, mod_id) in module_id.children(module_tree) {
        let def_loc = DefLoc::Module {
            id: mod_id,
            source_root,
        };
    }

    item_map.per_module.insert(module_id, module_items);
}
<commit_msg>move to method<commit_after>//! Name resolution algorithm
use std::sync::Arc;

use rustc_hash::FxHashMap;

use ra_syntax::{
    SmolStr, SyntaxKind::{self, *},
    ast::{self, NameOwner, AstNode}
};

use crate::{
    loc2id::{DefId, DefLoc},
    descriptors::{
        DescriptorDatabase,
        module::{ModuleId, ModuleTree},
    },
    syntax_ptr::{LocalSyntaxPtr, SyntaxPtr},
    input::SourceRootId,
};

/// A set of items and imports declared inside a module, without relation to
/// other modules.
///
/// This stands in-between raw syntax and name resolution and alow us to avoid
/// recomputing name res: if `InputModuleItems` are the same, we can avoid
/// running name resolution.
#[derive(Debug, Default)]
struct InputModuleItems {
    items: Vec<ModuleItem>,
    glob_imports: Vec<Path>,
    imports: Vec<Path>,
}

#[derive(Debug, Clone)]
struct Path {
    kind: PathKind,
    segments: Vec<(LocalSyntaxPtr, SmolStr)>,
}

#[derive(Debug, Clone, Copy)]
enum PathKind {
    Abs,
    Self_,
    Super,
    Crate,
}

#[derive(Debug)]
struct ItemMap {
    per_module: FxHashMap<ModuleId, ModuleItems>,
}

#[derive(Debug, Default)]
struct ModuleItems {
    items: FxHashMap<SmolStr, DefId>,
    import_resolutions: FxHashMap<LocalSyntaxPtr, DefId>,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
enum Namespace {
    Types,
    Values,
}

#[derive(Debug)]
struct PerNs<T> {
    types: Option<T>,
    values: Option<T>,
}

#[derive(Debug)]
struct ModuleItem {
    ptr: LocalSyntaxPtr,
    name: SmolStr,
    kind: SyntaxKind,
    vis: Vis,
}

#[derive(Debug)]
enum Vis {
    Priv,
    Other,
}

impl InputModuleItems {
    fn new<'a>(items: impl Iterator<Item = ast::ModuleItem<'a>>) -> InputModuleItems {
        let mut res = InputModuleItems::default();
        for item in items {
            res.add_item(item);
        }
        res
    }

    fn add_item(&mut self, item: ast::ModuleItem) -> Option<()> {
        match item {
            ast::ModuleItem::StructDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::EnumDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::FnDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TraitDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::TypeDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::ImplItem(it) => {
                // impls don't define items
            }
            ast::ModuleItem::UseItem(it) => self.add_use_item(it),
            ast::ModuleItem::ExternCrateItem(it) => (),
            ast::ModuleItem::ConstDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::StaticDef(it) => self.items.push(ModuleItem::new(it)?),
            ast::ModuleItem::Module(it) => self.items.push(ModuleItem::new(it)?),
        }
        Some(())
    }

    fn add_use_item(&mut self, item: ast::UseItem) {
        if let Some(tree) = item.use_tree() {
            self.add_use_tree(None, tree);
        }
    }

    fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) {
        if let Some(use_tree_list) = tree.use_tree_list() {
            let prefix = match tree.path() {
                None => prefix,
                Some(path) => match convert_path(prefix, path) {
                    Some(it) => Some(it),
                    None => return, // TODO: report errors somewhere
                },
            };
            for tree in use_tree_list.use_trees() {
                self.add_use_tree(prefix.clone(), tree);
            }
        } else {
            if let Some(path) = tree.path() {
                if let Some(path) = convert_path(prefix, path) {
                    if tree.has_star() {
                        &mut self.glob_imports
                    } else {
                        &mut self.imports
                    }
                    .push(path);
                }
            }
        }
    }
}

fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> {
    let prefix = if let Some(qual) = path.qualifier() {
        Some(convert_path(prefix, qual)?)
    } else {
        None
    };
    let segment = path.segment()?;
    let res = match segment.kind()? {
        ast::PathSegmentKind::Name(name) => {
            let mut res = prefix.unwrap_or_else(|| Path {
                kind: PathKind::Abs,
                segments: Vec::with_capacity(1),
            });
            let ptr = LocalSyntaxPtr::new(name.syntax());
            res.segments.push((ptr, name.text()));
            res
        }
        ast::PathSegmentKind::CrateKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Crate,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SelfKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Self_,
                segments: Vec::new(),
            }
        }
        ast::PathSegmentKind::SuperKw => {
            if prefix.is_some() {
                return None;
            }
            Path {
                kind: PathKind::Super,
                segments: Vec::new(),
            }
        }
    };
    Some(res)
}

impl ModuleItem {
    fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> {
        let name = item.name()?.text();
        let ptr = LocalSyntaxPtr::new(item.syntax());
        let kind = item.syntax().kind();
        let vis = Vis::Other;
        let res = ModuleItem {
            ptr,
            name,
            kind,
            vis,
        };
        Some(res)
    }
}

struct Resolver<'a, DB> {
    db: &'a DB,
    input: &'a FxHashMap<ModuleId, InputModuleItems>,
    source_root: SourceRootId,
    module_tree: Arc<ModuleTree>,
    result: ItemMap,
}

impl<'a, DB> Resolver<'a, DB>
where
    DB: DescriptorDatabase,
{
    fn resolve(&mut self) {
        for (&module_id, items) in self.input.iter() {
            self.populate_module(
                module_id,
                items,
            )
        }
    }

    fn populate_module(
        &mut self,
        module_id: ModuleId,
        input: &InputModuleItems,
    ) {
        let file_id = module_id.source(&self.module_tree).file_id();

        let mut module_items = ModuleItems::default();

        for item in input.items.iter() {
            if item.kind == MODULE {
                // handle submodules separatelly
                continue;
            }
            let ptr = item.ptr.into_global(file_id);
            let def_loc = DefLoc::Item { ptr };
            let def_id = self.db.id_maps().def_id(def_loc);
            module_items.items.insert(item.name.clone(), def_id);
        }

        for (name, mod_id) in module_id.children(&self.module_tree) {
            let def_loc = DefLoc::Module {
                id: mod_id,
                source_root: self.source_root,
            };
            let def_id = self.db.id_maps().def_id(def_loc);
            module_items.items.insert(name, def_id);
        }

        self.result.per_module.insert(module_id, module_items);
    }
}

<|endoftext|>