<commit_before>use regex::Regex;
use reqwest;
use serde_json;

use web::data::SolrTermSummary;
use web::config::Config;

pub struct Search {
    solr_url: String,
    close_synonym_boost: f32,
    distant_synonym_boost: f32,
}

#[derive(Deserialize, Debug)]
struct SolrResponse {
    pub docs: Vec<SolrTermSummary>,
}

#[derive(Deserialize, Debug)]
struct SolrResponseContainer {
    pub response: SolrResponse,
}

impl Search {
    pub fn new(config: &Config) -> Search {
        Search {
            solr_url: config.server.solr_url.clone(),
            close_synonym_boost: config.server.close_synonym_boost,
            distant_synonym_boost: config.server.distant_synonym_boost,
        }
    }

    fn get_query_part(&self, words: &Vec<String>) -> String {
        let mut ret = String::new();

        let words_length = words.len();

        for (i, word) in words.iter().enumerate() {
            if i == words_length - 1 {
                ret += &format!("{} {}~0.8 {}*", word, word, word);
            } else {
                ret += &format!("{} {}~0.8 ", word, word);
            }
        }

        ret
    }

    pub fn term_complete(&self, cv_name: &str, q: &str)
                         -> Result<Vec<SolrTermSummary>, reqwest::Error>
    {
        let mut terms_url =
            self.solr_url.to_owned() + "/terms/select?wt=json&q=";

        let termid_re_string = r"(?P<prefix>[\w_]+):(?P<accession>\d+)";
        let termid_re = Regex::new(termid_re_string).unwrap();

        let parent_re_string = r"^\[".to_owned() + termid_re_string + r"\]$";
        let parent_re = Regex::new(&parent_re_string).unwrap();

        let maybe_captures = parent_re.captures(cv_name);

        if let Some(captures) = maybe_captures {
            let prefix = captures.name("prefix").unwrap();
            let accession = captures.name("accession").unwrap();
            terms_url += &format!("(interesting_parents:{}\\:{} OR id:{}\\:{})",
                                  prefix, accession, prefix, accession);
        } else {
            terms_url += "cv_name:";
            terms_url += cv_name;
        }

        if let Some(captures) = termid_re.captures(q) {
            let prefix = captures.name("prefix").unwrap();
            let accession = captures.name("accession").unwrap();
            terms_url += " AND id:";
            terms_url += prefix;
            terms_url += r"\:";
            terms_url += accession;
        } else {
            terms_url += " AND (name:(";

            let clean_words: Vec<String> =
                Regex::new(r"(\w+)").unwrap().captures_iter(q)
                .map(|cap| cap.at(1).unwrap().to_owned()).collect();

            if clean_words.len() == 0 {
                return Ok(vec![]);
            }

            let clean_words_length = clean_words.len();

            for (i, word) in clean_words.iter().enumerate() {
                if i == clean_words_length - 1 {
                    terms_url += &format!("{} {}~0.8 {}*", word, word, word);
                } else {
                    terms_url += &format!("{} {}~0.8 ", word, word);
                }
            }

            let query_part = self.get_query_part(&clean_words);

            terms_url += &format!(") OR close_synonym_words:({})^{} OR distant_synonym_words:({})^{})",
                                  query_part, self.close_synonym_boost,
                                  query_part, self.distant_synonym_boost);
        }
        print!("{:?}\n", terms_url);

        let res = reqwest::get(&terms_url)?;

        println!("Status: {}", res.status());
        println!("Headers:\n{}", res.headers());

        match serde_json::from_reader(res) {
            Ok(solr_response_container) => {
                let container: SolrResponseContainer = solr_response_container;
                Ok(container.response.docs)
            },
            Err(err) => {
                panic!(format!("{:?}", err));
            }
        }
    }
}
<commit_msg>Don't split search words on hyphens<commit_after>use regex::Regex;
use reqwest;
use serde_json;

use web::data::SolrTermSummary;
use web::config::Config;

pub struct Search {
    solr_url: String,
    close_synonym_boost: f32,
    distant_synonym_boost: f32,
}

#[derive(Deserialize, Debug)]
struct SolrResponse {
    pub docs: Vec<SolrTermSummary>,
}

#[derive(Deserialize, Debug)]
struct SolrResponseContainer {
    pub response: SolrResponse,
}

impl Search {
    pub fn new(config: &Config) -> Search {
        Search {
            solr_url: config.server.solr_url.clone(),
            close_synonym_boost: config.server.close_synonym_boost,
            distant_synonym_boost: config.server.distant_synonym_boost,
        }
    }

    fn get_query_part(&self, words: &Vec<String>) -> String {
        let mut ret = String::new();

        let words_length = words.len();

        for (i, word) in words.iter().enumerate() {
            if i == words_length - 1 {
                ret += &format!("{} {}~0.8 {}*", word, word, word);
            } else {
                ret += &format!("{} {}~0.8 ", word, word);
            }
        }

        ret
    }

