<commit_before>//! This module contains functions for retrieve the original AST from lowered
//! `hir`.

#![deny(missing_docs_in_private_items)]

use rustc::hir;
use rustc::lint::LateContext;
use syntax::ast;
use utils::{is_expn_of, match_path, match_def_path, resolve_node, paths};

/// Convert a hir binary operator to the corresponding `ast` type.
pub fn binop(op: hir::BinOp_) -> ast::BinOpKind {
    match op {
        hir::BiEq => ast::BinOpKind::Eq,
        hir::BiGe => ast::BinOpKind::Ge,
        hir::BiGt => ast::BinOpKind::Gt,
        hir::BiLe => ast::BinOpKind::Le,
        hir::BiLt => ast::BinOpKind::Lt,
        hir::BiNe => ast::BinOpKind::Ne,
        hir::BiOr => ast::BinOpKind::Or,
        hir::BiAdd => ast::BinOpKind::Add,
        hir::BiAnd => ast::BinOpKind::And,
        hir::BiBitAnd => ast::BinOpKind::BitAnd,
        hir::BiBitOr => ast::BinOpKind::BitOr,
        hir::BiBitXor => ast::BinOpKind::BitXor,
        hir::BiDiv => ast::BinOpKind::Div,
        hir::BiMul => ast::BinOpKind::Mul,
        hir::BiRem => ast::BinOpKind::Rem,
        hir::BiShl => ast::BinOpKind::Shl,
        hir::BiShr => ast::BinOpKind::Shr,
        hir::BiSub => ast::BinOpKind::Sub,
    }
}

/// Represent a range akin to `ast::ExprKind::Range`.
#[derive(Debug, Copy, Clone)]
pub struct Range<'a> {
    /// The lower bound of the range, or `None` for ranges such as `..X`.
    pub start: Option<&'a hir::Expr>,
    /// The upper bound of the range, or `None` for ranges such as `X..`.
    pub end: Option<&'a hir::Expr>,
    /// Whether the interval is open or closed.
    pub limits: ast::RangeLimits,
}

/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
pub fn range(expr: &hir::Expr) -> Option<Range> {
    /// Find the field named `name` in the field. Always return `Some` for
    /// convenience.
    fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
        let expr = &fields
            .iter()
            .find(|field| field.name.node == name)
            .unwrap_or_else(|| panic!("missing {} field for range", name))
            .expr;

        Some(expr)
    }

    // The range syntax is expanded to literal paths starting with `core` or `std`
    // depending on
    // `#[no_std]`. Testing both instead of resolving the paths.

    match expr.node {
        hir::ExprPath(ref path) => {
            if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) {
                Some(Range {
                    start: None,
                    end: None,
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else {
                None
            }
        },
        hir::ExprStruct(ref path, ref fields, None) => {
            if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) {
                Some(Range {
                    start: get_field("start", fields),
                    end: None,
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else if match_path(path, &paths::RANGE_INCLUSIVE_STD) || match_path(path, &paths::RANGE_INCLUSIVE) {
                Some(Range {
                    start: get_field("start", fields),
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::Closed,
                })
            } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) {
                Some(Range {
                    start: get_field("start", fields),
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) {
                Some(Range {
                    start: None,
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::Closed,
                })
            } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) {
                Some(Range {
                    start: None,
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else {
                None
            }
        },
        _ => None,
    }
}

/// Checks if a `let` decl is from a `for` loop desugaring.
pub fn is_from_for_desugar(decl: &hir::Decl) -> bool {
    if_let_chain! {[
        let hir::DeclLocal(ref loc) = decl.node,
        let Some(ref expr) = loc.init,
        let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node,
    ], {
        return true;
    }}

    // This detects a variable binding in for loop to avoid `let_unit_value`
    // lint (see issue #1964).
    //
    // ```
    // for _ in vec![()] {
    //   // anything
    // }
    // ```
    if_let_chain! {[
        let hir::DeclLocal(ref loc) = decl.node,
        let hir::LocalSource::ForLoopDesugar = loc.source,
    ], {
        return true;
    }}

    false
}

/// Recover the essential nodes of a desugared for loop:
/// `for pat in arg { body }` becomes `(pat, arg, body)`.
pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> {
    if_let_chain! {[
        let hir::ExprMatch(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node,
        let hir::ExprCall(_, ref iterargs) = iterexpr.node,
        iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(),
        let hir::ExprLoop(ref block, _, _) = arms[0].body.node,
        block.expr.is_none(),
        let [ _, _, ref let_stmt, ref body ] = *block.stmts,
        let hir::StmtDecl(ref decl, _) = let_stmt.node,
        let hir::DeclLocal(ref decl) = decl.node,
        let hir::StmtExpr(ref expr, _) = body.node,
    ], {
        return Some((&*decl.pat, &iterargs[0], expr));
    }}
    None
}

/// Represent the pre-expansion arguments of a `vec!` invocation.
pub enum VecArgs<'a> {
    /// `vec![elem; len]`
    Repeat(&'a hir::Expr, &'a hir::Expr),
    /// `vec![a, b, c]`
    Vec(&'a [hir::Expr]),
}

/// Returns the arguments of the `vec!` macro if this expression was expanded
/// from `vec!`.
pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e>> {
    if_let_chain!{[
        let hir::ExprCall(ref fun, ref args) = expr.node,
        let hir::ExprPath(ref path) = fun.node,
        is_expn_of(fun.span, "vec").is_some(),
    ], {
        let fun_def = resolve_node(cx, path, fun.hir_id);
        return if match_def_path(cx.tcx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
            // `vec![elem; size]` case
            Some(VecArgs::Repeat(&args[0], &args[1]))
        }
        else if match_def_path(cx.tcx, fun_def.def_id(), &paths::SLICE_INTO_VEC) && args.len() == 1 {
            // `vec![a, b, c]` case
            if_let_chain!{[
                let hir::ExprBox(ref boxed) = args[0].node,
                let hir::ExprArray(ref args) = boxed.node
            ], {
                return Some(VecArgs::Vec(&*args));
            }}

            None
        }
        else {
            None
        };
    }}

    None
}
<commit_msg>is_from_for_loop: document what first check matches<commit_after>//! This module contains functions for retrieve the original AST from lowered
//! `hir`.

#![deny(missing_docs_in_private_items)]

use rustc::hir;
use rustc::lint::LateContext;
use syntax::ast;
use utils::{is_expn_of, match_path, match_def_path, resolve_node, paths};

/// Convert a hir binary operator to the corresponding `ast` type.
pub fn binop(op: hir::BinOp_) -> ast::BinOpKind {
    match op {
        hir::BiEq => ast::BinOpKind::Eq,
        hir::BiGe => ast::BinOpKind::Ge,
        hir::BiGt => ast::BinOpKind::Gt,
        hir::BiLe => ast::BinOpKind::Le,
        hir::BiLt => ast::BinOpKind::Lt,
        hir::BiNe => ast::BinOpKind::Ne,
        hir::BiOr => ast::BinOpKind::Or,
        hir::BiAdd => ast::BinOpKind::Add,
        hir::BiAnd => ast::BinOpKind::And,
        hir::BiBitAnd => ast::BinOpKind::BitAnd,
        hir::BiBitOr => ast::BinOpKind::BitOr,
        hir::BiBitXor => ast::BinOpKind::BitXor,
        hir::BiDiv => ast::BinOpKind::Div,
        hir::BiMul => ast::BinOpKind::Mul,
        hir::BiRem => ast::BinOpKind::Rem,
        hir::BiShl => ast::BinOpKind::Shl,
        hir::BiShr => ast::BinOpKind::Shr,
        hir::BiSub => ast::BinOpKind::Sub,
    }
}

/// Represent a range akin to `ast::ExprKind::Range`.
#[derive(Debug, Copy, Clone)]
pub struct Range<'a> {
    /// The lower bound of the range, or `None` for ranges such as `..X`.
    pub start: Option<&'a hir::Expr>,
    /// The upper bound of the range, or `None` for ranges such as `X..`.
    pub end: Option<&'a hir::Expr>,
    /// Whether the interval is open or closed.
    pub limits: ast::RangeLimits,
}

/// Higher a `hir` range to something similar to `ast::ExprKind::Range`.
pub fn range(expr: &hir::Expr) -> Option<Range> {
    /// Find the field named `name` in the field. Always return `Some` for
    /// convenience.
    fn get_field<'a>(name: &str, fields: &'a [hir::Field]) -> Option<&'a hir::Expr> {
        let expr = &fields
            .iter()
            .find(|field| field.name.node == name)
            .unwrap_or_else(|| panic!("missing {} field for range", name))
            .expr;

        Some(expr)
    }

    // The range syntax is expanded to literal paths starting with `core` or `std`
    // depending on
    // `#[no_std]`. Testing both instead of resolving the paths.

    match expr.node {
        hir::ExprPath(ref path) => {
            if match_path(path, &paths::RANGE_FULL_STD) || match_path(path, &paths::RANGE_FULL) {
                Some(Range {
                    start: None,
                    end: None,
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else {
                None
            }
        },
        hir::ExprStruct(ref path, ref fields, None) => {
            if match_path(path, &paths::RANGE_FROM_STD) || match_path(path, &paths::RANGE_FROM) {
                Some(Range {
                    start: get_field("start", fields),
                    end: None,
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else if match_path(path, &paths::RANGE_INCLUSIVE_STD) || match_path(path, &paths::RANGE_INCLUSIVE) {
                Some(Range {
                    start: get_field("start", fields),
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::Closed,
                })
            } else if match_path(path, &paths::RANGE_STD) || match_path(path, &paths::RANGE) {
                Some(Range {
                    start: get_field("start", fields),
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else if match_path(path, &paths::RANGE_TO_INCLUSIVE_STD) || match_path(path, &paths::RANGE_TO_INCLUSIVE) {
                Some(Range {
                    start: None,
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::Closed,
                })
            } else if match_path(path, &paths::RANGE_TO_STD) || match_path(path, &paths::RANGE_TO) {
                Some(Range {
                    start: None,
                    end: get_field("end", fields),
                    limits: ast::RangeLimits::HalfOpen,
                })
            } else {
                None
            }
        },
        _ => None,
    }
}

/// Checks if a `let` decl is from a `for` loop desugaring.
pub fn is_from_for_desugar(decl: &hir::Decl) -> bool {
    // This will detect plain for-loops without an actual variable binding:
    //
    // ```
    // for x in some_vec {
    //   // do stuff
    // }
    // ```
    if_let_chain! {[
        let hir::DeclLocal(ref loc) = decl.node,
        let Some(ref expr) = loc.init,
        let hir::ExprMatch(_, _, hir::MatchSource::ForLoopDesugar) = expr.node,
    ], {
        return true;
    }}

    // This detects a variable binding in for loop to avoid `let_unit_value`
    // lint (see issue #1964).
    //
    // ```
    // for _ in vec![()] {
    //   // anything
    // }
    // ```
    if_let_chain! {[
        let hir::DeclLocal(ref loc) = decl.node,
        let hir::LocalSource::ForLoopDesugar = loc.source,
    ], {
        return true;
    }}

    false
}

/// Recover the essential nodes of a desugared for loop:
/// `for pat in arg { body }` becomes `(pat, arg, body)`.
pub fn for_loop(expr: &hir::Expr) -> Option<(&hir::Pat, &hir::Expr, &hir::Expr)> {
    if_let_chain! {[
        let hir::ExprMatch(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.node,
        let hir::ExprCall(_, ref iterargs) = iterexpr.node,
        iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none(),
        let hir::ExprLoop(ref block, _, _) = arms[0].body.node,
        block.expr.is_none(),
        let [ _, _, ref let_stmt, ref body ] = *block.stmts,
        let hir::StmtDecl(ref decl, _) = let_stmt.node,
        let hir::DeclLocal(ref decl) = decl.node,
        let hir::StmtExpr(ref expr, _) = body.node,
    ], {
        return Some((&*decl.pat, &iterargs[0], expr));
    }}
    None
}

/// Represent the pre-expansion arguments of a `vec!` invocation.
pub enum VecArgs<'a> {
    /// `vec![elem; len]`
    Repeat(&'a hir::Expr, &'a hir::Expr),
    /// `vec![a, b, c]`
    Vec(&'a [hir::Expr]),
}

/// Returns the arguments of the `vec!` macro if this expression was expanded
/// from `vec!`.
pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e>> {
    if_let_chain!{[
        let hir::ExprCall(ref fun, ref args) = expr.node,
        let hir::ExprPath(ref path) = fun.node,
        is_expn_of(fun.span, "vec").is_some(),
    ], {
        let fun_def = resolve_node(cx, path, fun.hir_id);
        return if match_def_path(cx.tcx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
            // `vec![elem; size]` case
            Some(VecArgs::Repeat(&args[0], &args[1]))
        }
        else if match_def_path(cx.tcx, fun_def.def_id(), &paths::SLICE_INTO_VEC) && args.len() == 1 {
            // `vec![a, b, c]` case
            if_let_chain!{[
                let hir::ExprBox(ref boxed) = args[0].node,
                let hir::ExprArray(ref args) = boxed.node
            ], {
                return Some(VecArgs::Vec(&*args));
            }}

            None
        }
        else {
            None
        };
    }}

    None
}
<|endoftext|>


<commit_before>use std::net::{TcpListener, ToSocketAddrs};
use std::thread;
use std::collections::HashMap;
use std;
use std::sync::{Arc, Mutex};
use serde_rosmsg::to_vec;
use super::error::{ErrorKind, Result, ResultExt};
use super::header;
use super::Message;
use super::util::streamfork::{fork, DataStream, TargetList};
use super::util::tcpconnection;

pub struct Publisher {
    subscriptions: DataStream,
    pub port: u16,
    pub msg_type: String,
    pub topic: String,
    last_message: Arc<Mutex<Arc<Vec<u8>>>>,
    _raii: tcpconnection::Raii,
}

fn read_request<T: Message, U: std::io::Read>(mut stream: &mut U, topic: &str) -> Result<()> {
    let fields = header::decode(&mut stream)?;
    header::match_field(&fields, "md5sum", &T::md5sum())?;
    header::match_field(&fields, "type", &T::msg_type())?;
    header::match_field(&fields, "topic", topic)?;
    if fields.get("callerid").is_none() {
        bail!(ErrorKind::HeaderMissingField("callerid".into()));
    }
    Ok(())
}

fn write_response<T: Message, U: std::io::Write>(mut stream: &mut U) -> Result<()> {
    let mut fields = HashMap::<String, String>::new();
    fields.insert(String::from("md5sum"), T::md5sum());
    fields.insert(String::from("type"), T::msg_type());
    header::encode(&mut stream, &fields)?;
    Ok(())
}

fn exchange_headers<T, U>(mut stream: &mut U, topic: &str) -> Result<()>
where
    T: Message,
    U: std::io::Write + std::io::Read,
{
    read_request::<T, U>(&mut stream, topic)?;
    write_response::<T, U>(&mut stream)
}

fn listen_for_subscribers<T, U, V>(
    topic: &str,
    listener: V,
    targets: &TargetList<U>,
    last_message: Arc<Mutex<Arc<Vec<u8>>>>,
) where
    T: Message,
    U: std::io::Read + std::io::Write + Send,
    V: Iterator<Item = U>,
{
    // This listener stream never breaks by itself since it's a TcpListener
    for mut stream in listener {
        let result = exchange_headers::<T, _>(&mut stream, topic)
            .chain_err(|| ErrorKind::TopicConnectionFail(topic.into()));
        if let Err(err) = result {
            let info = err.iter()
                .map(|v| format!("{}", v))
                .collect::<Vec<_>>()
                .join("\nCaused by:");
            error!("{}", info);
            continue;
        }

        if let Err(err) = stream.write_all(&last_message.lock().unwrap()) {
            error!("{}", err);
            continue;
        }

        if targets.add(stream).is_err() {
            // The TCP listener gets shut down when streamfork's thread deallocates.
            // This happens only when all the corresponding publisher streams get deallocated,
            // causing streamfork's data channel to shut down
            break;
        }
    }
}

impl Publisher {
    pub fn new<T, U>(address: U, topic: &str) -> Result<Publisher>
    where
        T: Message,
        U: ToSocketAddrs,
    {
        let listener = TcpListener::bind(address)?;
        let socket_address = listener.local_addr()?;
        let (raii, listener) = tcpconnection::iterate(listener, format!("topic '{}'", topic));
        Ok(Publisher::wrap_stream::<T, _, _>(
            topic,
            raii,
            listener,
            socket_address.port(),
        ))
    }

    fn wrap_stream<T, U, V>(
        topic: &str,
        raii: tcpconnection::Raii,
        listener: V,
        port: u16,
    ) -> Publisher
    where
        T: Message,
        U: std::io::Read + std::io::Write + Send + 'static,
        V: Iterator<Item = U> + Send + 'static,
    {
        let (targets, data) = fork();
        let topic_name = String::from(topic);
        let last_message = Arc::new(Mutex::new(Arc::new(Vec::new())));
        let last_msg_for_thread = Arc::clone(&last_message);
        thread::spawn(move || {
            listen_for_subscribers::<T, _, _>(&topic_name, listener, &targets, last_msg_for_thread)
        });
        Publisher {
            subscriptions: data,
            port: port,
            msg_type: T::msg_type(),
            topic: String::from(topic),
            last_message,
            _raii: raii,
        }
    }

    pub fn stream<T: Message>(&self) -> Result<PublisherStream<T>> {
        PublisherStream::new(self)
    }
}

// TODO: publisher should only be removed from master API once the publisher and all
// publisher streams are gone. This should be done with a RAII Arc, residing next todo
// the datastream. So maybe replace DataStream with a wrapper that holds that Arc too

#[derive(Clone)]
pub struct PublisherStream<T: Message> {
    stream: DataStream,
    last_message: Arc<Mutex<Arc<Vec<u8>>>>,
    datatype: std::marker::PhantomData<T>,
    latching: bool,
}

impl<T: Message> PublisherStream<T> {
    fn new(publisher: &Publisher) -> Result<PublisherStream<T>> {
        let msg_type = T::msg_type();
        if publisher.msg_type != msg_type {
            bail!(ErrorKind::MessageTypeMismatch(
                publisher.msg_type.clone(),
                msg_type,
            ));
        }
        Ok(PublisherStream {
            stream: publisher.subscriptions.clone(),
            datatype: std::marker::PhantomData,
            last_message: Arc::clone(&publisher.last_message),
            latching: true,
        })
    }

    #[inline]
    pub fn set_latching(&mut self, latching: bool) {
        self.latching = latching;
    }

    pub fn send(&mut self, message: &T) -> Result<()> {
        let bytes = Arc::new(to_vec(message)?);

        if self.latching {
            *self.last_message.lock().unwrap() = Arc::clone(&bytes);
        }

        // Subscriptions can only be closed from the Publisher side
        // There is no way for the streamfork thread to fail by itself
        self.stream.send(bytes).expect("Connected thread died");
        Ok(())
    }
}
<commit_msg>Flip latching defaults<commit_after>use std::net::{TcpListener, ToSocketAddrs};
use std::thread;
use std::collections::HashMap;
use std;
use std::sync::{Arc, Mutex};
use serde_rosmsg::to_vec;
use super::error::{ErrorKind, Result, ResultExt};
use super::header;
use super::Message;
use super::util::streamfork::{fork, DataStream, TargetList};
use super::util::tcpconnection;

pub struct Publisher {
    subscriptions: DataStream,
    pub port: u16,
    pub msg_type: String,
    pub topic: String,
    last_message: Arc<Mutex<Arc<Vec<u8>>>>,
    _raii: tcpconnection::Raii,
}

fn read_request<T: Message, U: std::io::Read>(mut stream: &mut U, topic: &str) -> Result<()> {
    let fields = header::decode(&mut stream)?;
    header::match_field(&fields, "md5sum", &T::md5sum())?;
    header::match_field(&fields, "type", &T::msg_type())?;
    header::match_field(&fields, "topic", topic)?;
    if fields.get("callerid").is_none() {
        bail!(ErrorKind::HeaderMissingField("callerid".into()));
    }
    Ok(())
}

fn write_response<T: Message, U: std::io::Write>(mut stream: &mut U) -> Result<()> {
    let mut fields = HashMap::<String, String>::new();
    fields.insert(String::from("md5sum"), T::md5sum());
    fields.insert(String::from("type"), T::msg_type());
    header::encode(&mut stream, &fields)?;
    Ok(())
}

fn exchange_headers<T, U>(mut stream: &mut U, topic: &str) -> Result<()>
where
    T: Message,
    U: std::io::Write + std::io::Read,
{
    read_request::<T, U>(&mut stream, topic)?;
    write_response::<T, U>(&mut stream)
}

fn listen_for_subscribers<T, U, V>(
    topic: &str,
    listener: V,
    targets: &TargetList<U>,
    last_message: Arc<Mutex<Arc<Vec<u8>>>>,
) where
    T: Message,
    U: std::io::Read + std::io::Write + Send,
    V: Iterator<Item = U>,
{
    // This listener stream never breaks by itself since it's a TcpListener
    for mut stream in listener {
        let result = exchange_headers::<T, _>(&mut stream, topic)
            .chain_err(|| ErrorKind::TopicConnectionFail(topic.into()));
        if let Err(err) = result {
            let info = err.iter()
                .map(|v| format!("{}", v))
                .collect::<Vec<_>>()
                .join("\nCaused by:");
            error!("{}", info);
            continue;
        }

        if let Err(err) = stream.write_all(&last_message.lock().unwrap()) {
            error!("{}", err);
            continue;
        }

        if targets.add(stream).is_err() {
            // The TCP listener gets shut down when streamfork's thread deallocates.
            // This happens only when all the corresponding publisher streams get deallocated,
            // causing streamfork's data channel to shut down
            break;
        }
    }
}

impl Publisher {
    pub fn new<T, U>(address: U, topic: &str) -> Result<Publisher>
    where
        T: Message,
        U: ToSocketAddrs,
    {
        let listener = TcpListener::bind(address)?;
        let socket_address = listener.local_addr()?;
        let (raii, listener) = tcpconnection::iterate(listener, format!("topic '{}'", topic));
        Ok(Publisher::wrap_stream::<T, _, _>(
            topic,
            raii,
            listener,
            socket_address.port(),
        ))
    }

    fn wrap_stream<T, U, V>(
        topic: &str,
        raii: tcpconnection::Raii,
        listener: V,
        port: u16,
    ) -> Publisher
    where
        T: Message,
        U: std::io::Read + std::io::Write + Send + 'static,
        V: Iterator<Item = U> + Send + 'static,
    {
        let (targets, data) = fork();
        let topic_name = String::from(topic);
        let last_message = Arc::new(Mutex::new(Arc::new(Vec::new())));
        let last_msg_for_thread = Arc::clone(&last_message);
        thread::spawn(move || {
            listen_for_subscribers::<T, _, _>(&topic_name, listener, &targets, last_msg_for_thread)
        });
        Publisher {
            subscriptions: data,
            port: port,
            msg_type: T::msg_type(),
            topic: String::from(topic),
            last_message,
            _raii: raii,
        }
    }

    pub fn stream<T: Message>(&self) -> Result<PublisherStream<T>> {
        PublisherStream::new(self)
    }
}

// TODO: publisher should only be removed from master API once the publisher and all
// publisher streams are gone. This should be done with a RAII Arc, residing next todo
// the datastream. So maybe replace DataStream with a wrapper that holds that Arc too

#[derive(Clone)]
pub struct PublisherStream<T: Message> {
    stream: DataStream,
    last_message: Arc<Mutex<Arc<Vec<u8>>>>,
    datatype: std::marker::PhantomData<T>,
    latching: bool,
}

impl<T: Message> PublisherStream<T> {
    fn new(publisher: &Publisher) -> Result<PublisherStream<T>> {
        let msg_type = T::msg_type();
        if publisher.msg_type != msg_type {
            bail!(ErrorKind::MessageTypeMismatch(
                publisher.msg_type.clone(),
                msg_type,
            ));
        }
        Ok(PublisherStream {
            stream: publisher.subscriptions.clone(),
            datatype: std::marker::PhantomData,
            last_message: Arc::clone(&publisher.last_message),
            latching: false,
        })
    }

    #[inline]
    pub fn set_latching(&mut self, latching: bool) {
        self.latching = latching;
    }

    pub fn send(&mut self, message: &T) -> Result<()> {
        let bytes = Arc::new(to_vec(message)?);

        if self.latching {
            *self.last_message.lock().unwrap() = Arc::clone(&bytes);
        }

        // Subscriptions can only be closed from the Publisher side
        // There is no way for the streamfork thread to fail by itself
        self.stream.send(bytes).expect("Connected thread died");
        Ok(())
    }
}
<|endoftext|>


<commit_before>use libc;
use std::cell::Cell;

use cairo::{self, MatrixTrait};

use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::{self, RsvgDrawingCtx};
use handle::RsvgHandle;
use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
use parsers::parse;
use property_bag::PropertyBag;
use state::ComputedValues;

coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);

pub struct NodeClipPath {
    units: Cell<ClipPathUnits>,
}

impl NodeClipPath {
    fn new() -> NodeClipPath {
        NodeClipPath {
            units: Cell::new(ClipPathUnits::default()),
        }
    }

    pub fn get_units(&self) -> ClipPathUnits {
        self.units.get()
    }

    pub fn to_cairo_context(&self, node: &RsvgNode, draw_ctx: *mut RsvgDrawingCtx) {
        let values = &node.get_computed_values();

        let clip_units = self.units.get();

        let orig_bbox = drawing_ctx::get_bbox(draw_ctx).clone();

        let cr = drawing_ctx::get_cairo_context(draw_ctx);

        let cr_save_transform = cr.get_matrix();

        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            let rect = orig_bbox.rect.unwrap();

            let bbtransform = cairo::Matrix::new(rect.width, 0.0, 0.0, rect.height, rect.x, rect.y);
            cr.transform(bbtransform);
            println!("clipping objectBoundingBox");
        } else {
            println!("clipping userSpaceOnUse");
        }

        drawing_ctx::state_push(draw_ctx);

        drawing_ctx::state_reinherit_top(draw_ctx, node.get_state(), 0);
        drawing_ctx::push_discrete_layer(draw_ctx, values, true);
        node.draw_children(values, draw_ctx, -1, true);
        drawing_ctx::pop_discrete_layer(draw_ctx, values, true);

        drawing_ctx::state_pop(draw_ctx);

        // FIXME: this is an EPIC HACK to keep the clipping context from
        // accumulating bounding boxes.  We'll remove this later, when we
        // are able to extract bounding boxes from outside the
        // general drawing loop.
        drawing_ctx::set_bbox(draw_ctx, &orig_bbox);

        let cr = drawing_ctx::get_cairo_context(draw_ctx);
        cr.clip();

        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            cr.set_matrix(cr_save_transform);
        }
    }
}

impl NodeTrait for NodeClipPath {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::ClipPathUnits => {
                    self.units.set(parse("clipPathUnits", value, (), None)?)
                }

                _ => (),
            }
        }

        Ok(())
    }

    fn draw(&self, _: &RsvgNode, _: &ComputedValues, _: *mut RsvgDrawingCtx, _: i32, _: bool) {
        // nothing; clip paths are handled specially
    }

    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        unreachable!();
    }
}

#[no_mangle]
pub extern "C" fn rsvg_node_clip_path_new(
    _: *const libc::c_char,
    raw_parent: *const RsvgNode,
) -> *const RsvgNode {
    boxed_node_new(
        NodeType::ClipPath,
        raw_parent,
        Box::new(NodeClipPath::new()),
    )
}
<commit_msg>wip: try to fix clipping<commit_after>use libc;
use std::cell::Cell;

use cairo::{self, MatrixTrait};

use attributes::Attribute;
use coord_units::CoordUnits;
use drawing_ctx::{self, RsvgDrawingCtx};
use handle::RsvgHandle;
use node::{boxed_node_new, NodeResult, NodeTrait, NodeType, RsvgCNodeImpl, RsvgNode};
use parsers::parse;
use property_bag::PropertyBag;
use state::ComputedValues;

coord_units!(ClipPathUnits, CoordUnits::UserSpaceOnUse);

pub struct NodeClipPath {
    units: Cell<ClipPathUnits>,
}

impl NodeClipPath {
    fn new() -> NodeClipPath {
        NodeClipPath {
            units: Cell::new(ClipPathUnits::default()),
        }
    }

    pub fn get_units(&self) -> ClipPathUnits {
        self.units.get()
    }

    pub fn to_cairo_context(&self, node: &RsvgNode, draw_ctx: *mut RsvgDrawingCtx) {
        let values = &node.get_computed_values();

        let clip_units = self.units.get();

        let orig_bbox = drawing_ctx::get_bbox(draw_ctx).clone();

        let cr = drawing_ctx::get_cairo_context(draw_ctx);

        //        let cr_save_transform = cr.get_matrix();

        let child_matrix = if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
            let rect = orig_bbox.rect.unwrap();

            let mut bbtransform =
                cairo::Matrix::new(rect.width, 0.0, 0.0, rect.height, rect.x, rect.y);
            println!("clipping objectBoundingBox");
            cairo::Matrix::multiply(&bbtransform, &cr.get_matrix())
        } else {
            println!("clipping userSpaceOnUse");
            cr.get_matrix()
        };

        drawing_ctx::state_push(draw_ctx);

        drawing_ctx::state_reinherit_top(draw_ctx, node.get_state(), 0);
        drawing_ctx::push_discrete_layer(draw_ctx, values, true);

        let cr = drawing_ctx::get_cairo_context(draw_ctx);
        cr.set_matrix(child_matrix);

        node.draw_children(values, draw_ctx, -1, true);

        drawing_ctx::pop_discrete_layer(draw_ctx, values, true);

        drawing_ctx::state_pop(draw_ctx);

        // FIXME: this is an EPIC HACK to keep the clipping context from
        // accumulating bounding boxes.  We'll remove this later, when we
        // are able to extract bounding boxes from outside the
        // general drawing loop.
        drawing_ctx::set_bbox(draw_ctx, &orig_bbox);

        let cr = drawing_ctx::get_cairo_context(draw_ctx);
        cr.clip();

        //        if clip_units == ClipPathUnits(CoordUnits::ObjectBoundingBox) {
        //            cr.set_matrix(cr_save_transform);
        //        }
    }
}

impl NodeTrait for NodeClipPath {
    fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
        for (_key, attr, value) in pbag.iter() {
            match attr {
                Attribute::ClipPathUnits => {
                    self.units.set(parse("clipPathUnits", value, (), None)?)
                }

                _ => (),
            }
        }

        Ok(())
    }

    fn draw(&self, _: &RsvgNode, _: &ComputedValues, _: *mut RsvgDrawingCtx, _: i32, _: bool) {
        // nothing; clip paths are handled specially
    }

    fn get_c_impl(&self) -> *const RsvgCNodeImpl {
        unreachable!();
    }
}

#[no_mangle]
pub extern "C" fn rsvg_node_clip_path_new(
    _: *const libc::c_char,
    raw_parent: *const RsvgNode,
) -> *const RsvgNode {
    boxed_node_new(
        NodeType::ClipPath,
        raw_parent,
        Box::new(NodeClipPath::new()),
    )
}
<|endoftext|>


<commit_before>use cairo;

use std::f64::consts::*;

use cairo::MatrixTrait;
use cssparser::{ParseError as CssParseError, Parser, ParserInput, Token};

use error::*;
use parsers::{optional_comma, Parse, ParseError};

impl Parse for cairo::Matrix {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _: ()) -> Result<cairo::Matrix, AttributeError> {
        parse_transform(s)
    }
}

// This parser is for the "transform" attribute in SVG.
// Its operataion and grammar are described here:
// https://www.w3.org/TR/SVG/coords.html#TransformAttribute

pub fn parse_transform(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let matrix = parse_transform_list(s)?;

    matrix
        .try_invert()
        .map(|_| matrix)
        .map_err(|_| AttributeError::Value("invalid transformation matrix".to_string()))
}

fn parse_transform_list(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let mut matrix = cairo::Matrix::identity();

    loop {
        if parser.is_exhausted() {
            break;
        }

        let m = parse_transform_command(&mut parser)?;
        matrix = cairo::Matrix::multiply(&m, &matrix);

        optional_comma(&mut parser);
    }

    Ok(matrix)
}

fn make_expected_function_error() -> AttributeError {
    AttributeError::from(ParseError::new(
        "expected matrix|translate|scale|rotate|skewX|skewY",
    ))
}

fn parse_transform_command(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match parser.next()?.clone() {
        Token::Function(ref name) => parse_transform_function(name, parser),

        Token::Ident(ref name) => {
            parser.expect_parenthesis_block()?;
            parse_transform_function(name, parser)
        }

        _ => Err(make_expected_function_error()),
    }
}

fn parse_transform_function(
    name: &str,
    parser: &mut Parser,
) -> Result<cairo::Matrix, AttributeError> {
    match name {
        "matrix" => parse_matrix_args(parser),
        "translate" => parse_translate_args(parser),
        "scale" => parse_scale_args(parser),
        "rotate" => parse_rotate_args(parser),
        "skewX" => parse_skewx_args(parser),
        "skewY" => parse_skewy_args(parser),
        _ => Err(make_expected_function_error()),
    }
}

fn parse_matrix_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let xx = f64::from(p.expect_number()?);
            optional_comma(p);

            let yx = f64::from(p.expect_number()?);
            optional_comma(p);

            let xy = f64::from(p.expect_number()?);
            optional_comma(p);

            let yy = f64::from(p.expect_number()?);
            optional_comma(p);

            let x0 = f64::from(p.expect_number()?);
            optional_comma(p);

            let y0 = f64::from(p.expect_number()?);

            Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_translate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let tx = f64::from(p.expect_number()?);

            let ty = f64::from(p.try(|p| -> Result<f32, CssParseError<()>> {
                optional_comma(p);
                Ok(p.expect_number()?)
            }).unwrap_or(0.0));

            Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_scale_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let x = f64::from(p.expect_number()?);

            let y = p.try(|p| -> Result<f32, CssParseError<()>> {
                optional_comma(p);
                Ok(p.expect_number()?)
            }).map(f64::from)
                .unwrap_or(x);

            Ok(cairo::Matrix::new(x, 0.0, 0.0, y, 0.0, 0.0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_rotate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let angle = f64::from(p.expect_number()?) * PI / 180.0;
            let (s, c) = angle.sin_cos();

            let (tx, ty) = p.try(|p| -> Result<_, CssParseError<()>> {
                optional_comma(p);
                let tx = f64::from(p.expect_number()?);

                optional_comma(p);
                let ty = f64::from(p.expect_number()?);

                Ok((tx, ty))
            }).unwrap_or((0.0, 0.0));

            let mut m = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty);

            m = cairo::Matrix::multiply(&cairo::Matrix::new(c, s, -s, c, 0.0, 0.0), &m);
            m = cairo::Matrix::multiply(&cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
            Ok(m)
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_skewx_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let a = f64::from(p.expect_number()?) * PI / 180.0;
            Ok(cairo::Matrix::new(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_skewy_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let a = f64::from(p.expect_number()?) * PI / 180.0;
            Ok(cairo::Matrix::new(1.0, a.tan(), 0.0, 1.0, 0.0, 0.0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

#[cfg(test)]
fn make_rotation_matrix(angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity();
    r.rotate(angle);
    m = cairo::Matrix::multiply(&r, &m);

    m = cairo::Matrix::multiply(&cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

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

    #[test]
    fn parses_valid_transform() {
        let t = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix(30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply(&s, &t);
        assert_eq!(
            parse_transform("translate(20, 30), scale (10) rotate (30 10 10)").unwrap(),
            cairo::Matrix::multiply(&r, &a)
        );
    }

    fn assert_parse_error(s: &str) {
        match parse_transform(s) {
            Err(AttributeError::Parse(_)) => {}
            _ => {
                panic!();
            }
        }
    }

    #[test]
    fn syntax_error_yields_parse_error() {
        assert_parse_error("foo");
        assert_parse_error("matrix (1 2 3 4 5)");
        assert_parse_error("translate(1 2 3 4 5)");
        assert_parse_error("translate (1,)");
        assert_parse_error("scale (1,)");
        assert_parse_error("skewX (1,2)");
        assert_parse_error("skewY ()");
        assert_parse_error("skewY");
    }

    #[test]
    fn invalid_transform_yields_value_error() {
        match parse_transform("matrix (0 0 0 0 0 0)") {
            Err(AttributeError::Value(_)) => {}
            _ => {
                panic!();
            }
        }

        match parse_transform("scale (0), translate (10, 10)") {
            Err(AttributeError::Value(_)) => {}
            _ => {
                panic!();
            }
        }

        match parse_transform("scale (0), skewX (90)") {
            Err(AttributeError::Value(_)) => {}
            _ => {
                panic!();
            }
        }
    }
}

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

    #[test]
    fn parses_matrix() {
        assert_eq!(
            parse_transform("matrix (1 2 3 4 5 6)").unwrap(),
            cairo::Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
        );

        assert_eq!(
            parse_transform("matrix(1,2,3,4 5 6)").unwrap(),
            cairo::Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
        );

        assert_eq!(
            parse_transform("matrix (1,2.25,-3.25e2,4 5 6)").unwrap(),
            cairo::Matrix::new(1.0, 2.25, -325.0, 4.0, 5.0, 6.0)
        );
    }

    #[test]
    fn parses_translate() {
        assert_eq!(
            parse_transform("translate(-1 -2)").unwrap(),
            cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, -2.0)
        );

        assert_eq!(
            parse_transform("translate(-1, -2)").unwrap(),
            cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, -2.0)
        );

        assert_eq!(
            parse_transform("translate(-1)").unwrap(),
            cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, 0.0)
        );
    }

    #[test]
    fn parses_scale() {
        assert_eq!(
            parse_transform("scale (-1)").unwrap(),
            cairo::Matrix::new(-1.0, 0.0, 0.0, -1.0, 0.0, 0.0)
        );

        assert_eq!(
            parse_transform("scale(-1 -2)").unwrap(),
            cairo::Matrix::new(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0)
        );

        assert_eq!(
            parse_transform("scale(-1, -2)").unwrap(),
            cairo::Matrix::new(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0)
        );
    }

    #[test]
    fn parses_rotate() {
        assert_eq!(
            parse_transform("rotate (30)").unwrap(),
            make_rotation_matrix(30.0, 0.0, 0.0)
        );
        assert_eq!(
            parse_transform("rotate (30,-1,-2)").unwrap(),
            make_rotation_matrix(30.0, -1.0, -2.0)
        );
        assert_eq!(
            parse_transform("rotate(30, -1, -2)").unwrap(),
            make_rotation_matrix(30.0, -1.0, -2.0)
        );
    }

    fn make_skew_x_matrix(angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0)
    }

    fn make_skew_y_matrix(angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix(angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x() {
        assert_eq!(
            parse_transform("skewX (30)").unwrap(),
            make_skew_x_matrix(30.0)
        );
    }

    #[test]
    fn parses_skew_y() {
        assert_eq!(
            parse_transform("skewY (30)").unwrap(),
            make_skew_y_matrix(30.0)
        );
    }

    #[test]
    fn parses_transform_list() {
        let t = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix(30.0, 10.0, 10.0);

        assert_eq!(
            parse_transform("scale(10)rotate(30, 10, 10)").unwrap(),
            cairo::Matrix::multiply(&r, &s)
        );

        assert_eq!(
            parse_transform("translate(20, 30), scale (10)").unwrap(),
            cairo::Matrix::multiply(&s, &t)
        );

        let a = cairo::Matrix::multiply(&s, &t);
        assert_eq!(
            parse_transform("translate(20, 30), scale (10) rotate (30 10 10)").unwrap(),
            cairo::Matrix::multiply(&r, &a)
        );
    }

    #[test]
    fn parses_empty() {
        assert_eq!(parse_transform("").unwrap(), cairo::Matrix::identity());
    }
}
<commit_msg>Inline parse_transform() into its only caller<commit_after>use cairo;

use std::f64::consts::*;

use cairo::MatrixTrait;
use cssparser::{ParseError as CssParseError, Parser, ParserInput, Token};

use error::*;
use parsers::{optional_comma, Parse, ParseError};

impl Parse for cairo::Matrix {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _: ()) -> Result<cairo::Matrix, AttributeError> {
        let matrix = parse_transform_list(s)?;

        matrix
            .try_invert()
            .map(|_| matrix)
            .map_err(|_| AttributeError::Value("invalid transformation matrix".to_string()))
    }
}

// This parser is for the "transform" attribute in SVG.
// Its operataion and grammar are described here:
// https://www.w3.org/TR/SVG/coords.html#TransformAttribute

fn parse_transform_list(s: &str) -> Result<cairo::Matrix, AttributeError> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let mut matrix = cairo::Matrix::identity();

    loop {
        if parser.is_exhausted() {
            break;
        }

        let m = parse_transform_command(&mut parser)?;
        matrix = cairo::Matrix::multiply(&m, &matrix);

        optional_comma(&mut parser);
    }

    Ok(matrix)
}

fn make_expected_function_error() -> AttributeError {
    AttributeError::from(ParseError::new(
        "expected matrix|translate|scale|rotate|skewX|skewY",
    ))
}

fn parse_transform_command(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    match parser.next()?.clone() {
        Token::Function(ref name) => parse_transform_function(name, parser),

        Token::Ident(ref name) => {
            parser.expect_parenthesis_block()?;
            parse_transform_function(name, parser)
        }

        _ => Err(make_expected_function_error()),
    }
}

fn parse_transform_function(
    name: &str,
    parser: &mut Parser,
) -> Result<cairo::Matrix, AttributeError> {
    match name {
        "matrix" => parse_matrix_args(parser),
        "translate" => parse_translate_args(parser),
        "scale" => parse_scale_args(parser),
        "rotate" => parse_rotate_args(parser),
        "skewX" => parse_skewx_args(parser),
        "skewY" => parse_skewy_args(parser),
        _ => Err(make_expected_function_error()),
    }
}

fn parse_matrix_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let xx = f64::from(p.expect_number()?);
            optional_comma(p);

            let yx = f64::from(p.expect_number()?);
            optional_comma(p);

            let xy = f64::from(p.expect_number()?);
            optional_comma(p);

            let yy = f64::from(p.expect_number()?);
            optional_comma(p);

            let x0 = f64::from(p.expect_number()?);
            optional_comma(p);

            let y0 = f64::from(p.expect_number()?);

            Ok(cairo::Matrix::new(xx, yx, xy, yy, x0, y0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_translate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let tx = f64::from(p.expect_number()?);

            let ty = f64::from(p.try(|p| -> Result<f32, CssParseError<()>> {
                optional_comma(p);
                Ok(p.expect_number()?)
            }).unwrap_or(0.0));

            Ok(cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_scale_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let x = f64::from(p.expect_number()?);

            let y = p.try(|p| -> Result<f32, CssParseError<()>> {
                optional_comma(p);
                Ok(p.expect_number()?)
            }).map(f64::from)
                .unwrap_or(x);

            Ok(cairo::Matrix::new(x, 0.0, 0.0, y, 0.0, 0.0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_rotate_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let angle = f64::from(p.expect_number()?) * PI / 180.0;
            let (s, c) = angle.sin_cos();

            let (tx, ty) = p.try(|p| -> Result<_, CssParseError<()>> {
                optional_comma(p);
                let tx = f64::from(p.expect_number()?);

                optional_comma(p);
                let ty = f64::from(p.expect_number()?);

                Ok((tx, ty))
            }).unwrap_or((0.0, 0.0));

            let mut m = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty);

            m = cairo::Matrix::multiply(&cairo::Matrix::new(c, s, -s, c, 0.0, 0.0), &m);
            m = cairo::Matrix::multiply(&cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
            Ok(m)
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_skewx_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let a = f64::from(p.expect_number()?) * PI / 180.0;
            Ok(cairo::Matrix::new(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

fn parse_skewy_args(parser: &mut Parser) -> Result<cairo::Matrix, AttributeError> {
    parser
        .parse_nested_block(|p| {
            let a = f64::from(p.expect_number()?) * PI / 180.0;
            Ok(cairo::Matrix::new(1.0, a.tan(), 0.0, 1.0, 0.0, 0.0))
        })
        .map_err(CssParseError::<()>::basic)
        .map_err(AttributeError::from)
}

#[cfg(test)]
fn make_rotation_matrix(angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity();
    r.rotate(angle);
    m = cairo::Matrix::multiply(&r, &m);

    m = cairo::Matrix::multiply(&cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

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

    fn parse_transform(s: &str) -> Result<cairo::Matrix, AttributeError> {
        cairo::Matrix::parse(s, ())
    }

    #[test]
    fn parses_valid_transform() {
        let t = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix(30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply(&s, &t);
        assert_eq!(
            parse_transform("translate(20, 30), scale (10) rotate (30 10 10)").unwrap(),
            cairo::Matrix::multiply(&r, &a)
        );
    }

    fn assert_parse_error(s: &str) {
        match parse_transform(s) {
            Err(AttributeError::Parse(_)) => {}
            _ => {
                panic!();
            }
        }
    }

    #[test]
    fn syntax_error_yields_parse_error() {
        assert_parse_error("foo");
        assert_parse_error("matrix (1 2 3 4 5)");
        assert_parse_error("translate(1 2 3 4 5)");
        assert_parse_error("translate (1,)");
        assert_parse_error("scale (1,)");
        assert_parse_error("skewX (1,2)");
        assert_parse_error("skewY ()");
        assert_parse_error("skewY");
    }

    #[test]
    fn invalid_transform_yields_value_error() {
        match parse_transform("matrix (0 0 0 0 0 0)") {
            Err(AttributeError::Value(_)) => {}
            _ => {
                panic!();
            }
        }

        match parse_transform("scale (0), translate (10, 10)") {
            Err(AttributeError::Value(_)) => {}
            _ => {
                panic!();
            }
        }

        match parse_transform("scale (0), skewX (90)") {
            Err(AttributeError::Value(_)) => {}
            _ => {
                panic!();
            }
        }
    }

    #[test]
    fn parses_matrix() {
        assert_eq!(
            parse_transform("matrix (1 2 3 4 5 6)").unwrap(),
            cairo::Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
        );

        assert_eq!(
            parse_transform("matrix(1,2,3,4 5 6)").unwrap(),
            cairo::Matrix::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
        );

        assert_eq!(
            parse_transform("matrix (1,2.25,-3.25e2,4 5 6)").unwrap(),
            cairo::Matrix::new(1.0, 2.25, -325.0, 4.0, 5.0, 6.0)
        );
    }

    #[test]
    fn parses_translate() {
        assert_eq!(
            parse_transform("translate(-1 -2)").unwrap(),
            cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, -2.0)
        );

        assert_eq!(
            parse_transform("translate(-1, -2)").unwrap(),
            cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, -2.0)
        );

        assert_eq!(
            parse_transform("translate(-1)").unwrap(),
            cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, -1.0, 0.0)
        );
    }

    #[test]
    fn parses_scale() {
        assert_eq!(
            parse_transform("scale (-1)").unwrap(),
            cairo::Matrix::new(-1.0, 0.0, 0.0, -1.0, 0.0, 0.0)
        );

        assert_eq!(
            parse_transform("scale(-1 -2)").unwrap(),
            cairo::Matrix::new(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0)
        );

        assert_eq!(
            parse_transform("scale(-1, -2)").unwrap(),
            cairo::Matrix::new(-1.0, 0.0, 0.0, -2.0, 0.0, 0.0)
        );
    }

    #[test]
    fn parses_rotate() {
        assert_eq!(
            parse_transform("rotate (30)").unwrap(),
            make_rotation_matrix(30.0, 0.0, 0.0)
        );
        assert_eq!(
            parse_transform("rotate (30,-1,-2)").unwrap(),
            make_rotation_matrix(30.0, -1.0, -2.0)
        );
        assert_eq!(
            parse_transform("rotate(30, -1, -2)").unwrap(),
            make_rotation_matrix(30.0, -1.0, -2.0)
        );
    }

    fn make_skew_x_matrix(angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new(1.0, 0.0, a.tan(), 1.0, 0.0, 0.0)
    }

    fn make_skew_y_matrix(angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix(angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x() {
        assert_eq!(
            parse_transform("skewX (30)").unwrap(),
            make_skew_x_matrix(30.0)
        );
    }

    #[test]
    fn parses_skew_y() {
        assert_eq!(
            parse_transform("skewY (30)").unwrap(),
            make_skew_y_matrix(30.0)
        );
    }

    #[test]
    fn parses_transform_list() {
        let t = cairo::Matrix::new(1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new(10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix(30.0, 10.0, 10.0);

        assert_eq!(
            parse_transform("scale(10)rotate(30, 10, 10)").unwrap(),
            cairo::Matrix::multiply(&r, &s)
        );

        assert_eq!(
            parse_transform("translate(20, 30), scale (10)").unwrap(),
            cairo::Matrix::multiply(&s, &t)
        );

        let a = cairo::Matrix::multiply(&s, &t);
        assert_eq!(
            parse_transform("translate(20, 30), scale (10) rotate (30 10 10)").unwrap(),
            cairo::Matrix::multiply(&r, &a)
        );
    }

    #[test]
    fn parses_empty() {
        assert_eq!(parse_transform("").unwrap(), cairo::Matrix::identity());
    }
}
<|endoftext|>


<commit_before>#!/usr/bin/env run-cargo-script
//! ```cargo
//! [dependencies]
//! unixbar = "0"
//! systemstat = "0"
//! ```

#[macro_use] extern crate unixbar;
extern crate systemstat;
use unixbar::*;
use systemstat::{System, Platform};

fn main() {
    UnixBar::new(LemonbarFormatter::new())

        .add(Text::new(bfmt![click[MouseButton::Left => "notify-send hi"]
                             click[MouseButton::Right => "notify-send 'what?'"]
                             fg["#11bb55"] text[" Hello World! "]]))

        .add(Bspwm::new(|desktops| Format::Concat(desktops.iter().map(|d| Box::new({
                let bg = if d.focused { "#99aa11" } else { "#111111" };
                bfmt![click[MouseButton::Left => format!("bspc desktop -f {}", d.name)]
                      bg[bg] fmt[" {} ", d.name]]
            })).collect())))

        .add(Text::new(bfmt![right]))

        .add(Periodic::new(
             Duration::from_secs(2),
             || match System::new().memory() {
                 Ok(mem) => bfmt![bg["#556677"] fmt[" {}/{} RAM ", mem.free.to_string(false).replace(" GB", ""),
                                                    mem.free + mem.active + mem.inactive + mem.wired + mem.cache]],
                 Err(_) => bfmt![fg["#bb1155"] text["error"]],
             }))

        .add(Delayed::new(
             Duration::from_secs(1),
             || System::new().cpu_load_aggregate().unwrap(),
             |res| match res {
                 Ok(cpu) => bfmt![fg["#99aaff"] fmt[" {:04.1}% CPU ", (1.0 - cpu.idle) * 100.0]],
                 Err(_) => bfmt![fg["#bb1155"] text["error"]],
             }))

        .add(Wrap::new(
             |f| bfmt![fg["#bb1155"] f],
             DateTime::new(" %Y-%m-%d %H:%M:%S %z ")))

        .run();
}
<commit_msg>update example for systemstat update<commit_after>#!/usr/bin/env run-cargo-script
//! ```cargo
//! [dependencies]
//! unixbar = "0"
//! systemstat = "0"
//! ```

#[macro_use] extern crate unixbar;
extern crate systemstat;
use unixbar::*;
use systemstat::{System, Platform};

fn main() {
    UnixBar::new(LemonbarFormatter::new())

        .add(Text::new(bfmt![click[MouseButton::Left => "notify-send hi"]
                             click[MouseButton::Right => "notify-send 'what?'"]
                             fg["#11bb55"] text[" Hello World! "]]))

        .add(Bspwm::new(|desktops| Format::Concat(desktops.iter().map(|d| Box::new({
                let bg = if d.focused { "#99aa11" } else { "#111111" };
                bfmt![click[MouseButton::Left => format!("bspc desktop -f {}", d.name)]
                      bg[bg] fmt[" {} ", d.name]]
            })).collect())))

        .add(Text::new(bfmt![right]))

        .add(Periodic::new(
             Duration::from_secs(2),
             || match System::new().memory() {
                 Ok(mem) => bfmt![bg["#556677"] fmt[" {}/{} RAM ", mem.free.to_string(false).replace(" GB", ""), mem.total]],
                 Err(_) => bfmt![fg["#bb1155"] text["error"]],
             }))

        .add(Delayed::new(
             Duration::from_secs(1),
             || System::new().cpu_load_aggregate().unwrap(),
             |res| match res {
                 Ok(cpu) => bfmt![fg["#99aaff"] fmt[" {:04.1}% CPU ", (1.0 - cpu.idle) * 100.0]],
                 Err(_) => bfmt![fg["#bb1155"] text["error"]],
             }))

        .add(Wrap::new(
             |f| bfmt![fg["#bb1155"] f],
             DateTime::new(" %Y-%m-%d %H:%M:%S %z ")))

        .run();
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate typemap;
extern crate time;

use std::io::net::ip::Ipv4Addr;

use iron::{Request, Response, BeforeMiddleware, AfterMiddleware,
           IronResult, Iron, ChainBuilder, Chain, Set};
use iron::response::modifiers::{Status, Body};
use typemap::Assoc;
use time::precise_time_ns;

struct ResponseTime;

impl Assoc<u64> for ResponseTime {}

impl BeforeMiddleware for ResponseTime {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<ResponseTime, u64>(precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for ResponseTime {
    fn after(&self, req: &mut Request, _: &mut Response) -> IronResult<()> {
        let delta = precise_time_ns() - *req.extensions.find::<ResponseTime, u64>().unwrap();
        println!("Request took: {} ms", (delta as f64) / 1000000.0);
        Ok(())
    }
}

fn hello_world(_: &mut Request) -> IronResult<Response> {
    Ok(Response::new()
           .set(Status(iron::status::Ok))
           .set(Body("Hello World")))
}

fn main() {
    let mut chain = ChainBuilder::new(hello_world);
    chain.link_before(ResponseTime);
    chain.link_after(ResponseTime);
    Iron::new(chain).listen(Ipv4Addr(127, 0, 0, 1), 3000);
}
<commit_msg>(fix) Fix for typemap changes.<commit_after>extern crate iron;
extern crate typemap;
extern crate time;

use std::io::net::ip::Ipv4Addr;

use iron::{Request, Response, BeforeMiddleware, AfterMiddleware,
           IronResult, Iron, ChainBuilder, Chain, Set};
use iron::response::modifiers::{Status, Body};
use typemap::Assoc;
use time::precise_time_ns;

struct ResponseTime;

impl Assoc<u64> for ResponseTime {}

impl BeforeMiddleware for ResponseTime {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        req.extensions.insert::<ResponseTime, u64>(precise_time_ns());
        Ok(())
    }
}

impl AfterMiddleware for ResponseTime {
    fn after(&self, req: &mut Request, _: &mut Response) -> IronResult<()> {
        let delta = precise_time_ns() - *req.extensions.get::<ResponseTime, u64>().unwrap();
        println!("Request took: {} ms", (delta as f64) / 1000000.0);
        Ok(())
    }
}

fn hello_world(_: &mut Request) -> IronResult<Response> {
    Ok(Response::new()
           .set(Status(iron::status::Ok))
           .set(Body("Hello World")))
}

fn main() {
    let mut chain = ChainBuilder::new(hello_world);
    chain.link_before(ResponseTime);
    chain.link_after(ResponseTime);
    Iron::new(chain).listen(Ipv4Addr(127, 0, 0, 1), 3000);
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Binary_digits
use std::vec::Vec;
use std::string::String;

#[cfg(not(test))]
fn main() {
    let bins=binaries(16u);
    for s in bins.iter() {
        println!("{}", s);
    }
}

fn binaries(n:uint) -> Vec<String> {
    range(0, n).map(|i| format!("{:t}", i)).collect()
}

#[test]
fn test_digits() {
    let bins=binaries(16u);
    assert_eq!(bins, vec![String::from_str("0")
                        ,String::from_str("1")
                        ,String::from_str("10")
                        ,String::from_str("11")
                        ,String::from_str("100")
                        ,String::from_str("101")
                        ,String::from_str("110")
                        ,String::from_str("111")
                        ,String::from_str("1000")
                        ,String::from_str("1001")
                        ,String::from_str("1010")
                        ,String::from_str("1011")
                        ,String::from_str("1100")
                        ,String::from_str("1101")
                        ,String::from_str("1110")
                        ,String::from_str("1111")]);
}
<commit_msg>binary digits: Example of using a trait + style<commit_after>// Implements http://rosettacode.org/wiki/Binary_digits
use std::iter::range_inclusive;

trait BinaryString {
    fn to_binary_string(&self) -> String;
}

impl BinaryString for uint {
    fn to_binary_string(&self) -> String {
        format!("{:t}", *self)
    }
}

#[cfg(not(test))]
fn main() {
    for s in range_inclusive(0, 16u) {
        println!("{}", s.to_binary_string());
    }
}

#[test]
fn test_digits() {
    let expected = ["0", "1", "10", "11",
                    "100", "101", "110", "111",
                    "1000", "1001", "1010", "1011",
                    "1100", "1101", "1110", "1111"];

    for (n, expected) in range_inclusive(0, 16u).zip(expected.iter()) {
        assert_eq!(n.to_binary_string().as_slice(), *expected);
    }
}
<|endoftext|>


<commit_before>//! Bit level parsers
//!

use crate::error::{ErrorKind, ParseError};
use crate::internal::{Err, IResult};
use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
use crate::traits::{InputIter, InputLength, Slice, ToUsize};

/// Generates a parser taking `count` bits
///
/// # Example
/// ```rust
/// # use nom::bits::complete::take;
/// # use nom::IResult;
/// # use nom::error::{Error, ErrorKind};
/// // Input is a tuple of (input: I, bit_offset: usize)
/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
///  take(count)(input)
/// }
///
/// // Consumes 0 bits, returns 0
/// assert_eq!(parser(([0x12].as_ref(), 0), 0), Ok((([0x12].as_ref(), 0), 0)));
///
/// // Consumes 4 bits, returns their values and increase offset to 4
/// assert_eq!(parser(([0x12].as_ref(), 0), 4), Ok((([0x12].as_ref(), 4), 0x01)));
///
/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
/// assert_eq!(parser(([0x12].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0x02)));
///
/// // Tries to consume 12 bits but only 8 are available
/// assert_eq!(parser(([0x12].as_ref(), 0), 12), Err(nom::Err::Error(Error{input: ([0x12].as_ref(), 0), code: ErrorKind::Eof })));
/// ```
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
  count: C,
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
where
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
  C: ToUsize,
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
{
  let count = count.to_usize();
  move |(input, bit_offset): (I, usize)| {
    if count == 0 {
      Ok(((input, bit_offset), 0u8.into()))
    } else {
      let cnt = (count + bit_offset).div(8);
      if input.input_len() * 8 < count + bit_offset {
        Err(Err::Error(E::from_error_kind(
          (input, bit_offset),
          ErrorKind::Eof,
        )))
      } else {
        let mut acc: O = (0 as u8).into();
        let mut offset: usize = bit_offset;
        let mut remaining: usize = count;
        let mut end_offset: usize = 0;

        for byte in input.iter_elements().take(cnt + 1) {
          if remaining == 0 {
            break;
          }
          let val: O = if offset == 0 {
            byte.into()
          } else {
            ((byte << offset) as u8 >> offset).into()
          };

          if remaining < 8 - offset {
            acc += val >> (8 - offset - remaining);
            end_offset = remaining + offset;
            break;
          } else {
            acc += val << (remaining - (8 - offset));
            remaining -= 8 - offset;
            offset = 0;
          }
        }
        Ok(((input.slice(cnt..), end_offset), acc))
      }
    }
  }
}

/// Generates a parser taking `count` bits and comparing them to `pattern`
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
  pattern: O,
  count: C,
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
where
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
  C: ToUsize,
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
{
  let count = count.to_usize();
  move |input: (I, usize)| {
    let inp = input.clone();

    take(count)(input).and_then(|(i, o)| {
      if pattern == o {
        Ok((i, o))
      } else {
        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
      }
    })
  }
}

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

  #[test]
  fn test_take_0() {
    let input = [0x12].as_ref();
    let count = 0usize;
    assert_eq!(count, 0usize);
    let offset = 0usize;

    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));

    assert_eq!(result, Ok(((input, offset), 0)));
  }

  #[test]
  fn test_take_eof() {
    let input = [0x12].as_ref();

    let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));

    assert_eq!(
      result,
      Err(crate::Err::Error(crate::error::Error {
        input: (input, 8),
        code: ErrorKind::Eof
      }))
    )
  }

  #[test]
  fn test_take_span_over_multiple_bytes() {
    let input = [0x12, 0x34, 0xff, 0xff].as_ref();

    let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));

    assert_eq!(result, Ok((([0xff].as_ref(), 4), 0x234fff)));
  }
}
<commit_msg>bits::complete::take: Clarify usage, 0b over 0x<commit_after>//! Bit level parsers
//!

use crate::error::{ErrorKind, ParseError};
use crate::internal::{Err, IResult};
use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
use crate::traits::{InputIter, InputLength, Slice, ToUsize};

/// Generates a parser taking `count` bits
///
/// # Example
/// ```rust
/// # use nom::bits::complete::take;
/// # use nom::IResult;
/// # use nom::error::{Error, ErrorKind};
/// // Input is a tuple of (input: I, bit_offset: usize)
/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
///  take(count)(input)
/// }
///
/// // Consumes 0 bits, returns 0
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0)));
///
/// // Consumes 4 bits, returns their values and increase offset to 4
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001)));
///
/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010)));
///
/// // Tries to consume 12 bits but only 8 are available
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
/// ```
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
  count: C,
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
where
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
  C: ToUsize,
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
{
  let count = count.to_usize();
  move |(input, bit_offset): (I, usize)| {
    if count == 0 {
      Ok(((input, bit_offset), 0u8.into()))
    } else {
      let cnt = (count + bit_offset).div(8);
      if input.input_len() * 8 < count + bit_offset {
        Err(Err::Error(E::from_error_kind(
          (input, bit_offset),
          ErrorKind::Eof,
        )))
      } else {
        let mut acc: O = (0 as u8).into();
        let mut offset: usize = bit_offset;
        let mut remaining: usize = count;
        let mut end_offset: usize = 0;

        for byte in input.iter_elements().take(cnt + 1) {
          if remaining == 0 {
            break;
          }
          let val: O = if offset == 0 {
            byte.into()
          } else {
            ((byte << offset) as u8 >> offset).into()
          };

          if remaining < 8 - offset {
            acc += val >> (8 - offset - remaining);
            end_offset = remaining + offset;
            break;
          } else {
            acc += val << (remaining - (8 - offset));
            remaining -= 8 - offset;
            offset = 0;
          }
        }
        Ok(((input.slice(cnt..), end_offset), acc))
      }
    }
  }
}

/// Generates a parser taking `count` bits and comparing them to `pattern`
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
  pattern: O,
  count: C,
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
where
  I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
  C: ToUsize,
  O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
{
  let count = count.to_usize();
  move |input: (I, usize)| {
    let inp = input.clone();

    take(count)(input).and_then(|(i, o)| {
      if pattern == o {
        Ok((i, o))
      } else {
        Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
      }
    })
  }
}

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

  #[test]
  fn test_take_0() {
    let input = [0b00010010].as_ref();
    let count = 0usize;
    assert_eq!(count, 0usize);
    let offset = 0usize;

    let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));

    assert_eq!(result, Ok(((input, offset), 0)));
  }

  #[test]
  fn test_take_eof() {
    let input = [0b00010010].as_ref();

    let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));

    assert_eq!(
      result,
      Err(crate::Err::Error(crate::error::Error {
        input: (input, 8),
        code: ErrorKind::Eof
      }))
    )
  }

  #[test]
  fn test_take_span_over_multiple_bytes() {
    let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();

    let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));

    assert_eq!(result, Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111)));
  }
}
<|endoftext|>