    pub fn term_complete(&self, cv_name: &str, q: &str)
                         -> Result<Vec<SolrTermSummary>, reqwest::Error>
    {
        let mut terms_url =
            self.solr_url.to_owned() + "/terms/select?wt=json&q=";

        let termid_re_string = r"(?P<prefix>[\w_]+):(?P<accession>\d+)";
        let termid_re = Regex::new(termid_re_string).unwrap();

        let parent_re_string = r"^\[".to_owned() + termid_re_string + r"\]$";
        let parent_re = Regex::new(&parent_re_string).unwrap();

        let maybe_captures = parent_re.captures(cv_name);

        if let Some(captures) = maybe_captures {
            let prefix = captures.name("prefix").unwrap();
            let accession = captures.name("accession").unwrap();
            terms_url += &format!("(interesting_parents:{}\\:{} OR id:{}\\:{})",
                                  prefix, accession, prefix, accession);
        } else {
            terms_url += "cv_name:";
            terms_url += cv_name;
        }

        if let Some(captures) = termid_re.captures(q) {
            let prefix = captures.name("prefix").unwrap();
            let accession = captures.name("accession").unwrap();
            terms_url += " AND id:";
            terms_url += prefix;
            terms_url += r"\:";
            terms_url += accession;
        } else {
            terms_url += " AND (name:(";

            let clean_words: Vec<String> =
                Regex::new(r"([\w-]+)").unwrap().captures_iter(q)
                .map(|cap| cap.at(1).unwrap().to_owned()).collect();

            if clean_words.len() == 0 {
                return Ok(vec![]);
            }

            let clean_words_length = clean_words.len();

            for (i, word) in clean_words.iter().enumerate() {
                if i == clean_words_length - 1 {
                    terms_url += &format!("{} {}~0.8 {}*", word, word, word);
                } else {
                    terms_url += &format!("{} {}~0.8 ", word, word);
                }
            }

            let query_part = self.get_query_part(&clean_words);

            terms_url += &format!(") OR close_synonym_words:({})^{} OR distant_synonym_words:({})^{})",
                                  query_part, self.close_synonym_boost,
                                  query_part, self.distant_synonym_boost);
        }
        print!("{:?}\n", terms_url);

        let res = reqwest::get(&terms_url)?;

        println!("Status: {}", res.status());
        println!("Headers:\n{}", res.headers());

        match serde_json::from_reader(res) {
            Ok(solr_response_container) => {
                let container: SolrResponseContainer = solr_response_container;
                Ok(container.response.docs)
            },
            Err(err) => {
                panic!(format!("{:?}", err));
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::net::ToSocketAddrs;
use std::time::Duration;
use router::{Router, HttpRouter, Matcher};
use middleware::{MiddlewareStack, Middleware, ErrorHandler};
use server::Server;
use hyper::method::Method;
use hyper::status::StatusCode;

//pre defined middleware
use default_error_handler::DefaultErrorHandler;

/// Nickel is the application object. It's the surface that
/// holds all public APIs.
pub struct Nickel<D: Sync + Send + 'static = ()> {
    middleware_stack: MiddlewareStack<D>,
    data: D,
    keep_alive_timeout: Option<Duration>,
}

impl<D: Sync + Send + 'static> HttpRouter<D> for Nickel<D> {
    fn add_route<M: Into<Matcher>, H: Middleware<D>>(&mut self, method: Method, matcher: M, handler: H) -> &mut Self {
        let mut router = Router::new();
        router.add_route(method, matcher, handler);
        self.utilize(router);
        self
    }
}

impl Nickel<()> {
    /// Creates an instance of Nickel with default error handling.
    pub fn new() -> Nickel<()> {
        Nickel::with_data(())
    }
}

impl<D: Sync + Send + 'static> Nickel<D> {
    /// Creates an instance of Nickel with default error handling and custom data.
    pub fn with_data(data: D) -> Nickel<D> {
        let mut middleware_stack = MiddlewareStack::new();

        // Hook up the default error handler by default. Users are
        // free to cancel it out from their custom error handler if
        // they don't like the default behaviour.
        middleware_stack.add_error_handler(DefaultErrorHandler);

        Nickel {
            middleware_stack: middleware_stack,
            data: data,
            // Default value from nginx
            keep_alive_timeout: Some(Duration::from_secs(75))
        }
    }

    /// Registers a middleware handler which will be invoked among other middleware
    /// handlers before each request. Middleware can be stacked and is invoked in the
    /// same order it was registered.
    ///
    /// A middleware handler is nearly identical to a regular route handler with the only
    /// difference that it expects a result of either Action or NickelError.
    /// That is to indicate whether other middleware handlers (if any) further
    /// down the stack should continue or if the middleware invocation should
    /// be stopped after the current handler.
    ///
    /// # Examples
    /// ```{rust}
    /// # #[macro_use] extern crate nickel;
    /// # fn main() {
    /// use nickel::Nickel;
    /// let mut server = Nickel::new();
    /// server.utilize(middleware! { |req|
    ///     println!("logging request: {:?}", req.origin.uri);
    /// });
    /// # }
    /// ```
    pub fn utilize<T: Middleware<D>>(&mut self, handler: T){
        self.middleware_stack.add_middleware(handler);
    }

    /// Registers an error handler which will be invoked among other error handler
    /// as soon as any regular handler returned an error
    ///
    /// A error handler is nearly identical to a regular middleware handler with the only
    /// difference that it takes an additional error parameter or type `NickelError.
    ///
    /// # Examples
    ///
    /// ```{rust}
    /// # extern crate nickel;
    /// # fn main() {
    /// use std::io::Write;
    /// use nickel::{Nickel, Request, Continue, Halt};
    /// use nickel::{NickelError, Action};
    /// use nickel::status::StatusCode::NotFound;
    ///
    /// fn error_handler<D>(err: &mut NickelError<D>, _req: &mut Request<D>) -> Action {
    ///    if let Some(ref mut res) = err.stream {
    ///        if res.status() == NotFound {
    ///            let _ = res.write_all(b"<h1>Call the police!</h1>");
    ///            return Halt(())
    ///        }
    ///    }
    ///
    ///     Continue(())
    /// }
    ///
    /// let mut server = Nickel::new();
    ///
    /// let ehandler: fn(&mut NickelError<()>, &mut Request<()>) -> Action = error_handler;
    ///
    /// server.handle_error(ehandler)
    /// # }
    /// ```
    pub fn handle_error<T: ErrorHandler<D>>(&mut self, handler: T){
        self.middleware_stack.add_error_handler(handler);
    }

    /// Create a new middleware to serve as a router.
    ///
    ///
    /// # Examples
    /// ```{rust}
    /// #[macro_use] extern crate nickel;
    /// use nickel::{Nickel, HttpRouter};
    ///
    /// fn main() {
    ///     let mut server = Nickel::new();
    ///     let mut router = Nickel::router();
    ///
    ///     router.get("/foo", middleware! {
    ///         "Hi from /foo"
    ///     });
    ///
    ///     server.utilize(router);
    /// }
    /// ```
    pub fn router() -> Router<D> {
        Router::new()
    }

    /// Bind and listen for connections on the given host and port.
    ///
    /// # Panics
    ///
    /// Panics if `addr` is an invalid `SocketAddr`.
    ///
    /// # Examples
    /// ```{rust,no_run}
    /// use nickel::Nickel;
    ///
    /// let server = Nickel::new();
    /// server.listen("127.0.0.1:6767");
    /// ```
    pub fn listen<T: ToSocketAddrs>(mut self, addr: T) {
        self.middleware_stack.add_middleware(middleware! {
            (StatusCode::NotFound, "File Not Found")
        });

        let server = Server::new(self.middleware_stack, self.data);
        let listener = server.serve(addr, self.keep_alive_timeout).unwrap();

        println!("Listening on http://{}", listener.socket);
        println!("Ctrl-C to shutdown server");
    }

    /// Set the timeout for the keep-alive loop
    ///
    /// # Performance
    ///
    /// Setting this to `None` can have significant performance impact, but if
    /// you need to use a version of rustc < 1.4, then it may be a good choice.
    ///
    /// Alternatively, setting this too high, can lead to thread exhaustion,
    /// see [this thread](https://github.com/hyperium/hyper/issues/368) for more.
    ///
    /// # Default
    ///
    /// The default value is 75 seconds.
    pub fn keep_alive_timeout(&mut self, timeout: Option<Duration>){
        self.keep_alive_timeout = timeout;
    }
}

#[test]
#[should_panic]
fn invalid_listen_addr() {
    Nickel::new().listen("127.0.0.1.6667");
}
<commit_msg>feat(server): use a random port when NICKEL_TEST_HARNESS exists in env<commit_after>use std::net::ToSocketAddrs;
use std::time::Duration;
use std::env;
use router::{Router, HttpRouter, Matcher};
use middleware::{MiddlewareStack, Middleware, ErrorHandler};
use server::Server;
use hyper::method::Method;
use hyper::status::StatusCode;

//pre defined middleware
use default_error_handler::DefaultErrorHandler;

/// Nickel is the application object. It's the surface that
/// holds all public APIs.
pub struct Nickel<D: Sync + Send + 'static = ()> {
    middleware_stack: MiddlewareStack<D>,
    data: D,
    keep_alive_timeout: Option<Duration>,
}

impl<D: Sync + Send + 'static> HttpRouter<D> for Nickel<D> {
    fn add_route<M: Into<Matcher>, H: Middleware<D>>(&mut self, method: Method, matcher: M, handler: H) -> &mut Self {
        let mut router = Router::new();
        router.add_route(method, matcher, handler);
        self.utilize(router);
        self
    }
}

impl Nickel<()> {
    /// Creates an instance of Nickel with default error handling.
    pub fn new() -> Nickel<()> {
        Nickel::with_data(())
    }
}