<commit_before>use rlua::{self, Lua};
use wlroots::{self, key_events::KeyEvent,
              xkbcommon::xkb::{KEY_Escape, KEY_Super_L, KEY_Super_R}, CompositorHandle,
              KeyboardHandle, KeyboardHandler, WLR_KEY_PRESSED, KeyboardModifier};

use awesome::{self, emit_object_signal, Objectable, LUA, ROOT_KEYS_HANDLE};
use compositor::Server;

pub struct Keyboard;

fn key_is_meta(key: u32) -> bool {
    // TODO configure meta key
    key == KEY_Super_L || key == KEY_Super_R
}

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self,
              compositor: CompositorHandle,
              keyboard: KeyboardHandle,
              event: &KeyEvent) {
        let modifiers = with_handles!([(compositor: {compositor})] => {
            if event.key_state() == WLR_KEY_PRESSED {
                for key in event.pressed_keys() {
                    if key == KEY_Escape {
                        // NOTE No need to call awesome::lua::terminate.
                        // that will be handled by wlroots.
                        ::wlroots::terminate();
                    }
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = true;
                    }
                }
            } else {
                for key in event.pressed_keys() {
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = false;
                    }
                }
            }
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_key(event.time_msec(),
                                         event.keycode(),
                                         event.key_state() as u32);
                seat.keyboard_send_modifiers(&mut keyboard.get_modifier_masks());
                keyboard.get_modifiers()
            }).expect("Seat was destroyed")
        }).unwrap();
        LUA.with(|lua| {
                     let lua = lua.borrow();
                     if let Err(err) = emit_awesome_keybindings(&*lua, event, modifiers) {
                         warn!("Could not emit binding for {}: {:?}", event.keycode(), err);
                     }
                 });
    }

    fn modifiers(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_modifiers(&mut keyboard.get_modifier_masks());
            }).unwrap();
        }).unwrap();
    }
}