impl<D: Sync + Send + 'static> Nickel<D> {
    /// Creates an instance of Nickel with default error handling and custom data.
    pub fn with_data(data: D) -> Nickel<D> {
        let mut middleware_stack = MiddlewareStack::new();

        // Hook up the default error handler by default. Users are
        // free to cancel it out from their custom error handler if
        // they don't like the default behaviour.
        middleware_stack.add_error_handler(DefaultErrorHandler);

        Nickel {
            middleware_stack: middleware_stack,
            data: data,
            // Default value from nginx
            keep_alive_timeout: Some(Duration::from_secs(75))
        }
    }

    /// Registers a middleware handler which will be invoked among other middleware
    /// handlers before each request. Middleware can be stacked and is invoked in the
    /// same order it was registered.
    ///
    /// A middleware handler is nearly identical to a regular route handler with the only
    /// difference that it expects a result of either Action or NickelError.
    /// That is to indicate whether other middleware handlers (if any) further
    /// down the stack should continue or if the middleware invocation should
    /// be stopped after the current handler.
    ///
    /// # Examples
    /// ```{rust}
    /// # #[macro_use] extern crate nickel;
    /// # fn main() {
    /// use nickel::Nickel;
    /// let mut server = Nickel::new();
    /// server.utilize(middleware! { |req|
    ///     println!("logging request: {:?}", req.origin.uri);
    /// });
    /// # }
    /// ```
    pub fn utilize<T: Middleware<D>>(&mut self, handler: T){
        self.middleware_stack.add_middleware(handler);
    }

    /// Registers an error handler which will be invoked among other error handler
    /// as soon as any regular handler returned an error
    ///
    /// A error handler is nearly identical to a regular middleware handler with the only
    /// difference that it takes an additional error parameter or type `NickelError.
    ///
    /// # Examples
    ///
    /// ```{rust}
    /// # extern crate nickel;
    /// # fn main() {
    /// use std::io::Write;
    /// use nickel::{Nickel, Request, Continue, Halt};
    /// use nickel::{NickelError, Action};
    /// use nickel::status::StatusCode::NotFound;
    ///
    /// fn error_handler<D>(err: &mut NickelError<D>, _req: &mut Request<D>) -> Action {
    ///    if let Some(ref mut res) = err.stream {
    ///        if res.status() == NotFound {
    ///            let _ = res.write_all(b"<h1>Call the police!</h1>");
    ///            return Halt(())
    ///        }
    ///    }
    ///
    ///     Continue(())
    /// }
    ///
    /// let mut server = Nickel::new();
    ///
    /// let ehandler: fn(&mut NickelError<()>, &mut Request<()>) -> Action = error_handler;
    ///
    /// server.handle_error(ehandler)
    /// # }
    /// ```
    pub fn handle_error<T: ErrorHandler<D>>(&mut self, handler: T){
        self.middleware_stack.add_error_handler(handler);
    }

    /// Create a new middleware to serve as a router.
    ///
    ///
    /// # Examples
    /// ```{rust}
    /// #[macro_use] extern crate nickel;
    /// use nickel::{Nickel, HttpRouter};
    ///
    /// fn main() {
    ///     let mut server = Nickel::new();
    ///     let mut router = Nickel::router();
    ///
    ///     router.get("/foo", middleware! {
    ///         "Hi from /foo"
    ///     });
    ///
    ///     server.utilize(router);
    /// }
    /// ```
    pub fn router() -> Router<D> {
        Router::new()
    }

    /// Bind and listen for connections on the given host and port.
    ///
    /// # Panics
    ///
    /// Panics if `addr` is an invalid `SocketAddr`.
    ///
    /// # Examples
    /// ```{rust,no_run}
    /// use nickel::Nickel;
    ///
    /// let server = Nickel::new();
    /// server.listen("127.0.0.1:6767");
    /// ```
    pub fn listen<T: ToSocketAddrs>(mut self, addr: T) {
        self.middleware_stack.add_middleware(middleware! {
            (StatusCode::NotFound, "File Not Found")
        });

        let server = Server::new(self.middleware_stack, self.data);

        let is_test_harness = env::vars().any(|(ref k, _)| k == "NICKEL_TEST_HARNESS");

        let listener = if is_test_harness {
            // If we're under a test harness, we'll pass zero to get assigned a random
            // port. See http://doc.rust-lang.org/std/net/struct.TcpListener.html#method.bind
            server.serve("localhost:0", self.keep_alive_timeout).unwrap()
        } else {
            server.serve(addr, self.keep_alive_timeout).unwrap()
        };

        println!("Listening on http://{}", listener.socket);
        println!("Ctrl-C to shutdown server");
    }

    /// Set the timeout for the keep-alive loop
    ///
    /// # Performance
    ///
    /// Setting this to `None` can have significant performance impact, but if
    /// you need to use a version of rustc < 1.4, then it may be a good choice.
    ///
    /// Alternatively, setting this too high, can lead to thread exhaustion,
    /// see [this thread](https://github.com/hyperium/hyper/issues/368) for more.
    ///
    /// # Default
    ///
    /// The default value is 75 seconds.
    pub fn keep_alive_timeout(&mut self, timeout: Option<Duration>){
        self.keep_alive_timeout = timeout;
    }
}

#[test]
#[should_panic]
fn invalid_listen_addr() {
    Nickel::new().listen("127.0.0.1.6667");
}
<|endoftext|>


<commit_before>use std::hash;
use std::hash::Hash;
use std::int::MAX;
use std::num::Int;

/// Our fixed-point loop needs a way of hashing the "current state" (type `St).
/// The details of what states are and how they relate need not be revealed.
/// We hide all of these details in a "state system" (type `Sys`).
/// `next` checks for unstepped states to become the "current state".
/// `step` updates the system at the "current state".
trait Step {
    type St : Hash ;
    type Sys ;
    pub fn step (st:Self::St, sys:Self::Sys) -> Self::Sys ;
    pub fn next (sys:Self::Sys) -> Option<Self::St> ;
}

trait Fp<S:Step> {
    pub fn work_tree (left_lev:int, sys:S::Sys, parent_lev:int) -> S::Sys ;
    pub fn fp ( st:S::Sys ) -> S::Sys ;
}

struct FpS;

impl<S:Step> Fp<S> for FpS {

    fn work_tree (left_lev:int, sys:S::Sys, parent_lev:int) -> S::Sys {
        let nxt = Step::next(sys) ;
        match nxt {
            None => sys,
            Some(st) => {
                let st_lev = Int::trailing_zeros(hash::hash(&st)) as int ;
                if ( left_lev <= st_lev &&
                     st_lev   <= parent_lev )
                {
                    let sys = Step::step(st, sys) ;
                    let sys = Fp::work_tree ( -1,     sys, st_lev );
                    let sys = Fp::work_tree ( st_lev, sys, parent_lev );
                    sys
                }
                else {
                    sys
                }
            }
        }
    }

    fn fp (sys:S::Sys) -> S::Sys {
        Fp::work_tree (-1, sys, MAX );
    }
}
<commit_msg>still confused about typing issues with balfp traits<commit_after>use std::hash;
use std::hash::Hash;
use std::int::MAX;
use std::num::Int;

/// Our fixed-point loop needs a way of hashing the "current state" (type `St`).
/// The details of what states are and how they relate need not be revealed.
/// We hide all of these details in a "state system" (type `Sys`).
/// `next` checks for unstepped states to become the "current state".
/// `step` updates the system at the "current state".
trait Step {
    type St : Hash ;
    type Sys ;
    fn step (st:Self::St, sys:Self::Sys) -> Self::Sys ;
    fn next (sys:Self::Sys) -> Option<Self::St> ;
}

trait Fp<S:Step> {
    fn work_tree (left_lev:int, sys:S::Sys, parent_lev:int) -> S::Sys ;
    fn fp ( st:S::Sys ) -> S::Sys ;
}

struct FpS;

impl<S:Step> Fp<S> for FpS {

    fn work_tree (left_lev:int, sys:S::Sys, parent_lev:int) -> S::Sys {

        panic!("!");
        // let nxt = Step::next(sys) ;
        // match nxt {
        //     None => sys,
        //     Some(st) => {
        //         let st_lev = Int::trailing_zeros(hash::hash(&st)) as int ;
        //         if ( left_lev <= st_lev &&
        //              st_lev   <= parent_lev )
        //         {
        //             let sys = Step::step(st, sys) ;
        //             let sys = Fp::work_tree ( -1,     sys, st_lev );
        //             let sys = Fp::work_tree ( st_lev, sys, parent_lev );
        //             sys
        //         }
        //         else {
        //             sys
        //         }
        //     }
        // }

    }

    fn fp (sys:S::Sys) -> S::Sys {
        //Fp::work_tree (-1, sys, MAX );
        panic!("!");
    }
}
<|endoftext|>


<commit_before>use std::io::BufReader;
use std::io::Result;
use std::net::{TcpListener, TcpStream};
use std::sync::mpsc::sync_channel;
use std::sync::mpsc::SyncSender;
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

use birch::client::ClientConnection;
use birch::proto::RawMessage;
use birch::socket::IrcReader;
use birch::socket::{IrcSocket, IrcSocketConfig, IrcWriter};

#[derive(Clone)]
struct UserFanoutWriter(SyncSender<RawMessage>);

impl IrcWriter for UserFanoutWriter {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        // TODO: Is it worth propagating this error?
        self.0.send(msg.clone()).expect("receiver disconnected");
        Ok(())
    }
}

fn main() -> Result<()> {
    let (sync_sender, receiver) = sync_channel(100);
    let mut user_fanout = UserFanoutWriter(sync_sender);

    thread::spawn(move || {
        let config = IrcSocketConfig {
            nick: "ep",
            addr: "irc.freenode.net:6667",
            max_retries: Some(3),
        };

        let mut sock = IrcSocket::new(config);
        // TODO: surface any errors here + shutdown hook
        sock.start_loop(&mut user_fanout)
    });

    let clients = Arc::new(Mutex::new(Vec::<TcpStream>::new()));
    let mut _clients = Arc::clone(&clients);
    thread::spawn(move || {
        for msg in receiver {
            let mut clients = _clients.lock().expect("mutex poisoned");
            let mut dead_clients = vec![];

            for (i, ref mut c) in clients.iter().enumerate() {
                if let Err(err) = c.write_message(&msg) {
                    println!("Failed to write to client: {:?}", err);
                    dead_clients.push(i);
                }
            }

            // Prune anything we failed to write to
            for index in dead_clients.into_iter().rev() {
                clients.remove(index);
            }
        }
    });

    // TODO: hook this up
    let listener = TcpListener::bind("127.0.0.1:9123").unwrap();
    for stream in listener.incoming() {
        if let Ok(stream) = stream {
            println!("Client connected");

            let fanout_writer = stream.try_clone().expect("clone stream");
            clients.lock().expect("mutex poisoned").push(fanout_writer);

            thread::spawn(move || {
                let mut client_writer = stream.try_clone().expect("clone stream");
                let mut client = ClientConnection::new(&mut client_writer);
                let mut reader = BufReader::new(stream);

                loop {
                    let result = reader
                        .read_message()
                        .and_then(|msg| client.handle_message(&msg));

                    if result.is_err() {
                        break;
                    }
                }
            });
        }
    }

    Ok(())
}
<commit_msg>Split client handling logic out of main<commit_after>use std::collections::HashMap;
use std::io::BufReader;
use std::io::Result;
use std::io::{Error, ErrorKind};
use std::net::{TcpListener, TcpStream};
use std::sync::mpsc::sync_channel;
use std::sync::mpsc::{Receiver, SyncSender};
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