/// Emits the Awesome keybindinsg.
fn emit_awesome_keybindings(lua: &Lua,
                            event: &KeyEvent,
                            event_modifiers: KeyboardModifier)
                            -> rlua::Result<()> {
    let state_string = if event.key_state() == WLR_KEY_PRESSED {
        "press"
    } else {
        "release"
    };
    // TODO Should also emit by current focused client so we can
    // do client based rules.
    let keybindings = lua.named_registry_value::<Vec<rlua::AnyUserData>>(ROOT_KEYS_HANDLE)?;
    for event_keysym in event.pressed_keys() {
        for binding in &keybindings {
            let obj: awesome::Object = binding.clone().into();
            let key = awesome::Key::cast(obj.clone()).unwrap();
            let keycode = key.keycode()?;
            let keysym = key.keysym()?;
            let modifiers = key.modifiers()?;
            let binding_match = (keysym != 0 && keysym == event_keysym
                                 || keycode != 0 && keycode == event.keycode())
                                && modifiers == 0
                                || modifiers == event_modifiers.bits();
            if binding_match {
                emit_object_signal(&*lua, obj, state_string.into(), event_keysym)?;
            }
        }
    }
    Ok(())
}
<commit_msg>Removed unnecessary import<commit_after>use rlua::{self, Lua};
use wlroots::{key_events::KeyEvent,
              xkbcommon::xkb::{KEY_Escape, KEY_Super_L, KEY_Super_R}, CompositorHandle,
              KeyboardHandle, KeyboardHandler, WLR_KEY_PRESSED, KeyboardModifier};

use awesome::{self, emit_object_signal, Objectable, LUA, ROOT_KEYS_HANDLE};
use compositor::Server;

pub struct Keyboard;

fn key_is_meta(key: u32) -> bool {
    // TODO configure meta key
    key == KEY_Super_L || key == KEY_Super_R
}

impl KeyboardHandler for Keyboard {
    fn on_key(&mut self,
              compositor: CompositorHandle,
              keyboard: KeyboardHandle,
              event: &KeyEvent) {
        let modifiers = with_handles!([(compositor: {compositor})] => {
            if event.key_state() == WLR_KEY_PRESSED {
                for key in event.pressed_keys() {
                    if key == KEY_Escape {
                        // NOTE No need to call awesome::lua::terminate.
                        // that will be handled by wlroots.
                        ::wlroots::terminate();
                    }
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = true;
                    }
                }
            } else {
                for key in event.pressed_keys() {
                    if key_is_meta(key) {
                        let server: &mut Server = compositor.into();
                        server.seat.meta = false;
                    }
                }
            }
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_key(event.time_msec(),
                                         event.keycode(),
                                         event.key_state() as u32);
                seat.keyboard_send_modifiers(&mut keyboard.get_modifier_masks());
                keyboard.get_modifiers()
            }).expect("Seat was destroyed")
        }).unwrap();
        LUA.with(|lua| {
                     let lua = lua.borrow();
                     if let Err(err) = emit_awesome_keybindings(&*lua, event, modifiers) {
                         warn!("Could not emit binding for {}: {:?}", event.keycode(), err);
                     }
                 });
    }

    fn modifiers(&mut self, compositor: CompositorHandle, keyboard: KeyboardHandle) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            with_handles!([(seat: {&mut server.seat.seat}),
                           (keyboard: {keyboard})] => {
                seat.keyboard_notify_modifiers(&mut keyboard.get_modifier_masks());
            }).unwrap();
        }).unwrap();
    }
}