use birch::client::ClientConnection;
use birch::proto::RawMessage;
use birch::socket::IrcReader;
use birch::socket::{IrcSocket, IrcSocketConfig, IrcWriter};

#[derive(Clone)]
struct IrcChannel(SyncSender<RawMessage>);

impl IrcChannel {
    fn new() -> (Self, Receiver<RawMessage>) {
        let (sender, receiver) = sync_channel(100);
        (IrcChannel(sender), receiver)
    }
}

impl IrcWriter for IrcChannel {
    fn write_message(&mut self, msg: &RawMessage) -> Result<()> {
        if let Err(err) = self.0.send(msg.clone()) {
            println!("Failed to write to client: {:?}", err);
            return Err(Error::new(ErrorKind::Other, "other end disconnected"));
        }

        Ok(())
    }
}

struct ClientFanoutManager {
    id_counter: usize,
    clients: HashMap<usize, SyncSender<RawMessage>>,
}

impl ClientFanoutManager {
    fn new() -> Self {
        Self {
            id_counter: 0,
            clients: HashMap::new(),
        }
    }

    fn next_id(&mut self) -> usize {
        let id = self.id_counter;
        self.id_counter += 1;
        id
    }

    fn add_client(&mut self, sender: SyncSender<RawMessage>) -> usize {
        let id = self.next_id();
        self.clients.insert(id, sender);
        id
    }

    fn remove_client(&mut self, id: usize) -> Option<()> {
        self.clients.remove(&id).map(|_| ())
    }

    fn write_message(&mut self, msg: &RawMessage) {
        let mut dead_clients = vec![];
        for (id, client) in self.clients.iter() {
            if let Err(err) = client.send(msg.clone()) {
                println!("Failed to write to client: {:?}", err);
                dead_clients.push(*id);
            }
        }
        // Prune anything we failed to write to
        for id in dead_clients.into_iter() {
            self.remove_client(id);
        }
    }
}

struct ClientManager {
    fanout_manager: Arc<Mutex<ClientFanoutManager>>,
    fanout: IrcChannel,
}

impl ClientManager {
    fn new() -> Self {
        let (sender, receiver) = IrcChannel::new();
        let manager = Arc::new(Mutex::new(ClientFanoutManager::new()));

        let fanout = Arc::clone(&manager);
        thread::spawn(move || {
            for msg in receiver {
                fanout.lock().expect("mutex poisoned").write_message(&msg);
            }
        });

        Self {
            fanout_manager: manager,
            fanout: sender,
        }
    }

    fn fanout_sender(&self) -> IrcChannel {
        self.fanout.clone()
    }

    fn accept_client_connection(&mut self, stream: TcpStream) {
        let (sender, receiver) = sync_channel(100);

        // TODO: write up disconnect logic
        let _client_id = self
            .fanout_manager
            .lock()
            .unwrap()
            .add_client(sender.clone());

        let mut writer = stream.try_clone().expect("clone stream");
        // Writer thread
        thread::spawn(move || {
            for msg in receiver {
                if let Err(err) = writer.write_message(&msg) {
                    println!("failed to write to client: {:?}", err);
                    break;
                }
            }
        });

        // Reader thread
        thread::spawn(move || {
            let mut writer = IrcChannel(sender);
            let mut client = ClientConnection::new(&mut writer);
            let mut reader = BufReader::new(stream);

            loop {
                let result = reader
                    .read_message()
                    .and_then(|msg| client.handle_message(&msg));

                if result.is_err() {
                    break;
                }
            }
        });
    }
}