/// Emits the Awesome keybindinsg.
fn emit_awesome_keybindings(lua: &Lua,
                            event: &KeyEvent,
                            event_modifiers: KeyboardModifier)
                            -> rlua::Result<()> {
    let state_string = if event.key_state() == WLR_KEY_PRESSED {
        "press"
    } else {
        "release"
    };
    // TODO Should also emit by current focused client so we can
    // do client based rules.
    let keybindings = lua.named_registry_value::<Vec<rlua::AnyUserData>>(ROOT_KEYS_HANDLE)?;
    for event_keysym in event.pressed_keys() {
        for binding in &keybindings {
            let obj: awesome::Object = binding.clone().into();
            let key = awesome::Key::cast(obj.clone()).unwrap();
            let keycode = key.keycode()?;
            let keysym = key.keysym()?;
            let modifiers = key.modifiers()?;
            let binding_match = (keysym != 0 && keysym == event_keysym
                                 || keycode != 0 && keycode == event.keycode())
                                && modifiers == 0
                                || modifiers == event_modifiers.bits();
            if binding_match {
                emit_object_signal(&*lua, obj, state_string.into(), event_keysym)?;
            }
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! A Single-Producer, Multiple-Consumer queue.

use std::sync::mpsc::{channel, Receiver, RecvError, Sender, SendError};
use std::sync::{Arc, Mutex, MutexGuard};
use std::marker::PhantomData;
use std::fmt;
use std::any::Any;
use std::error::Error;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
/// Error from broadcast module.
pub enum BroadcastError<T> {
    /// Send error
    SendError(T),
    /// Receive error
    RecvError,
}

impl<T: fmt::Display> fmt::Display for BroadcastError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BroadcastError::SendError(ref t) =>
                write!(fmt, "could not send data on channel: {}", t),
            BroadcastError::RecvError =>
                write!(fmt, "could not receive data on channel"),
        }
    }
}

impl<T: Send + fmt::Display + fmt::Debug + Any> Error for BroadcastError<T> {
    fn description(&self) -> &str {
        match *self {
            BroadcastError::SendError(_) => "could not send data on channel",
            BroadcastError::RecvError => "could not receive data on channel",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<T> From<SendError<T>> for BroadcastError<T> {
    fn from(err: SendError<T>) -> BroadcastError<T> {
        let SendError(data) = err;
        BroadcastError::SendError(data)
    }
}

impl<T> From<RecvError> for BroadcastError<T> {
    fn from(_err: RecvError) -> BroadcastError<T> {
        BroadcastError::RecvError
    }
}

/// Struct that sends message on a broadcast pattern.
pub struct Broadcast<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Broadcast<T> {
    /// Create a new Broadcast struct.
    pub fn new() -> Broadcast<T> {
        let inner = Arc::new(Inner { senders: Mutex::new(Vec::new()) });
        Broadcast { inner: inner, not_sync: PhantomData }
    }

    /// Create a Consumer that listens to messages from the Broadcaster.
    pub fn consume(&self) -> Consumer<T> {
        let (b, c) = channel();
        self.inner.add_sender(b);
        Consumer { inner: self.inner.clone(), receiver: c }
    }
}

impl<T: Clone> Broadcast<T> {
    /// Send a message on the broadcast.
    pub fn send(&self, data: T) -> Result<(), BroadcastError<T>> {
        let guard = self.inner.read_senders();
        for s in guard.iter() {
            try!(s.send(data.clone()));
        }

        Ok(())
    }
}

struct Inner<T> {
    senders: Mutex<Vec<Sender<T>>>,
}

impl<T> Inner<T> {
    fn read_senders<'a>(&'a self) -> MutexGuard<'a, Vec<Sender<T>>> {
        self.senders.lock().unwrap()
    }

    fn add_sender(&self, sender: Sender<T>) {
        let mut vec = self.senders.lock().unwrap();
        vec.push(sender);
    }
}

/// Struct that receives messages from Broadcast.
pub struct Consumer<T> {
    inner: Arc<Inner<T>>,
    receiver: Receiver<T>,
}

impl<T> Consumer<T> {
    /// Receive a message from the Broadcast.
    ///
    /// This function will block.
    pub fn recv(&self) -> Result<T, BroadcastError<T>> {
        let data = try!(self.receiver.recv());
        Ok(data)
    }
}

impl<T> Clone for Consumer<T> {
    fn clone(&self) -> Self {
        let (s, r) = channel();
        self.inner.add_sender(s);
        Consumer {
            inner: self.inner.clone(),
            receiver: r,
        }
    }
}

/// Create a (Broadcast<T>, Consumer<T>) pair.
pub fn broadcast_channel<T: Clone>() -> (Broadcast<T>, Consumer<T>) {
    let broadcast = Broadcast::new();
    let consumer = broadcast.consume();
    (broadcast, consumer)
}

#[cfg(test)]
mod test {
    use broadcast::broadcast_channel;
    use super::Inner;