fn main() -> Result<()> {
    let mut client_manager = ClientManager::new();

    let config = IrcSocketConfig {
        nick: "ep",
        addr: "irc.freenode.net:6667",
        max_retries: Some(3),
    };

    let mut fanout_sender = client_manager.fanout_sender();
    let mut sock = IrcSocket::new(config);
    thread::spawn(move || {
        // TODO: surface any errors here + shutdown hook
        sock.start_loop(&mut fanout_sender)
    });

    // TODO: hook this up to config
    let listener = TcpListener::bind("127.0.0.1:9123").unwrap();
    for stream in listener.incoming() {
        if let Ok(stream) = stream {
            println!("Client connected");
            client_manager.accept_client_connection(stream);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use {
    CanRectangle,
    HasRectangle,
    Rectangle,
};
use vecmath::{
    margin_rectangle,
    relative_rectangle,
};

/// Should be implemented by contexts that have rectangle information.
pub trait RelativeRectangle<'a> {
    /// Shrinks the current rectangle equally by all sides.
    fn margin(&'a self, m: f64) -> Self;

    /// Expands the current rectangle equally by all sides.
    #[inline(always)]
    fn expand(&'a self, m: f64) -> Self {
        self.margin(-m)
    }

    /// Moves to a relative rectangle using the current rectangle as tile.
    fn rel(&'a self, x: f64, y: f64) -> Self;

    /// Moves to the rectangle above using the current rectangle as tile.
    #[inline(always)]
    fn up(&'a self) -> Self {
        self.rel(0.0, 1.0)
    }

    /// Moves to the left rectangle using the current rectangle as tile.
    #[inline(always)]
    fn left(&'a self) -> Self {
        self.rel(-1.0, 0.0)
    }

    /// Moves to the right rectangle using the current rectangle as tile.
    #[inline(always)]
    fn right(&'a self) -> Self {
        self.rel(1.0, 0.0)
    }

    /// Moves to the rectangle below using the current rectangle as tile.
    #[inline(always)]
    fn down(&'a self) -> Self {
        self.rel(0.0, -1.0)
    }
}

impl<
    'a,
    T: HasRectangle<'a, Rectangle> + CanRectangle<'a, T, Rectangle>
> RelativeRectangle<'a> for T {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> T {
        self.rectangle(margin_rectangle(self.get_rectangle(), m))
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> T {
        self.rectangle(relative_rectangle(self.get_rectangle(), x, y))
    }
}

<commit_msg>Added generic parameter to `RelativeRectangle`<commit_after>use {
    CanRectangle,
    HasRectangle,
    Rectangle,
};
use vecmath::{
    margin_rectangle,
    relative_rectangle,
};

/// Should be implemented by contexts that have rectangle information.
pub trait RelativeRectangle<'a, T> {
    /// Shrinks the current rectangle equally by all sides.
    fn margin(&'a self, m: f64) -> T;

    /// Expands the current rectangle equally by all sides.
    #[inline(always)]
    fn expand(&'a self, m: f64) -> T {
        self.margin(-m)
    }

    /// Moves to a relative rectangle using the current rectangle as tile.
    fn rel(&'a self, x: f64, y: f64) -> T;

    /// Moves to the rectangle above using the current rectangle as tile.
    #[inline(always)]
    fn up(&'a self) -> T {
        self.rel(0.0, 1.0)
    }

    /// Moves to the left rectangle using the current rectangle as tile.
    #[inline(always)]
    fn left(&'a self) -> T {
        self.rel(-1.0, 0.0)
    }

    /// Moves to the right rectangle using the current rectangle as tile.
    #[inline(always)]
    fn right(&'a self) -> T {
        self.rel(1.0, 0.0)
    }

    /// Moves to the rectangle below using the current rectangle as tile.
    #[inline(always)]
    fn down(&'a self) -> T {
        self.rel(0.0, -1.0)
    }
}

impl<
    'a,
    T: HasRectangle<'a, Rectangle> + CanRectangle<'a, U, Rectangle>,
    U
> RelativeRectangle<'a, U> for T {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> U {
        self.rectangle(margin_rectangle(self.get_rectangle(), m))
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> U {
        self.rectangle(relative_rectangle(self.get_rectangle(), x, y))
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2017, 2018 Erik Nordstrøm <erik@nordstroem.no>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

use strum::IntoEnumIterator;
use arrayvec::ArrayVec;
use rand::seq::SliceRandom;

use std::ops::Deref;

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Color
{
    #[strum(serialize="?")]
    Unknown,
    #[strum(serialize="♠")]
    Spades,
    #[strum(serialize="♥")]
    Hearts,
    #[strum(serialize="♦")]
    Diamonds,
    #[strum(serialize="♣")]
    Clubs
}

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Rank
{
    #[strum(serialize="?")]
    Unknown,
    A,
    #[strum(serialize="2")]
    Two,
    #[strum(serialize="3")]
    Three,
    #[strum(serialize="4")]
    Four,
    #[strum(serialize="5")]
    Five,
    #[strum(serialize="6")]
    Six,
    #[strum(serialize="7")]
    Seven,
    #[strum(serialize="8")]
    Eight,
    #[strum(serialize="9")]
    Nine,
    #[strum(serialize="10")]
    Ten,
    J,
    Q,
    K
}

pub struct Card
{
    pub color:     Color,
    pub rank:      Rank,
    pub id:        i8,
    pub facing_up: bool
}

// TODO: Change to ArrayVec<[Card; 52]> after PR for that size has been merged.
type DeckArray = [Card; 56];
type Deck = ArrayVec<DeckArray>;

pub struct ShuffledDeck(Deck);

NewtypeFrom! { () pub struct ShuffledDeck(Deck); }

impl ShuffledDeck
{
    pub fn new () -> ShuffledDeck
    {
        /*
         * The cards in the shuffled deck appear in order of their IDs,
         * such that the card with ID n is at array position n.
         */

        let mut deck = Deck::new();

        let mut card_ids: Vec<i8> = (0..52).collect();
        card_ids.shuffle(&mut rand::thread_rng());

        let mut card_ids_iter = card_ids.iter_mut();

        for color in Color::iter().skip(1)
        {
            for rank in Rank::iter().skip(1)
            {
                deck.push(Card
                {
                    color:     color,
                    rank:      rank,
                    id:        *(card_ids_iter.next().unwrap()),
                    facing_up: false
                });
            }
        }

        deck.sort_unstable_by_key(|k| k.id);

        ShuffledDeck::from(deck)
    }

    pub fn push (&mut self, element: <DeckArray as arrayvec::Array>::Item)
    {
        Deck::push(&mut self.0, element)
    }
}

impl Deref for ShuffledDeck
{
    type Target = [<DeckArray as arrayvec::Array>::Item];

    #[inline]
    fn deref (&self) -> &[<DeckArray as arrayvec::Array>::Item]
    {
        Deck::deref(&self.0)
    }
}
<commit_msg>Whitespace.<commit_after>/*
 * Copyright (c) 2017, 2018 Erik Nordstrøm <erik@nordstroem.no>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

use strum::IntoEnumIterator;
use arrayvec::ArrayVec;
use rand::seq::SliceRandom;

use std::ops::Deref;

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Color
{
    #[strum(serialize="?")]     Unknown,
    #[strum(serialize="♠")]     Spades,
    #[strum(serialize="♥")]     Hearts,
    #[strum(serialize="♦")]     Diamonds,
    #[strum(serialize="♣")]     Clubs
}

#[derive(EnumIter, Display, Copy, Clone)]
pub enum Rank
{
    #[strum(serialize="?")]     Unknown,
                                A,
    #[strum(serialize="2")]     Two,
    #[strum(serialize="3")]     Three,
    #[strum(serialize="4")]     Four,
    #[strum(serialize="5")]     Five,
    #[strum(serialize="6")]     Six,
    #[strum(serialize="7")]     Seven,
    #[strum(serialize="8")]     Eight,
    #[strum(serialize="9")]     Nine,
    #[strum(serialize="10")]    Ten,
                                J,
                                Q,
                                K
}

pub struct Card
{
    pub color:     Color,
    pub rank:      Rank,
    pub id:        i8,
    pub facing_up: bool
}

// TODO: Change to ArrayVec<[Card; 52]> after PR for that size has been merged.
type DeckArray = [Card; 56];
type Deck = ArrayVec<DeckArray>;

pub struct ShuffledDeck(Deck);

NewtypeFrom! { () pub struct ShuffledDeck(Deck); }

impl ShuffledDeck
{
    pub fn new () -> ShuffledDeck
    {
        /*
         * The cards in the shuffled deck appear in order of their IDs,
         * such that the card with ID n is at array position n.
         */

        let mut deck = Deck::new();

        let mut card_ids: Vec<i8> = (0..52).collect();
        card_ids.shuffle(&mut rand::thread_rng());

        let mut card_ids_iter = card_ids.iter_mut();

        for color in Color::iter().skip(1)
        {
            for rank in Rank::iter().skip(1)
            {
                deck.push(Card
                {
                    color:     color,
                    rank:      rank,
                    id:        *(card_ids_iter.next().unwrap()),
                    facing_up: false
                });
            }
        }

        deck.sort_unstable_by_key(|k| k.id);

        ShuffledDeck::from(deck)
    }

    pub fn push (&mut self, element: <DeckArray as arrayvec::Array>::Item)
    {
        Deck::push(&mut self.0, element)
    }
}

impl Deref for ShuffledDeck
{
    type Target = [<DeckArray as arrayvec::Array>::Item];

    #[inline]
    fn deref (&self) -> &[<DeckArray as arrayvec::Array>::Item]
    {
        Deck::deref(&self.0)
    }
}
<|endoftext|>


<commit_before>pub mod ffi {
   #![allow(non_upper_case_globals)]

   pub use libc::{
      c_char, c_int, c_uint, c_long, c_ulong, c_void
   };
   use std::mem;
   use ::os::xcb::ffi::xcb_connection_t;

   pub enum XDisplay { }
   pub enum XPrivate { }
   pub enum XrmHashBucketRec { }
   pub enum XGC { }

   pub type XID = c_ulong;
   pub type GC = *mut XGC;
   pub type Display = XDisplay;
   pub type Colormap = XID;
   pub type Window = XID;
   pub type XPointer = *mut c_char;
   pub type VisualID = c_ulong;

   pub type XEventQueueOwner = c_uint;

   pub const XlibOwnsEventQueue: c_uint = 0;
   pub const XCBOwnsEventQueue: c_uint = 1;

   #[repr(C)]
   #[derive(Copy)]
   pub struct XExtData {
      pub number: c_int,
      pub next: *mut XExtData,
      pub free_private: Option<extern "C" fn(extension: *mut XExtData) -> c_int>,
      pub private_data: XPointer,
   }
   impl Clone for XExtData {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XExtData {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Visual {
      pub ext_data: *mut XExtData,
      pub visualid: VisualID,
      pub class: c_int,
      pub red_mask: c_ulong,
      pub green_mask: c_ulong,
      pub blue_mask: c_ulong,
      pub bits_per_rgb: c_int,
      pub map_entries: c_int,
   }
   impl Clone for Visual {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Visual {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Depth {
      pub depth: c_int,
      pub nvisuals: c_int,
      pub visuals: *mut Visual,
   }
   impl Clone for Depth {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Depth {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Screen {
      pub ext_data: *mut XExtData,
      pub display: *mut XDisplay,
      pub root: Window,
      pub width: c_int,
      pub height: c_int,
      pub mwidth: c_int,
      pub mheight: c_int,
      pub ndepths: c_int,
      pub depths: *mut Depth,
      pub root_depth: c_int,
      pub root_visual: *mut Visual,
      pub default_gc: GC,
      pub cmap: Colormap,
      pub white_pixel: c_ulong,
      pub black_pixel: c_ulong,
      pub max_maps: c_int,
      pub min_maps: c_int,
      pub backing_store: c_int,
      pub save_unders: c_int,
      pub root_input_mask: c_long,
   }
   impl Clone for Screen {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Screen {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct ScreenFormat {
      pub ext_data: *mut XExtData,
      pub depth: c_int,
      pub bits_per_pixel: c_int,
      pub scanline_pad: c_int,
   }
   impl Clone for ScreenFormat {
      fn clone(&self) -> Self { *self }
   }
   impl Default for ScreenFormat {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct XPrivDisplay {
      pub ext_data: *mut XExtData,
      pub private1: *mut XPrivate,
      pub fd: c_int,
      pub private2: c_int,
      pub proto_major_version: c_int,
      pub proto_minor_version: c_int,
      pub vendor: *mut c_char,
      pub private3: XID,
      pub private4: XID,
      pub private5: XID,
      pub private6: c_int,
      pub resource_alloc: Option<extern "C" fn(arg1: *mut XDisplay) -> XID>,
      pub byte_order: c_int,
      pub bitmap_unit: c_int,
      pub bitmap_pad: c_int,
      pub bitmap_bit_order: c_int,
      pub nformats: c_int,
      pub pixmap_format: *mut ScreenFormat,
      pub private8: c_int,
      pub release: c_int,
      pub private9: *mut XPrivate,
      pub private10: *mut XPrivate,
      pub qlen: c_int,
      pub last_request_read: c_ulong,
      pub request: c_ulong,
      pub private11: XPointer,
      pub private12: XPointer,
      pub private13: XPointer,
      pub private14: XPointer,
      pub max_request_size: c_uint,
      pub db: *mut XrmHashBucketRec,
      pub private15: Option<extern "C" fn(arg1: *mut XDisplay) -> c_int>,
      pub display_name: *mut c_char,
      pub default_screen: c_int,
      pub nscreens: c_int,
      pub screens: *mut Screen,
      pub motion_buffer: c_ulong,
      pub private16: c_ulong,
      pub min_keycode: c_int,
      pub max_keycode: c_int,
      pub private17: XPointer,
      pub private18: XPointer,
      pub private19: c_int,
      pub xdefaults: *mut c_char,
   }
   impl Clone for XPrivDisplay {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XPrivDisplay {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }
   pub type _XPrivDisplay = *mut XPrivDisplay;

   #[link(name="X11")]
   extern "C" {
      pub fn XOpenDisplay(display_name: *const c_char) -> *mut Display;
      pub fn XCloseDisplay(display: *mut Display) -> c_int;
      pub fn XFree(data: *mut c_void) -> c_int;
   }

   #[link(name="X11-xcb")]
   extern "C" {
      pub fn XGetXCBConnection(
         display: *mut Display
      ) -> *mut xcb_connection_t;

      pub fn XSetEventQueueOwner(
         display: *mut Display,
         owner: XEventQueueOwner
      ) -> ();
   }
}

use std::ptr;
use std::ffi::{CString, CStr};

use libc::c_char;

use ::error::{RuntimeError, ErrorKind};
use ::os::xcb::Connection;

pub struct Display {
   pub ptr: *mut ffi::Display
}

impl Display {
   pub fn default() -> Result<Self, RuntimeError> {
      Display::from_ptr(ptr::null())
   }

   pub fn new<T: Into<Vec<u8>>>(name: T) -> Result<Self, RuntimeError> {
      let c_name = try!(CString::new(name.into()));

      Display::from_ptr(c_name.as_ptr())
   }

   fn from_ptr(name: *const c_char) -> Result<Self, RuntimeError> {
      let display_ptr = unsafe {
         ffi::XOpenDisplay(name)
      };

      if display_ptr.is_null() {
         let description = format!(
            "Opening X display '{}' failed",
            unsafe { CStr::from_ptr(name).to_str().unwrap() }
         );
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            description
         ));
      }

      Ok(
         Display {
            ptr: display_ptr
         }
      )
   }

   pub fn xcb_connection(&self) -> Result<Connection, RuntimeError> {
      let connection = unsafe {
         ffi::XGetXCBConnection(self.ptr)
      };
      if connection.is_null() {
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            "Getting XCB connection from display failed".to_string()
         ));
      }

      Ok(
         Connection::new(connection)
      )
   }

   pub fn xcb_own_event_queue(&self) {
      unsafe {
         ffi::XSetEventQueueOwner(
            self.ptr,
            ffi::XCBOwnsEventQueue
         )
      };
   }

   #[inline]
   pub fn default_screen(&self) -> ffi::c_int {
      unsafe{
         (
            *(self.ptr as ffi::_XPrivDisplay)
         ).default_screen
      }
   }
}

impl Drop for Display {
   fn drop (&mut self) {
      unsafe {
         ffi::XCloseDisplay(self.ptr);
      }
   }
}

#[cfg(test)]
mod test {
   use std::env;
   use super::Display;

   #[test]
   fn test_create_display() {
      assert!(Display::default().is_ok());
   }

   #[test]
   fn test_create_display_from_env() {
      let name = env::var("DISPLAY").unwrap();
      assert!(Display::new(name).is_ok());
   }

   #[test]
   fn test_create_display_error_str() {
      assert!(Display::new("ErrorStringHere").is_err());
   }

   #[test]
   fn test_create_display_nul_str() {
      assert!(Display::new(&b"one\0two"[..]).is_err());
   }

   #[test]
   fn test_create_get_xcb_connection() {
      assert!(Display::default().unwrap().xcb_connection().is_ok());
   }
}

<commit_msg>x11::default_screen formating improvement<commit_after>pub mod ffi {
   #![allow(non_upper_case_globals)]

   pub use libc::{
      c_char, c_int, c_uint, c_long, c_ulong, c_void
   };
   use std::mem;
   use ::os::xcb::ffi::xcb_connection_t;

   pub enum XDisplay { }
   pub enum XPrivate { }
   pub enum XrmHashBucketRec { }
   pub enum XGC { }

   pub type XID = c_ulong;
   pub type GC = *mut XGC;
   pub type Display = XDisplay;
   pub type Colormap = XID;
   pub type Window = XID;
   pub type XPointer = *mut c_char;
   pub type VisualID = c_ulong;

   pub type XEventQueueOwner = c_uint;

   pub const XlibOwnsEventQueue: c_uint = 0;
   pub const XCBOwnsEventQueue: c_uint = 1;

   #[repr(C)]
   #[derive(Copy)]
   pub struct XExtData {
      pub number: c_int,
      pub next: *mut XExtData,
      pub free_private: Option<extern "C" fn(extension: *mut XExtData) -> c_int>,
      pub private_data: XPointer,
   }
   impl Clone for XExtData {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XExtData {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Visual {
      pub ext_data: *mut XExtData,
      pub visualid: VisualID,
      pub class: c_int,
      pub red_mask: c_ulong,
      pub green_mask: c_ulong,
      pub blue_mask: c_ulong,
      pub bits_per_rgb: c_int,
      pub map_entries: c_int,
   }
   impl Clone for Visual {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Visual {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Depth {
      pub depth: c_int,
      pub nvisuals: c_int,
      pub visuals: *mut Visual,
   }
   impl Clone for Depth {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Depth {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct Screen {
      pub ext_data: *mut XExtData,
      pub display: *mut XDisplay,
      pub root: Window,
      pub width: c_int,
      pub height: c_int,
      pub mwidth: c_int,
      pub mheight: c_int,
      pub ndepths: c_int,
      pub depths: *mut Depth,
      pub root_depth: c_int,
      pub root_visual: *mut Visual,
      pub default_gc: GC,
      pub cmap: Colormap,
      pub white_pixel: c_ulong,
      pub black_pixel: c_ulong,
      pub max_maps: c_int,
      pub min_maps: c_int,
      pub backing_store: c_int,
      pub save_unders: c_int,
      pub root_input_mask: c_long,
   }
   impl Clone for Screen {
      fn clone(&self) -> Self { *self }
   }
   impl Default for Screen {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct ScreenFormat {
      pub ext_data: *mut XExtData,
      pub depth: c_int,
      pub bits_per_pixel: c_int,
      pub scanline_pad: c_int,
   }
   impl Clone for ScreenFormat {
      fn clone(&self) -> Self { *self }
   }
   impl Default for ScreenFormat {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }

   #[repr(C)]
   #[derive(Copy)]
   pub struct XPrivDisplay {
      pub ext_data: *mut XExtData,
      pub private1: *mut XPrivate,
      pub fd: c_int,
      pub private2: c_int,
      pub proto_major_version: c_int,
      pub proto_minor_version: c_int,
      pub vendor: *mut c_char,
      pub private3: XID,
      pub private4: XID,
      pub private5: XID,
      pub private6: c_int,
      pub resource_alloc: Option<extern "C" fn(arg1: *mut XDisplay) -> XID>,
      pub byte_order: c_int,
      pub bitmap_unit: c_int,
      pub bitmap_pad: c_int,
      pub bitmap_bit_order: c_int,
      pub nformats: c_int,
      pub pixmap_format: *mut ScreenFormat,
      pub private8: c_int,
      pub release: c_int,
      pub private9: *mut XPrivate,
      pub private10: *mut XPrivate,
      pub qlen: c_int,
      pub last_request_read: c_ulong,
      pub request: c_ulong,
      pub private11: XPointer,
      pub private12: XPointer,
      pub private13: XPointer,
      pub private14: XPointer,
      pub max_request_size: c_uint,
      pub db: *mut XrmHashBucketRec,
      pub private15: Option<extern "C" fn(arg1: *mut XDisplay) -> c_int>,
      pub display_name: *mut c_char,
      pub default_screen: c_int,
      pub nscreens: c_int,
      pub screens: *mut Screen,
      pub motion_buffer: c_ulong,
      pub private16: c_ulong,
      pub min_keycode: c_int,
      pub max_keycode: c_int,
      pub private17: XPointer,
      pub private18: XPointer,
      pub private19: c_int,
      pub xdefaults: *mut c_char,
   }
   impl Clone for XPrivDisplay {
      fn clone(&self) -> Self { *self }
   }
   impl Default for XPrivDisplay {
      fn default() -> Self { unsafe { mem::zeroed() } }
   }
   pub type _XPrivDisplay = *mut XPrivDisplay;

   #[link(name="X11")]
   extern "C" {
      pub fn XOpenDisplay(display_name: *const c_char) -> *mut Display;
      pub fn XCloseDisplay(display: *mut Display) -> c_int;
      pub fn XFree(data: *mut c_void) -> c_int;
   }

   #[link(name="X11-xcb")]
   extern "C" {
      pub fn XGetXCBConnection(
         display: *mut Display
      ) -> *mut xcb_connection_t;

      pub fn XSetEventQueueOwner(
         display: *mut Display,
         owner: XEventQueueOwner
      ) -> ();
   }
}

use std::ptr;
use std::ffi::{CString, CStr};

use libc::c_char;

use ::error::{RuntimeError, ErrorKind};
use ::os::xcb::Connection;

pub struct Display {
   pub ptr: *mut ffi::Display
}

impl Display {
   pub fn default() -> Result<Self, RuntimeError> {
      Display::from_ptr(ptr::null())
   }

   pub fn new<T: Into<Vec<u8>>>(name: T) -> Result<Self, RuntimeError> {
      let c_name = try!(CString::new(name.into()));

      Display::from_ptr(c_name.as_ptr())
   }

   fn from_ptr(name: *const c_char) -> Result<Self, RuntimeError> {
      let display_ptr = unsafe {
         ffi::XOpenDisplay(name)
      };

      if display_ptr.is_null() {
         let description = format!(
            "Opening X display '{}' failed",
            unsafe { CStr::from_ptr(name).to_str().unwrap() }
         );
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            description
         ));
      }

      Ok(
         Display {
            ptr: display_ptr
         }
      )
   }

   pub fn xcb_connection(&self) -> Result<Connection, RuntimeError> {
      let connection = unsafe {
         ffi::XGetXCBConnection(self.ptr)
      };
      if connection.is_null() {
         return Err(RuntimeError::new(
            ErrorKind::Xlib,
            "Getting XCB connection from display failed".to_string()
         ));
      }

      Ok(
         Connection::new(connection)
      )
   }

   pub fn xcb_own_event_queue(&self) {
      unsafe {
         ffi::XSetEventQueueOwner(
            self.ptr,
            ffi::XCBOwnsEventQueue
         )
      };
   }

   #[inline]
   pub fn default_screen(&self) -> ffi::c_int {
      unsafe {
         (*(self.ptr as ffi::_XPrivDisplay)).default_screen
      }
   }
}

impl Drop for Display {
   fn drop (&mut self) {
      unsafe {
         ffi::XCloseDisplay(self.ptr);
      }
   }
}

#[cfg(test)]
mod test {
   use std::env;
   use super::Display;

   #[test]
   fn test_create_display() {
      assert!(Display::default().is_ok());
   }

   #[test]
   fn test_create_display_from_env() {
      let name = env::var("DISPLAY").unwrap();
      assert!(Display::new(name).is_ok());
   }

   #[test]
   fn test_create_display_error_str() {
      assert!(Display::new("ErrorStringHere").is_err());
   }

   #[test]
   fn test_create_display_nul_str() {
      assert!(Display::new(&b"one\0two"[..]).is_err());
   }

   #[test]
   fn test_create_get_xcb_connection() {
      assert!(Display::default().unwrap().xcb_connection().is_ok());
   }
}

<|endoftext|>


<commit_before>//! The `parser` module contains structures and functions for parsing the VQA
//! (Vector Quantized Animation) format.

use nom::{be_u32, le_u8, le_u16, le_u32};

#[derive(Debug)]
pub struct FormChunk {
    pub size: u32
}

named!(pub form_chunk<FormChunk>,
    do_parse!(
        tag!("FORM") >>
        size: be_u32 >>
        (FormChunk {
            size: size
        })
    )
);

#[derive(Debug)]
pub enum VQAVersion {
    One,
    Two,
    Three
}

named!(pub vqa_version<VQAVersion>,
    switch!(le_u16,
        1 => value!(VQAVersion::One) |
        2 => value!(VQAVersion::Two) |
        3 => value!(VQAVersion::Three)
    )
);

bitflags! {
    pub struct VQAFlags: u16 {
        const HAS_SOUND = 0b00000001;
    }
}

#[derive(Debug)]
pub struct VQAHeader {
    pub version       : VQAVersion, // VQA version number
    pub flags         : VQAFlags,   // VQA flags
    pub num_frames    : u16,        // Number of frames
    pub width         : u16,        // Movie width (pixels)
    pub height        : u16,        // Movie height (pixels)
    pub block_width   : u8,         // Width of each image block (pixels)
    pub block_height  : u8,         // Height of each image block (pixels)
    pub frame_rate    : u8,         // Frame rate of the VQA
    pub cbparts       : u8,         // How many images use the same lookup table
    pub colors        : u16,        // Max number of colors used in VQA
    pub maxblocks     : u16,        // Max number of image blocks
    pub unk1          : u32,        // Always 0?
    pub unk2          : u16,        // Some kind of size?
    pub freq          : u16,        // Sound sampling frequency
    pub channels      : u8,         // Number of sound channels
    pub bits          : u8,         // Sound resolution
    pub unk3          : u32,        // Always 0?
    pub unk4          : u16,        // 0 in old VQAs, 4 in HiColor VQAs?
    pub max_cbfz_size : u32,        // 0 in old VQAs, CBFZ size in HiColor
    pub unk5          : u32,        // Always 0?
}

named!(pub vqa_header<VQAHeader>,
    do_parse!(
        tag!("VQHD")              >>
        tag!(b"\x00\x00\x00\x2a") >> // VQAHeader is always 42 bytes long
        version: vqa_version      >>
        flags: le_u16             >>
        num_frames: le_u16        >>
        width: le_u16             >>
        height: le_u16            >>
        block_width: le_u8        >>
        block_height: le_u8       >>
        frame_rate: le_u8         >>
        cbparts: le_u8            >>
        colors: le_u16            >>
        maxblocks: le_u16         >>
        unk1: le_u32              >>
        unk2: le_u16              >>
        freq: le_u16              >>
        channels: le_u8           >>
        bits: le_u8               >>
        unk3: le_u32              >>
        unk4: le_u16              >>
        max_cbfz_size: le_u32     >>
        unk5: le_u32              >>
        (VQAHeader {
            version: version,
            flags: VQAFlags::from_bits_truncate(flags),
            num_frames: num_frames,
            width: width,
            height: height,
            block_width: block_width,
            block_height: block_height,
            frame_rate: frame_rate,
            cbparts: cbparts,
            colors: colors,
            maxblocks: maxblocks,
            unk1: unk1,
            unk2: unk2,
            freq: freq,
            channels: channels,
            bits: bits,
            unk3: unk3,
            unk4: unk4,
            max_cbfz_size: max_cbfz_size,
            unk5: unk5
        })
    )
);

#[derive(Debug)]
pub struct FINFChunk {
    pub offsets: Vec<u32>
}

named!(pub finf_chunk<FINFChunk>,
    do_parse!(
        tag!("FINF") >>
        size: be_u32 >>
        offsets: many_m_n!(size as usize / 4, size as usize / 4, le_u32) >>
        (FINFChunk {
            offsets: offsets
        })
    )
);

#[derive(Debug)]
pub struct SND2Chunk<'a> {
    pub data: &'a [u8]
}

named!(pub snd2_chunk<SND2Chunk>,
    do_parse!(
        tag!("SND2")       >>
        size: be_u32       >>
        data: take!(size)  >>
        (SND2Chunk {
            data: data
        })
    )
);
<commit_msg>parse the VQFR container chunk<commit_after>//! The `parser` module contains structures and functions for parsing the VQA
//! (Vector Quantized Animation) format.

use nom::{be_u32, le_u8, le_u16, le_u32};

#[derive(Debug)]
pub struct FormChunk {
    pub size: u32
}

named!(pub form_chunk<FormChunk>,
    do_parse!(
        tag!("FORM") >>
        size: be_u32 >>
        (FormChunk {
            size: size
        })
    )
);

#[derive(Debug)]
pub enum VQAVersion {
    One,
    Two,
    Three
}

named!(pub vqa_version<VQAVersion>,
    switch!(le_u16,
        1 => value!(VQAVersion::One) |
        2 => value!(VQAVersion::Two) |
        3 => value!(VQAVersion::Three)
    )
);

bitflags! {
    pub struct VQAFlags: u16 {
        const HAS_SOUND = 0b00000001;
    }
}

#[derive(Debug)]
pub struct VQAHeader {
    pub version       : VQAVersion, // VQA version number
    pub flags         : VQAFlags,   // VQA flags
    pub num_frames    : u16,        // Number of frames
    pub width         : u16,        // Movie width (pixels)
    pub height        : u16,        // Movie height (pixels)
    pub block_width   : u8,         // Width of each image block (pixels)
    pub block_height  : u8,         // Height of each image block (pixels)
    pub frame_rate    : u8,         // Frame rate of the VQA
    pub cbparts       : u8,         // How many images use the same lookup table
    pub colors        : u16,        // Max number of colors used in VQA
    pub maxblocks     : u16,        // Max number of image blocks
    pub unk1          : u32,        // Always 0?
    pub unk2          : u16,        // Some kind of size?
    pub freq          : u16,        // Sound sampling frequency
    pub channels      : u8,         // Number of sound channels
    pub bits          : u8,         // Sound resolution
    pub unk3          : u32,        // Always 0?
    pub unk4          : u16,        // 0 in old VQAs, 4 in HiColor VQAs?
    pub max_cbfz_size : u32,        // 0 in old VQAs, CBFZ size in HiColor
    pub unk5          : u32,        // Always 0?
}

named!(pub vqa_header<VQAHeader>,
    do_parse!(
        tag!("VQHD")              >>
        tag!(b"\x00\x00\x00\x2a") >> // VQAHeader is always 42 bytes long
        version: vqa_version      >>
        flags: le_u16             >>
        num_frames: le_u16        >>
        width: le_u16             >>
        height: le_u16            >>
        block_width: le_u8        >>
        block_height: le_u8       >>
        frame_rate: le_u8         >>
        cbparts: le_u8            >>
        colors: le_u16            >>
        maxblocks: le_u16         >>
        unk1: le_u32              >>
        unk2: le_u16              >>
        freq: le_u16              >>
        channels: le_u8           >>
        bits: le_u8               >>
        unk3: le_u32              >>
        unk4: le_u16              >>
        max_cbfz_size: le_u32     >>
        unk5: le_u32              >>
        (VQAHeader {
            version: version,
            flags: VQAFlags::from_bits_truncate(flags),
            num_frames: num_frames,
            width: width,
            height: height,
            block_width: block_width,
            block_height: block_height,
            frame_rate: frame_rate,
            cbparts: cbparts,
            colors: colors,
            maxblocks: maxblocks,
            unk1: unk1,
            unk2: unk2,
            freq: freq,
            channels: channels,
            bits: bits,
            unk3: unk3,
            unk4: unk4,
            max_cbfz_size: max_cbfz_size,
            unk5: unk5
        })
    )
);

#[derive(Debug)]
pub struct FINFChunk {
    pub offsets: Vec<u32>
}

named!(pub finf_chunk<FINFChunk>,
    do_parse!(
        tag!("FINF") >>
        size: be_u32 >>
        offsets: many_m_n!(size as usize / 4, size as usize / 4, le_u32) >>
        (FINFChunk {
            offsets: offsets
        })
    )
);

#[derive(Debug)]
pub struct SND2Chunk<'a> {
    pub data: &'a [u8]
}

named!(pub snd2_chunk<SND2Chunk>,
    do_parse!(
        tag!("SND2")       >>
        size: be_u32       >>
        data: take!(size)  >>
        (SND2Chunk {
            data: data
        })
    )
);

#[derive(Debug)]
pub struct VQFRChunk<'a> {
    pub size: u32,
    pub data: &'a [u8]
}

named!(pub vqfr_chunk<VQFRChunk>,
    do_parse!(
        tag!("VQFR")      >>
        size: be_u32      >>
        data: take!(size) >>
        (VQFRChunk {
            size: size,
            data: data
        })
    )
);
<|endoftext|>


<commit_before>//! Error conditions.

use std::fmt::{self, Debug, Display, Formatter};

use ruma_api::error::{FromHttpResponseError, IntoHttpError};

/// An error that can occur during client operations.
#[derive(Debug)]
#[non_exhaustive]
pub enum Error<E> {
    /// Queried endpoint requires authentication but was called on an anonymous client.
    AuthenticationRequired,
    /// Construction of the HTTP request failed (this should never happen).
    IntoHttp(IntoHttpError),
    /// The request's URL is invalid (this should never happen).
    Url(UrlError),
    /// Couldn't obtain an HTTP response (e.g. due to network or DNS issues).
    Response(ResponseError),
    /// Converting the HTTP response to one of ruma's types failed.
    FromHttpResponse(FromHttpResponseError<E>),
}

impl<E> Display for Error<E> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::AuthenticationRequired => {
                write!(f, "The queried endpoint requires authentication but was called with an anonymous client.")
            }
            Self::IntoHttp(err) => write!(f, "HTTP request construction failed: {}", err),
            Self::Url(UrlError(err)) => write!(f, "Invalid URL: {}", err),
            Self::Response(ResponseError(err)) => write!(f, "Couldn't obtain a response: {}", err),
            // FIXME: ruma-client-api's Error type currently doesn't implement
            //        `Display`, update this when it does.
            Self::FromHttpResponse(_) => write!(f, "HTTP response conversion failed"),
        }
    }
}

impl<E> From<IntoHttpError> for Error<E> {
    fn from(err: IntoHttpError) -> Self {
        Error::IntoHttp(err)
    }
}

#[doc(hidden)]
impl<E> From<http::uri::InvalidUri> for Error<E> {
    fn from(err: http::uri::InvalidUri) -> Self {
        Error::Url(UrlError(err))
    }
}

#[doc(hidden)]
impl<E> From<hyper::Error> for Error<E> {
    fn from(err: hyper::Error) -> Self {
        Error::Response(ResponseError(err))
    }
}

impl<E> From<FromHttpResponseError<E>> for Error<E> {
    fn from(err: FromHttpResponseError<E>) -> Self {
        Error::FromHttpResponse(err)
    }
}

impl<E: Debug> std::error::Error for Error<E> {}

#[derive(Debug)]
pub struct UrlError(http::uri::InvalidUri);

#[derive(Debug)]
pub struct ResponseError(hyper::Error);
<commit_msg>Improve Display implementation for Error<commit_after>//! Error conditions.

use std::fmt::{self, Debug, Display, Formatter};

use ruma_api::error::{FromHttpResponseError, IntoHttpError};

/// An error that can occur during client operations.
#[derive(Debug)]
#[non_exhaustive]
pub enum Error<E> {
    /// Queried endpoint requires authentication but was called on an anonymous client.
    AuthenticationRequired,
    /// Construction of the HTTP request failed (this should never happen).
    IntoHttp(IntoHttpError),
    /// The request's URL is invalid (this should never happen).
    Url(UrlError),
    /// Couldn't obtain an HTTP response (e.g. due to network or DNS issues).
    Response(ResponseError),
    /// Converting the HTTP response to one of ruma's types failed.
    FromHttpResponse(FromHttpResponseError<E>),
}

impl<E: Display> Display for Error<E> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::AuthenticationRequired => {
                write!(f, "The queried endpoint requires authentication but was called with an anonymous client.")
            }
            Self::IntoHttp(err) => write!(f, "HTTP request construction failed: {}", err),
            Self::Url(UrlError(err)) => write!(f, "Invalid URL: {}", err),
            Self::Response(ResponseError(err)) => write!(f, "Couldn't obtain a response: {}", err),
            Self::FromHttpResponse(err) => write!(f, "HTTP response conversion failed: {}", err),
        }
    }
}

impl<E> From<IntoHttpError> for Error<E> {
    fn from(err: IntoHttpError) -> Self {
        Error::IntoHttp(err)
    }
}

#[doc(hidden)]
impl<E> From<http::uri::InvalidUri> for Error<E> {
    fn from(err: http::uri::InvalidUri) -> Self {
        Error::Url(UrlError(err))
    }
}

#[doc(hidden)]
impl<E> From<hyper::Error> for Error<E> {
    fn from(err: hyper::Error) -> Self {
        Error::Response(ResponseError(err))
    }
}

impl<E> From<FromHttpResponseError<E>> for Error<E> {
    fn from(err: FromHttpResponseError<E>) -> Self {
        Error::FromHttpResponse(err)
    }
}

impl<E: Debug + Display> std::error::Error for Error<E> {}

#[derive(Debug)]
pub struct UrlError(http::uri::InvalidUri);

#[derive(Debug)]
pub struct ResponseError(hyper::Error);
<|endoftext|>