    use std::sync::{Arc, Mutex};
    use std::sync::mpsc::{channel};
    use std::thread::spawn;

    #[test]
    fn inner_iterator() {
        let (s1, r1) = channel();
        let (s2, r2) = channel();
        let inner = Arc::new(Inner { senders: Mutex::new(vec!(s1, s2)) });
        let guard = inner.read_senders();
        for s in guard.iter() {
            assert!(s.send(10u8).is_ok());
        }

        assert_eq!(r1.recv().unwrap(), 10u8);
        assert_eq!(r2.recv().unwrap(), 10u8);
    }

    #[test]
    fn sends_to_multiple_consumers() {
        let (p, c) = broadcast_channel();
        let c2 = c.clone();

        let res = p.send(9u8);
        assert!(res.is_ok());

        let res = c.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8);

        let res = c2.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8)
    }

    #[test]
    fn test_send_threads() {
        let (p, c1) = broadcast_channel();
        let c2 = c1.clone();

        let (s1, r1) = channel();
        let (s2, r2) = channel();

        let _thread = spawn(move || {
            assert_eq!(c1.recv().unwrap(), 9u8);
            s1.send(10u8).unwrap();
        });

        let _thread = spawn(move || {
            assert_eq!(c2.recv().unwrap(), 9u8);
            s2.send(10u8).unwrap();
        });

        assert!(p.send(9u8).is_ok());
        assert!(r1.recv().is_ok());
        assert!(r2.recv().is_ok());
    }
}
<commit_msg>Running tests is good<commit_after>//! A Single-Producer, Multiple-Consumer queue.

use std::sync::mpsc::{channel, Receiver, RecvError, Sender, SendError};
use std::sync::{Arc, Mutex, MutexGuard};
use std::fmt;
use std::any::Any;
use std::error::Error;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
/// Error from broadcast module.
pub enum BroadcastError<T> {
    /// Send error
    SendError(T),
    /// Receive error
    RecvError,
}

impl<T: fmt::Display> fmt::Display for BroadcastError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            BroadcastError::SendError(ref t) =>
                write!(fmt, "could not send data on channel: {}", t),
            BroadcastError::RecvError =>
                write!(fmt, "could not receive data on channel"),
        }
    }
}

impl<T: Send + fmt::Display + fmt::Debug + Any> Error for BroadcastError<T> {
    fn description(&self) -> &str {
        match *self {
            BroadcastError::SendError(_) => "could not send data on channel",
            BroadcastError::RecvError => "could not receive data on channel",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<T> From<SendError<T>> for BroadcastError<T> {
    fn from(err: SendError<T>) -> BroadcastError<T> {
        let SendError(data) = err;
        BroadcastError::SendError(data)
    }
}

impl<T> From<RecvError> for BroadcastError<T> {
    fn from(_err: RecvError) -> BroadcastError<T> {
        BroadcastError::RecvError
    }
}

/// Struct that sends message on a broadcast pattern.
pub struct Broadcast<T> {
    inner: Arc<Inner<T>>,
}

impl<T> Broadcast<T> {
    /// Create a new Broadcast struct.
    pub fn new() -> Broadcast<T> {
        let inner = Arc::new(Inner { senders: Mutex::new(Vec::new()) });
        Broadcast { inner: inner }
    }

    /// Create a Consumer that listens to messages from the Broadcaster.
    pub fn consume(&self) -> Consumer<T> {
        let (b, c) = channel();
        self.inner.add_sender(b);
        Consumer { inner: self.inner.clone(), receiver: c }
    }
}

impl<T: Clone> Broadcast<T> {
    /// Send a message on the broadcast.
    pub fn send(&self, data: T) -> Result<(), BroadcastError<T>> {
        let guard = self.inner.read_senders();
        for s in guard.iter() {
            try!(s.send(data.clone()));
        }

        Ok(())
    }
}

struct Inner<T> {
    senders: Mutex<Vec<Sender<T>>>,
}

impl<T> Inner<T> {
    fn read_senders<'a>(&'a self) -> MutexGuard<'a, Vec<Sender<T>>> {
        self.senders.lock().unwrap()
    }

    fn add_sender(&self, sender: Sender<T>) {
        let mut vec = self.senders.lock().unwrap();
        vec.push(sender);
    }
}

/// Struct that receives messages from Broadcast.
pub struct Consumer<T> {
    inner: Arc<Inner<T>>,
    receiver: Receiver<T>,
}

impl<T> Consumer<T> {
    /// Receive a message from the Broadcast.
    ///
    /// This function will block.
    pub fn recv(&self) -> Result<T, BroadcastError<T>> {
        let data = try!(self.receiver.recv());
        Ok(data)
    }
}

impl<T> Clone for Consumer<T> {
    fn clone(&self) -> Self {
        let (s, r) = channel();
        self.inner.add_sender(s);
        Consumer {
            inner: self.inner.clone(),
            receiver: r,
        }
    }
}

/// Create a (Broadcast<T>, Consumer<T>) pair.
pub fn broadcast_channel<T: Clone>() -> (Broadcast<T>, Consumer<T>) {
    let broadcast = Broadcast::new();
    let consumer = broadcast.consume();
    (broadcast, consumer)
}

#[cfg(test)]
mod test {
    use broadcast::broadcast_channel;
    use super::Inner;

    use std::sync::{Arc, Mutex};
    use std::sync::mpsc::{channel};
    use std::thread::spawn;

    #[test]
    fn inner_iterator() {
        let (s1, r1) = channel();
        let (s2, r2) = channel();
        let inner = Arc::new(Inner { senders: Mutex::new(vec!(s1, s2)) });
        let guard = inner.read_senders();
        for s in guard.iter() {
            assert!(s.send(10u8).is_ok());
        }

        assert_eq!(r1.recv().unwrap(), 10u8);
        assert_eq!(r2.recv().unwrap(), 10u8);
    }

    #[test]
    fn sends_to_multiple_consumers() {
        let (p, c) = broadcast_channel();
        let c2 = c.clone();

        let res = p.send(9u8);
        assert!(res.is_ok());

        let res = c.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8);

        let res = c2.recv();
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), 9u8)
    }

    #[test]
    fn test_send_threads() {
        let (p, c1) = broadcast_channel();
        let c2 = c1.clone();

        let (s1, r1) = channel();
        let (s2, r2) = channel();

        let _thread = spawn(move || {
            assert_eq!(c1.recv().unwrap(), 9u8);
            s1.send(10u8).unwrap();
        });

        let _thread = spawn(move || {
            assert_eq!(c2.recv().unwrap(), 9u8);
            s2.send(10u8).unwrap();
        });

        assert!(p.send(9u8).is_ok());
        assert!(r1.recv().is_ok());
        assert!(r2.recv().is_ok());
    }
}
<|endoftext|>