<commit_before>use std::io;
use std::net::SocketAddr;
use std::marker::PhantomData;

use time::{Duration, Timespec};

use super::crypto::{PublicKey, SecretKey};
use super::events::{Events, MioChannel, EventLoop, Reactor,
                    Network, NetworkConfiguration,
                    Event, EventsConfiguration,
                    Channel, EventHandler};
use super::blockchain::Blockchain;
use super::messages::{Connect, RawMessage};

mod state;
mod basic;
mod consensus;
mod requests;

pub use self::state::{State, Round, Height, RequestData, ValidatorId};

#[derive(Clone, Debug)]
pub enum ExternalMessage<B: Blockchain> {
    Transaction(B::Transaction),
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum NodeTimeout {
    Status,
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    PeerExchange,
}

pub struct TxSender<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout>
{
    inner: S,
    _b: PhantomData<B>,
}

// TODO: avoid recursion calls?

pub struct NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout>
{
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub state: State<B::Transaction>,
    pub channel: S,
    pub blockchain: B,
    pub round_timeout: u32,
    pub status_timeout: u32,
    pub peers_timeout: u32,
    // TODO: move this into peer exchange service
    pub peer_discovery: Vec<SocketAddr>,
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub events: EventsConfiguration,
    pub network: NetworkConfiguration,
    pub round_timeout: u32,
    pub status_timeout: u32,
    pub peers_timeout: u32,
    pub peer_discovery: Vec<SocketAddr>,
    pub validators: Vec<PublicKey>,
}

impl<B, S> NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout> + Clone
{
    pub fn new(blockchain: B, sender: S, config: Configuration) -> NodeHandler<B, S> {
        // FIXME: remove unwraps here, use FATAL log level instead
        let id = config.validators
            .iter()
            .position(|pk| pk == &config.public_key)
            .unwrap();
        let connect = Connect::new(&config.public_key,
                                   sender.address(),
                                   sender.get_time(),
                                   &config.secret_key);

        let last_hash = blockchain.last_hash().unwrap().unwrap_or_else(|| super::crypto::hash(&[]));

        let state = State::new(id as u32, config.validators, connect, last_hash);
        NodeHandler {
            public_key: config.public_key,
            secret_key: config.secret_key,
            state: state,
            channel: sender,
            blockchain: blockchain,
            round_timeout: config.round_timeout,
            status_timeout: config.status_timeout,
            peers_timeout: config.peers_timeout,
            peer_discovery: config.peer_discovery,
        }
    }

    pub fn state(&self) -> &State<B::Transaction> {
        &self.state
    }

    pub fn initialize(&mut self) {
        info!("Start listening...");
        for address in &self.peer_discovery.clone() {
            if address == &self.channel.address() {
                continue;
            }
            self.connect(address);
            info!("Try to connect with peer {}", address);
        }

        // TODO: rewrite this bullshit
        let time = self.blockchain
            .last_block()
            .unwrap()
            .map_or_else(|| Timespec { sec: 0, nsec: 0 }, |p| p.time());
        let round = 1 +
                    (self.channel.get_time() - time).num_milliseconds() / self.round_timeout as i64;
        self.state.jump_round(round as u32);

        info!("Jump to round {}", round);

        self.add_round_timeout();
        self.add_status_timeout();
        self.add_peer_exchange_timeout();
    }

    pub fn send_to_validator(&mut self, id: u32, message: &RawMessage) {
        // TODO: check validator id
        let public_key = self.state.validators()[id as usize];
        self.send_to_peer(public_key, message);
    }

    pub fn send_to_peer(&mut self, public_key: PublicKey, message: &RawMessage) {
        if let Some(conn) = self.state.peers().get(&public_key) {
            self.channel.send_to(&conn.addr(), message.clone());
        } else {
            warn!("Hasn't connection with peer {:?}", public_key);
        }
    }

    pub fn send_to_addr(&mut self, address: &SocketAddr, message: &RawMessage) {
        self.channel.send_to(address, message.clone());
    }

    pub fn connect(&mut self, address: &SocketAddr) {
        self.channel.connect(address);
    }

    pub fn request(&mut self, data: RequestData, peer: PublicKey) {
        let is_new = self.state.request(data.clone(), peer);

        if is_new {
            debug!("ADD REQUEST TIMEOUT");
            self.add_request_timeout(data, None);
        }
    }

    pub fn add_round_timeout(&mut self) {
        let ms = self.state.round() as i64 * self.round_timeout as i64;
        let time = self.blockchain
            .last_block()
            .unwrap()
            .map_or_else(|| Timespec { sec: 0, nsec: 0 }, |p| p.time()) +
                   Duration::milliseconds(ms);
        debug!("ADD ROUND TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Round(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_status_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::milliseconds(self.status_timeout as i64);
        self.channel.add_timeout(NodeTimeout::Status, time);
    }

    pub fn add_request_timeout(&mut self, data: RequestData, peer: Option<PublicKey>) {
        let time = self.channel.get_time() + data.timeout();
        self.channel.add_timeout(NodeTimeout::Request(data, peer), time);
    }

    pub fn add_peer_exchange_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::milliseconds(self.peers_timeout as i64);
        self.channel.add_timeout(NodeTimeout::PeerExchange, time);
    }

    // TODO: use Into<RawMessage>
    pub fn broadcast(&mut self, message: &RawMessage) {
        for conn in self.state.peers().values() {
            self.channel.send_to(&conn.addr(), message.clone());
        }
    }
}

impl<B, S> EventHandler for NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout> + Clone
{
    type Timeout = NodeTimeout;
    type ApplicationEvent = ExternalMessage<B>;

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::Connected(addr) => self.handle_connected(&addr),
            Event::Disconnected(addr) => self.handle_disconnected(&addr),
            Event::Incoming(raw) => self.handle_message(raw),
            Event::Error(_) => {}
        }
    }

    fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
        match event {
            ExternalMessage::Transaction(tx) => {
                self.handle_incoming_tx(tx);
            }
        }
    }

    fn handle_timeout(&mut self, timeout: Self::Timeout) {
        match timeout {
            NodeTimeout::Round(height, round) => self.handle_round_timeout(height, round),
            NodeTimeout::Request(data, peer) => self.handle_request_timeout(data, peer),
            NodeTimeout::Status => self.handle_status_timeout(),
            NodeTimeout::PeerExchange => self.handle_peer_exchange_timeout(),
        }
    }
}

impl<B, S> TxSender<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout>
{
    pub fn new(inner: S) -> TxSender<B, S> {
        TxSender {
            inner: inner,
            _b: PhantomData,
        }
    }

    // TODO handle error
    pub fn send(&self, tx: B::Transaction) {
        if B::verify_tx(&tx) {
            let msg = ExternalMessage::Transaction(tx);
            self.inner.post_event(msg).unwrap();
        }
    }
}

type NodeChannel<B> = MioChannel<ExternalMessage<B>, NodeTimeout>;

pub struct Node<B>
    where B: Blockchain
{
    reactor: Events<NodeHandler<B, NodeChannel<B>>>
}

impl<B> Node<B>
    where B: Blockchain
{
    pub fn new(blockchain: B, config: Configuration) -> Node<B> {
        let network = Network::with_config(config.network.clone());
        let event_loop = EventLoop::configured(config.events.clone()).unwrap();
        let channel = MioChannel::new(config.network.listen_address, event_loop.channel());

        let worker = NodeHandler::new(blockchain, channel, config);

        Node {
            reactor: Events::with_event_loop(network, worker, event_loop)
        }
    }

    pub fn run(&mut self) -> io::Result<()> {
        self.reactor.handler_mut().initialize();
        self.reactor.run()
    }

    pub fn state(&self) -> &State<B::Transaction> {
        self.reactor.handler().state()
    }

    pub fn channel(&self) -> TxSender<B, NodeChannel<B>> {
        TxSender::new(self.reactor.handler().channel.clone())
    }
}<commit_msg>Bind node before run<commit_after>use std::io;
use std::net::SocketAddr;
use std::marker::PhantomData;

use time::{Duration, Timespec};

use super::crypto::{PublicKey, SecretKey};
use super::events::{Events, MioChannel, EventLoop, Reactor,
                    Network, NetworkConfiguration,
                    Event, EventsConfiguration,
                    Channel, EventHandler};
use super::blockchain::Blockchain;
use super::messages::{Connect, RawMessage};

mod state;
mod basic;
mod consensus;
mod requests;

pub use self::state::{State, Round, Height, RequestData, ValidatorId};

#[derive(Clone, Debug)]
pub enum ExternalMessage<B: Blockchain> {
    Transaction(B::Transaction),
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum NodeTimeout {
    Status,
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    PeerExchange,
}

pub struct TxSender<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout>
{
    inner: S,
    _b: PhantomData<B>,
}

// TODO: avoid recursion calls?

pub struct NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout>
{
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub state: State<B::Transaction>,
    pub channel: S,
    pub blockchain: B,
    pub round_timeout: u32,
    pub status_timeout: u32,
    pub peers_timeout: u32,
    // TODO: move this into peer exchange service
    pub peer_discovery: Vec<SocketAddr>,
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub events: EventsConfiguration,
    pub network: NetworkConfiguration,
    pub round_timeout: u32,
    pub status_timeout: u32,
    pub peers_timeout: u32,
    pub peer_discovery: Vec<SocketAddr>,
    pub validators: Vec<PublicKey>,
}

impl<B, S> NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout> + Clone
{
    pub fn new(blockchain: B, sender: S, config: Configuration) -> NodeHandler<B, S> {
        // FIXME: remove unwraps here, use FATAL log level instead
        let id = config.validators
            .iter()
            .position(|pk| pk == &config.public_key)
            .unwrap();
        let connect = Connect::new(&config.public_key,
                                   sender.address(),
                                   sender.get_time(),
                                   &config.secret_key);

        let last_hash = blockchain.last_hash().unwrap().unwrap_or_else(|| super::crypto::hash(&[]));

        let state = State::new(id as u32, config.validators, connect, last_hash);
        NodeHandler {
            public_key: config.public_key,
            secret_key: config.secret_key,
            state: state,
            channel: sender,
            blockchain: blockchain,
            round_timeout: config.round_timeout,
            status_timeout: config.status_timeout,
            peers_timeout: config.peers_timeout,
            peer_discovery: config.peer_discovery,
        }
    }

    pub fn state(&self) -> &State<B::Transaction> {
        &self.state
    }

    pub fn initialize(&mut self) {
        info!("Start listening...");
        for address in &self.peer_discovery.clone() {
            if address == &self.channel.address() {
                continue;
            }
            self.connect(address);
            info!("Try to connect with peer {}", address);
        }

        // TODO: rewrite this bullshit
        let time = self.blockchain
            .last_block()
            .unwrap()
            .map_or_else(|| Timespec { sec: 0, nsec: 0 }, |p| p.time());
        let round = 1 +
                    (self.channel.get_time() - time).num_milliseconds() / self.round_timeout as i64;
        self.state.jump_round(round as u32);

        info!("Jump to round {}", round);

        self.add_round_timeout();
        self.add_status_timeout();
        self.add_peer_exchange_timeout();
    }

    pub fn send_to_validator(&mut self, id: u32, message: &RawMessage) {
        // TODO: check validator id
        let public_key = self.state.validators()[id as usize];
        self.send_to_peer(public_key, message);
    }

    pub fn send_to_peer(&mut self, public_key: PublicKey, message: &RawMessage) {
        if let Some(conn) = self.state.peers().get(&public_key) {
            self.channel.send_to(&conn.addr(), message.clone());
        } else {
            warn!("Hasn't connection with peer {:?}", public_key);
        }
    }

    pub fn send_to_addr(&mut self, address: &SocketAddr, message: &RawMessage) {
        self.channel.send_to(address, message.clone());
    }

    pub fn connect(&mut self, address: &SocketAddr) {
        self.channel.connect(address);
    }

    pub fn request(&mut self, data: RequestData, peer: PublicKey) {
        let is_new = self.state.request(data.clone(), peer);

        if is_new {
            debug!("ADD REQUEST TIMEOUT");
            self.add_request_timeout(data, None);
        }
    }

    pub fn add_round_timeout(&mut self) {
        let ms = self.state.round() as i64 * self.round_timeout as i64;
        let time = self.blockchain
            .last_block()
            .unwrap()
            .map_or_else(|| Timespec { sec: 0, nsec: 0 }, |p| p.time()) +
                   Duration::milliseconds(ms);
        debug!("ADD ROUND TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Round(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_status_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::milliseconds(self.status_timeout as i64);
        self.channel.add_timeout(NodeTimeout::Status, time);
    }

    pub fn add_request_timeout(&mut self, data: RequestData, peer: Option<PublicKey>) {
        let time = self.channel.get_time() + data.timeout();
        self.channel.add_timeout(NodeTimeout::Request(data, peer), time);
    }

    pub fn add_peer_exchange_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::milliseconds(self.peers_timeout as i64);
        self.channel.add_timeout(NodeTimeout::PeerExchange, time);
    }

    // TODO: use Into<RawMessage>
    pub fn broadcast(&mut self, message: &RawMessage) {
        for conn in self.state.peers().values() {
            self.channel.send_to(&conn.addr(), message.clone());
        }
    }
}

impl<B, S> EventHandler for NodeHandler<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout> + Clone
{
    type Timeout = NodeTimeout;
    type ApplicationEvent = ExternalMessage<B>;

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::Connected(addr) => self.handle_connected(&addr),
            Event::Disconnected(addr) => self.handle_disconnected(&addr),
            Event::Incoming(raw) => self.handle_message(raw),
            Event::Error(_) => {}
        }
    }

    fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
        match event {
            ExternalMessage::Transaction(tx) => {
                self.handle_incoming_tx(tx);
            }
        }
    }

    fn handle_timeout(&mut self, timeout: Self::Timeout) {
        match timeout {
            NodeTimeout::Round(height, round) => self.handle_round_timeout(height, round),
            NodeTimeout::Request(data, peer) => self.handle_request_timeout(data, peer),
            NodeTimeout::Status => self.handle_status_timeout(),
            NodeTimeout::PeerExchange => self.handle_peer_exchange_timeout(),
        }
    }
}

impl<B, S> TxSender<B, S>
    where B: Blockchain,
          S: Channel<ApplicationEvent = ExternalMessage<B>, Timeout = NodeTimeout>
{
    pub fn new(inner: S) -> TxSender<B, S> {
        TxSender {
            inner: inner,
            _b: PhantomData,
        }
    }

    // TODO handle error
    pub fn send(&self, tx: B::Transaction) {
        if B::verify_tx(&tx) {
            let msg = ExternalMessage::Transaction(tx);
            self.inner.post_event(msg).unwrap();
        }
    }
}

pub type NodeChannel<B> = MioChannel<ExternalMessage<B>, NodeTimeout>;

pub struct Node<B>
    where B: Blockchain
{
    reactor: Events<NodeHandler<B, NodeChannel<B>>>
}

impl<B> Node<B>
    where B: Blockchain
{
    pub fn new(blockchain: B, config: Configuration) -> Node<B> {
        let network = Network::with_config(config.network.clone());
        let event_loop = EventLoop::configured(config.events.clone()).unwrap();
        let channel = MioChannel::new(config.network.listen_address, event_loop.channel());

        let worker = NodeHandler::new(blockchain, channel, config);

        Node {
            reactor: Events::with_event_loop(network, worker, event_loop)
        }
    }

    pub fn run(&mut self) -> io::Result<()> {
        self.reactor.bind()?;
        self.reactor.handler_mut().initialize();
        self.reactor.run()
    }

    pub fn state(&self) -> &State<B::Transaction> {
        self.reactor.handler().state()
    }

    pub fn channel(&self) -> TxSender<B, NodeChannel<B>> {
        TxSender::new(self.reactor.handler().channel.clone())
    }
}
<|endoftext|>


<commit_before>use std::ops::Add;

use blas::Nrm2;
use onezero::Zero;

use ops::norm;
use traits::Norm;
use {Mat, Transposed};

// NOTE Core
impl<T, U> Norm for Mat<T> where T: Nrm2<Output=U>, U: Add<Output=U> + Zero {
    type Output = U;

    fn norm(&self) -> U {
        norm::slice(self.as_slice())
    }
}

// NOTE Secondary
impl<T, U> Norm for Transposed<Mat<T>> where T: Nrm2<Output=U>, U: Add<Output=U> + Zero {
    type Output = U;

    fn norm(&self) -> U {
        self.0.norm()
    }
}
<commit_msg>feat: impl Norm for SubMat[Mut]<commit_after>use std::ops::Add;

use blas::Nrm2;
use onezero::Zero;

use ops::norm;
use traits::{Norm, Slice};
use {Mat, SubMat, SubMatMut, Transposed};

// NOTE Core
impl<T, U> Norm for Mat<T> where T: Nrm2<Output=U>, U: Add<Output=U> + Zero {
    type Output = U;

    fn norm(&self) -> U {
        norm::slice(self.as_slice())
    }
}

// NOTE Core
impl<'a, T, U> Norm for SubMat<'a, T> where T: Nrm2<Output=U>, U: Add<Output=U> + Zero {
    type Output = U;

    fn norm(&self) -> U {
        if let Some(slice) = self.as_slice() {
            norm::slice(slice)
        } else {
            unimplemented!();
        }
    }
}

// NOTE Secondary
impl<T, U> Norm for Transposed<Mat<T>> where T: Nrm2<Output=U>, U: Add<Output=U> + Zero {
    type Output = U;

    fn norm(&self) -> U {
        self.0.norm()
    }
}

// NOTE Forward
impl<'a, T, U> Norm for SubMatMut<'a, T> where T: Nrm2<Output=U>, U: Add<Output=U> + Zero {
    type Output = U;

    fn norm(&self) -> U {
        self.slice(..).norm()
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ops;
use std::borrow::{Borrow, BorrowMut, ToOwned};

use super::{ParseErrorKind, ParseError};
use ::slice::Slice;
use ::parse_helpers;
use ::parse::IrcMsg as IrcMsgLegacy;

#[derive(Clone)]
pub struct IrcMsgBuf {
    inner: Vec<u8>,
}

pub struct IrcMsg {
    inner: Slice,
}

pub struct IrcMsgPrefix {
    inner: Slice,
}

impl ops::Deref for IrcMsgBuf {
    type Target = IrcMsg;

    fn deref<'a>(&'a self) -> &'a IrcMsg {
        self.as_irc_msg()
    }
}

impl Borrow<IrcMsg> for IrcMsgBuf {
    fn borrow(&self) -> &IrcMsg {
        self.as_irc_msg()
    }
}

impl AsRef<IrcMsg> for IrcMsgBuf {
    fn as_ref(&self) -> &IrcMsg {
        self.as_irc_msg()
    }
}

impl BorrowMut<IrcMsg> for IrcMsgBuf {
    fn borrow_mut(&mut self) -> &mut IrcMsg {
        self.as_irc_msg_mut()
    }
}

impl AsMut<IrcMsg> for IrcMsgBuf {
    fn as_mut(&mut self) -> &mut IrcMsg {
        self.as_irc_msg_mut()
    }
}

impl ToOwned for IrcMsg {
    type Owned = IrcMsgBuf;

    fn to_owned(&self) -> IrcMsgBuf {
        IrcMsgBuf { inner: self.inner.to_owned() }
    }
}

impl IrcMsgBuf {
    pub fn new(mut buf: Vec<u8>) -> Result<IrcMsgBuf, ParseError> {
        let msg_len = try!(IrcMsg::new(&buf)).as_bytes().len();
        buf.truncate(msg_len);
        Ok(IrcMsgBuf { inner: buf })
    }

    pub fn into_inner(self) -> Vec<u8> {
        self.inner
    }

    fn as_irc_msg(&self) -> &IrcMsg {
        unsafe { IrcMsg::from_u8_slice_unchecked(&self.inner) }
    }

    fn as_irc_msg_mut(&mut self) -> &mut IrcMsg {
        unsafe { IrcMsg::from_u8_slice_unchecked_mut(&mut self.inner) }
    }

    pub fn from_legacy(legacy: IrcMsgLegacy) -> IrcMsgBuf {
        IrcMsgBuf::new(legacy.into_bytes()).unwrap()
    }

    pub fn into_legacy(self) -> IrcMsgLegacy {
        IrcMsgLegacy::new(self.inner).unwrap()
    }
}

impl IrcMsg {
    pub fn new(buf: &[u8]) -> Result<&IrcMsg, ParseError>  {
        let buf = parse_helpers::first_line(buf);
        try!(IrcMsg::validate_buffer(&buf));

        Ok(unsafe {
            // Invariant is maintained by IrcMsg::validate_buffer
            IrcMsg::from_u8_slice_unchecked(buf)
        })
    }

    pub fn from_legacy(legacy: &IrcMsgLegacy) -> &IrcMsg {
        IrcMsg::new(legacy.as_bytes()).unwrap()
    }

    fn validate_buffer(buf: &[u8]) -> Result<(), ParseError> {
        let mut parser = IrcParser::new();

        for &byte in buf.iter()  {
            parser = match parser.push_byte(byte) {
                Ok(new_parser) => new_parser,
                Err(err) => return Err(err.replace_message(buf))
            };
        }

        if let Err(err) = parser.finish() {
            return Err(err.replace_message(buf));
        }

        Ok(())
    }

    /// The following function allows unchecked construction of a irc message
    /// from a u8 slice.  This is unsafe because it does not maintain
    /// the IrcMsg invariant.
    pub unsafe fn from_u8_slice_unchecked(s: &[u8]) -> &IrcMsg {
        mem::transmute(s)
    }

    /// The following function allows unchecked construction of a
    /// mutable irc message from a mutable u8 slice.  This is unsafe because it
    /// does not maintain the IrcMsg invariant.
    pub unsafe fn from_u8_slice_unchecked_mut(s: &mut [u8]) -> &mut IrcMsg {
        mem::transmute(s)
    }

    pub fn as_bytes(&self) -> &[u8] {
        &self.inner
    }

    /// Mutably borrow the underlying storage.  This is private because it
    /// does not maintain the IrcMsg invariant.
    fn as_u8_slice_mut(&mut self) -> &mut [u8] {
        unsafe { mem::transmute(self) }
    }

    pub fn get_prefix<'a>(&'a self) -> Option<&'a IrcMsgPrefix> {
        let buffer = &self.inner[..];
        let (prefix, _) = parse_helpers::split_prefix(buffer);

        if prefix.len() > 0 {
            assert!(prefix.len() > 1);
            Some(IrcMsgPrefix::from_u8_slice_unchecked(&prefix[1..]))
        } else {
            None
        }
    }

    pub fn get_command(&self) -> &str {
        let buffer = &self.inner[..];
        let (_, buffer) = parse_helpers::split_prefix(buffer);
        let (command, _) = parse_helpers::split_command(buffer);

        unsafe { ::std::str::from_utf8_unchecked(command) }
    }

    pub fn args(&self) -> ArgumentIter {
        let buffer = &self.inner[..];
        let (_, buffer) = parse_helpers::split_prefix(buffer);
        let (_, buffer) = parse_helpers::split_command(buffer);
        ArgumentIter { arg_body: buffer }
    }
}

impl IrcMsgPrefix {
    /// The following function allows unchecked construction of a ogg track
    /// from a u8 slice.  This is private because it does not maintain
    /// the IrcMsgPrefix invariant.
    fn from_u8_slice_unchecked(s: &[u8]) -> &IrcMsgPrefix {
        unsafe { mem::transmute(s) }
    }

    pub fn as_bytes(&self) -> &[u8] {
        &self.inner
    }
}

pub struct ArgumentIter<'a> {
    arg_body: &'a [u8],
}

impl<'a> Iterator for ArgumentIter<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<&'a [u8]> {
        if self.arg_body.len() == 0 {
            return None;
        }

        let (output, remainder) = parse_helpers::split_arg(self.arg_body);
        self.arg_body = remainder;
        Some(output)
    }
}

#[derive(Clone)]
struct IrcParser(IrcParserState);

#[derive(Copy, Clone)]
enum IrcParserState {
    Initial,
    Prefix,
    CommandStart,
    Command,
    ArgStart,
    Arg,
    ArgEnd,
    RestArg,
}

impl IrcParser {
    fn new() -> IrcParser {
        IrcParser(IrcParserState::Initial)
    }

    fn push_byte(&self, byte: u8) -> Result<IrcParser, ParseError> {
        use self::IrcParserState::*;
        use parse_helpers::is_valid_prefix_byte;

        match (self.0, byte) {
            (Initial, b' ') => Ok(IrcParser(Initial)),
            (Initial, b':') => Ok(IrcParser(Prefix)),
            (Initial, _byte) => Ok(IrcParser(Command)),

            (Prefix, b' ') => Ok(IrcParser(CommandStart)),
            (Prefix, byte) if is_valid_prefix_byte(byte) => Ok(IrcParser(Prefix)),
            (Prefix, _byte) => {
                Err(ParseError::unexpected_byte(byte, "prefix"))
            },

            (CommandStart, b' ') => Ok(IrcParser(CommandStart)),
            (CommandStart, _byte) => Ok(IrcParser(Command)),

            (Command, b' ') => Ok(IrcParser(ArgStart)),
            (Command, _byte) => Ok(IrcParser(Command)),

            (ArgStart, b' ') => Ok(IrcParser(ArgStart)),
            (ArgStart, _byte) => Ok(IrcParser(Arg)),

            (Arg, b' ') => Ok(IrcParser(ArgEnd)),
            (Arg, _byte) => Ok(IrcParser(Arg)),

            (ArgEnd, b' ') => Ok(IrcParser(ArgEnd)),
            (ArgEnd, b':') => Ok(IrcParser(RestArg)),
            (ArgEnd, _byte) => Ok(IrcParser(Arg)),

            (RestArg, _byte) => Ok(IrcParser(RestArg)),
        }
    }

    fn finish(&self) -> Result<(), ParseError> {
        use self::IrcParserState::*;

        let truncated = Err(ParseError::new(ParseErrorKind::Truncated, Vec::new()));
        match self.0 {
            Initial => truncated,
            Prefix => truncated,
            CommandStart => truncated,
            Command => truncated,
            ArgStart => truncated,
            Arg => Ok(()),
            ArgEnd => Ok(()),
            RestArg => Ok(())
        }
    }
}

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

    #[test]
    fn test_many_modes() {
        let buf: &[u8] = b":InfinityB!q@d0-0-0-0.abhsia.telus.net MODE # +vvvvvvvvvvvvvvvvvvvv a b c d e f g h i j k l m n o p q r s t";
        let _ = IrcMsg::new(buf).unwrap();
    }

    #[test]
    fn test_many_modes2() {
        let buf: &[u8] = b":InfinityB!q@d0-0-0-0.abhsia.telus.net MODE # +vvvvvvvvvvvvvvvvvvvv a b c d e f g h i j k l m n o p q r s t";
        let msg = IrcMsg::new(buf).unwrap();

        assert_eq!(msg.get_prefix().unwrap().as_bytes(), b"InfinityB!d0-0-0-0.abhsia.telus.net" as &[u8]);
        assert_eq!(msg.get_command(), "MODE");

        let mut arg_iter = msg.args();
        assert_eq!(arg_iter.next().unwrap(), b"#");
        assert_eq!(arg_iter.next().unwrap(), b"+vvvvvvvvvvvvvvvvvvvv");
        assert_eq!(arg_iter.next().unwrap(), b"a");
        assert_eq!(arg_iter.next().unwrap(), b"b");
        assert_eq!(arg_iter.next().unwrap(), b"c");
        assert_eq!(arg_iter.next().unwrap(), b"d");
        assert_eq!(arg_iter.next().unwrap(), b"e");
        assert_eq!(arg_iter.next().unwrap(), b"f");
        assert_eq!(arg_iter.next().unwrap(), b"g");
        assert_eq!(arg_iter.next().unwrap(), b"h");
        assert_eq!(arg_iter.next().unwrap(), b"i");
        assert_eq!(arg_iter.next().unwrap(), b"j");
        assert_eq!(arg_iter.next().unwrap(), b"k");
        assert_eq!(arg_iter.next().unwrap(), b"l");
        assert_eq!(arg_iter.next().unwrap(), b"m");
        assert_eq!(arg_iter.next().unwrap(), b"n");
        assert_eq!(arg_iter.next().unwrap(), b"o");
        assert_eq!(arg_iter.next().unwrap(), b"p");
        assert_eq!(arg_iter.next().unwrap(), b"q");
        assert_eq!(arg_iter.next().unwrap(), b"r");
        assert_eq!(arg_iter.next().unwrap(), b"s");
        assert_eq!(arg_iter.next().unwrap(), b"t");
        assert!(arg_iter.next().is_none());
    }
}
<commit_msg>parse2: Fix broken test<commit_after>use std::mem;
use std::ops;
use std::borrow::{Borrow, BorrowMut, ToOwned};

use super::{ParseErrorKind, ParseError};
use ::slice::Slice;
use ::parse_helpers;
use ::parse::IrcMsg as IrcMsgLegacy;

#[derive(Clone)]
pub struct IrcMsgBuf {
    inner: Vec<u8>,
}

pub struct IrcMsg {
    inner: Slice,
}

pub struct IrcMsgPrefix {
    inner: Slice,
}

impl ops::Deref for IrcMsgBuf {
    type Target = IrcMsg;

    fn deref<'a>(&'a self) -> &'a IrcMsg {
        self.as_irc_msg()
    }
}

impl Borrow<IrcMsg> for IrcMsgBuf {
    fn borrow(&self) -> &IrcMsg {
        self.as_irc_msg()
    }
}

impl AsRef<IrcMsg> for IrcMsgBuf {
    fn as_ref(&self) -> &IrcMsg {
        self.as_irc_msg()
    }
}

impl BorrowMut<IrcMsg> for IrcMsgBuf {
    fn borrow_mut(&mut self) -> &mut IrcMsg {
        self.as_irc_msg_mut()
    }
}

impl AsMut<IrcMsg> for IrcMsgBuf {
    fn as_mut(&mut self) -> &mut IrcMsg {
        self.as_irc_msg_mut()
    }
}

impl ToOwned for IrcMsg {
    type Owned = IrcMsgBuf;

    fn to_owned(&self) -> IrcMsgBuf {
        IrcMsgBuf { inner: self.inner.to_owned() }
    }
}

impl IrcMsgBuf {
    pub fn new(mut buf: Vec<u8>) -> Result<IrcMsgBuf, ParseError> {
        let msg_len = try!(IrcMsg::new(&buf)).as_bytes().len();
        buf.truncate(msg_len);
        Ok(IrcMsgBuf { inner: buf })
    }

    pub fn into_inner(self) -> Vec<u8> {
        self.inner
    }

    fn as_irc_msg(&self) -> &IrcMsg {
        unsafe { IrcMsg::from_u8_slice_unchecked(&self.inner) }
    }

    fn as_irc_msg_mut(&mut self) -> &mut IrcMsg {
        unsafe { IrcMsg::from_u8_slice_unchecked_mut(&mut self.inner) }
    }

    pub fn from_legacy(legacy: IrcMsgLegacy) -> IrcMsgBuf {
        IrcMsgBuf::new(legacy.into_bytes()).unwrap()
    }

    pub fn into_legacy(self) -> IrcMsgLegacy {
        IrcMsgLegacy::new(self.inner).unwrap()
    }
}

impl IrcMsg {
    pub fn new(buf: &[u8]) -> Result<&IrcMsg, ParseError>  {
        let buf = parse_helpers::first_line(buf);
        try!(IrcMsg::validate_buffer(&buf));

        Ok(unsafe {
            // Invariant is maintained by IrcMsg::validate_buffer
            IrcMsg::from_u8_slice_unchecked(buf)
        })
    }

    pub fn from_legacy(legacy: &IrcMsgLegacy) -> &IrcMsg {
        IrcMsg::new(legacy.as_bytes()).unwrap()
    }

    fn validate_buffer(buf: &[u8]) -> Result<(), ParseError> {
        let mut parser = IrcParser::new();

        for &byte in buf.iter()  {
            parser = match parser.push_byte(byte) {
                Ok(new_parser) => new_parser,
                Err(err) => return Err(err.replace_message(buf))
            };
        }

        if let Err(err) = parser.finish() {
            return Err(err.replace_message(buf));
        }

        Ok(())
    }

    /// The following function allows unchecked construction of a irc message
    /// from a u8 slice.  This is unsafe because it does not maintain
    /// the IrcMsg invariant.
    pub unsafe fn from_u8_slice_unchecked(s: &[u8]) -> &IrcMsg {
        mem::transmute(s)
    }

    /// The following function allows unchecked construction of a
    /// mutable irc message from a mutable u8 slice.  This is unsafe because it
    /// does not maintain the IrcMsg invariant.
    pub unsafe fn from_u8_slice_unchecked_mut(s: &mut [u8]) -> &mut IrcMsg {
        mem::transmute(s)
    }

    pub fn as_bytes(&self) -> &[u8] {
        &self.inner
    }

    /// Mutably borrow the underlying storage.  This is private because it
    /// does not maintain the IrcMsg invariant.
    fn as_u8_slice_mut(&mut self) -> &mut [u8] {
        unsafe { mem::transmute(self) }
    }

    pub fn get_prefix<'a>(&'a self) -> Option<&'a IrcMsgPrefix> {
        let buffer = &self.inner[..];
        let (prefix, _) = parse_helpers::split_prefix(buffer);

        if prefix.len() > 0 {
            assert!(prefix.len() > 1);
            Some(IrcMsgPrefix::from_u8_slice_unchecked(&prefix[1..]))
        } else {
            None
        }
    }

    pub fn get_command(&self) -> &str {
        let buffer = &self.inner[..];
        let (_, buffer) = parse_helpers::split_prefix(buffer);
        let (command, _) = parse_helpers::split_command(buffer);

        unsafe { ::std::str::from_utf8_unchecked(command) }
    }

    pub fn args(&self) -> ArgumentIter {
        let buffer = &self.inner[..];
        let (_, buffer) = parse_helpers::split_prefix(buffer);
        let (_, buffer) = parse_helpers::split_command(buffer);
        ArgumentIter { arg_body: buffer }
    }
}

impl IrcMsgPrefix {
    /// The following function allows unchecked construction of a ogg track
    /// from a u8 slice.  This is private because it does not maintain
    /// the IrcMsgPrefix invariant.
    fn from_u8_slice_unchecked(s: &[u8]) -> &IrcMsgPrefix {
        unsafe { mem::transmute(s) }
    }

    pub fn as_bytes(&self) -> &[u8] {
        &self.inner
    }
}

pub struct ArgumentIter<'a> {
    arg_body: &'a [u8],
}

impl<'a> Iterator for ArgumentIter<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<&'a [u8]> {
        if self.arg_body.len() == 0 {
            return None;
        }

        let (output, remainder) = parse_helpers::split_arg(self.arg_body);
        self.arg_body = remainder;
        Some(output)
    }
}

#[derive(Clone)]
struct IrcParser(IrcParserState);

#[derive(Copy, Clone)]
enum IrcParserState {
    Initial,
    Prefix,
    CommandStart,
    Command,
    ArgStart,
    Arg,
    ArgEnd,
    RestArg,
}

impl IrcParser {
    fn new() -> IrcParser {
        IrcParser(IrcParserState::Initial)
    }

    fn push_byte(&self, byte: u8) -> Result<IrcParser, ParseError> {
        use self::IrcParserState::*;
        use parse_helpers::is_valid_prefix_byte;

        match (self.0, byte) {
            (Initial, b' ') => Ok(IrcParser(Initial)),
            (Initial, b':') => Ok(IrcParser(Prefix)),
            (Initial, _byte) => Ok(IrcParser(Command)),

            (Prefix, b' ') => Ok(IrcParser(CommandStart)),
            (Prefix, byte) if is_valid_prefix_byte(byte) => Ok(IrcParser(Prefix)),
            (Prefix, _byte) => {
                Err(ParseError::unexpected_byte(byte, "prefix"))
            },

            (CommandStart, b' ') => Ok(IrcParser(CommandStart)),
            (CommandStart, _byte) => Ok(IrcParser(Command)),

            (Command, b' ') => Ok(IrcParser(ArgStart)),
            (Command, _byte) => Ok(IrcParser(Command)),

            (ArgStart, b' ') => Ok(IrcParser(ArgStart)),
            (ArgStart, _byte) => Ok(IrcParser(Arg)),

            (Arg, b' ') => Ok(IrcParser(ArgEnd)),
            (Arg, _byte) => Ok(IrcParser(Arg)),

            (ArgEnd, b' ') => Ok(IrcParser(ArgEnd)),
            (ArgEnd, b':') => Ok(IrcParser(RestArg)),
            (ArgEnd, _byte) => Ok(IrcParser(Arg)),

            (RestArg, _byte) => Ok(IrcParser(RestArg)),
        }
    }

    fn finish(&self) -> Result<(), ParseError> {
        use self::IrcParserState::*;

        let truncated = Err(ParseError::new(ParseErrorKind::Truncated, Vec::new()));
        match self.0 {
            Initial => truncated,
            Prefix => truncated,
            CommandStart => truncated,
            Command => truncated,
            ArgStart => truncated,
            Arg => Ok(()),
            ArgEnd => Ok(()),
            RestArg => Ok(())
        }
    }
}

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

    #[test]
    fn test_many_modes() {
        let buf: &[u8] = b":InfinityB!q@d0-0-0-0.abhsia.telus.net MODE # +vvvvvvvvvvvvvvvvvvvv a b c d e f g h i j k l m n o p q r s t";
        let _ = IrcMsg::new(buf).unwrap();
    }

    #[test]
    fn test_many_modes2() {
        let buf: &[u8] = b":InfinityB!q@d0-0-0-0.abhsia.telus.net MODE # +vvvvvvvvvvvvvvvvvvvv a b c d e f g h i j k l m n o p q r s t";
        let msg = IrcMsg::new(buf).unwrap();

        assert_eq!(msg.get_prefix().unwrap().as_bytes(), b"InfinityB!q@d0-0-0-0.abhsia.telus.net" as &[u8]);
        assert_eq!(msg.get_command(), "MODE");

        let mut arg_iter = msg.args();
        assert_eq!(arg_iter.next().unwrap(), b"#");
        assert_eq!(arg_iter.next().unwrap(), b"+vvvvvvvvvvvvvvvvvvvv");
        assert_eq!(arg_iter.next().unwrap(), b"a");
        assert_eq!(arg_iter.next().unwrap(), b"b");
        assert_eq!(arg_iter.next().unwrap(), b"c");
        assert_eq!(arg_iter.next().unwrap(), b"d");
        assert_eq!(arg_iter.next().unwrap(), b"e");
        assert_eq!(arg_iter.next().unwrap(), b"f");
        assert_eq!(arg_iter.next().unwrap(), b"g");
        assert_eq!(arg_iter.next().unwrap(), b"h");
        assert_eq!(arg_iter.next().unwrap(), b"i");
        assert_eq!(arg_iter.next().unwrap(), b"j");
        assert_eq!(arg_iter.next().unwrap(), b"k");
        assert_eq!(arg_iter.next().unwrap(), b"l");
        assert_eq!(arg_iter.next().unwrap(), b"m");
        assert_eq!(arg_iter.next().unwrap(), b"n");
        assert_eq!(arg_iter.next().unwrap(), b"o");
        assert_eq!(arg_iter.next().unwrap(), b"p");
        assert_eq!(arg_iter.next().unwrap(), b"q");
        assert_eq!(arg_iter.next().unwrap(), b"r");
        assert_eq!(arg_iter.next().unwrap(), b"s");
        assert_eq!(arg_iter.next().unwrap(), b"t");
        assert!(arg_iter.next().is_none());
    }
}
<|endoftext|>


<commit_before>use parsers::*;

#[derive(Show, Eq, PartialEq, Clone)]
enum Input {
  A,
  B,
  C,
  D,
}

//need more tests :/

#[test]
fn test_seq() {
  let input = [Input::A, Input::B, Input::C, Input::D];
  let parser = seq!(literal(Input::A), literal(Input::B), literal(Input::C));
  assert_eq!( parser.parse(input.as_slice()) , Ok(((Input::A, (Input::B, Input::C)), input.slice_from(3))));
}

#[test]
fn test_seq_map() {
  let input = [Input::A, Input::B];
  let parser = seq!(literal(Input::A), literal(Input::B) to |&: (a, b)| 5);
  let expected = Ok( (5, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_rep() {
  let input = [Input::A, Input::B, Input::A, Input::B, Input::A, Input::C];
  let parser = rep!(seq!(literal(Input::A), literal(Input::B)));
  let expected = Ok((
    vec![(Input::A, Input::B), (Input::A, Input::B)],
    input.slice_from(4)
  ));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_or() {
  let input = [Input::A, Input::B, Input::A, Input::C];
  let parser = rep!(or!(literal(Input::A), literal(Input::B)));
  let expected = Ok((
    vec![Input::A, Input::B, Input::A],
    input.slice_from(3)
  ));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_multi_or() {
  let input = [Input::A];
  let parser = or!(literal(Input::A), literal(Input::B), literal(Input::C));
  let expected = Ok( (Input::A, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_or_map() {
  let input = [Input::B];
  let parser = or!(literal(Input::A), literal(Input::B) to |&: x| 5);
  let expected = Ok( (5, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_map() {
  let input = [Input::A];
  let parser = map!(literal(Input::A), |&: a| 5);
  let expected = Ok( (5, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_recursive_or() {
  let input = [Input::A, Input::A, Input::C];
  fn a_seq<'a>() -> Box<Parser<'a, &'a [Input], usize> + 'a> {
    Box::new(or!(
      map!(literal(Input::C), |&: _| 2),
      map!(seq!(literal(Input::A), lazy!(a_seq())), |&: (a, seq)| 1 + seq)
    ))
  }
  let parser = a_seq();
  let expected = Ok( (4, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_repsep() {
  let input = [Input::A, Input::B, Input::C, Input::B, Input::A, Input::A];
  let parser = repsep!(or!(literal(Input::A), literal(Input::C)) , literal(Input::B));
  let expected = Ok((vec![Input::A, Input::C, Input::A], input.slice_from(5)));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_opt() {
  let input = [Input::A, Input::A, Input::B];
  let parser = rep!(seq!(literal(Input::A), opt!(literal(Input::B))));
  let expected = Ok((vec![(Input::A, None), (Input::A, Some(Input::B))], input.slice_from(3)));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_matcher() {
  let input = [Input::A, Input::B, Input::C];
  let parser = rep!(matcher!(Input : Input::A => 4, Input::B => 5));
  let expected = Ok( (vec![4, 5], input.slice_from(2)) );
  assert_eq!( parser.parse(input.as_slice()), expected );

}

<commit_msg>Allow unused imports in tests<commit_after>// these imports (of, eg, 'literal') are only used within macros. It appears
// Rust will incorrectly warn that they are unused, hence this attribute.
#[allow(unused_imports)]
use parsers::*;

#[derive(Show, Eq, PartialEq, Clone)]
enum Input {
  A,
  B,
  C,
  D,
}

//need more tests :/

#[test]
fn test_seq() {
  let input = [Input::A, Input::B, Input::C, Input::D];
  let parser = seq!(literal(Input::A), literal(Input::B), literal(Input::C));
  assert_eq!( parser.parse(input.as_slice()) , Ok(((Input::A, (Input::B, Input::C)), input.slice_from(3))));
}

#[test]
fn test_seq_map() {
  let input = [Input::A, Input::B];
  let parser = seq!(literal(Input::A), literal(Input::B) to |&: (a, b)| 5);
  let expected = Ok( (5, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_rep() {
  let input = [Input::A, Input::B, Input::A, Input::B, Input::A, Input::C];
  let parser = rep!(seq!(literal(Input::A), literal(Input::B)));
  let expected = Ok((
    vec![(Input::A, Input::B), (Input::A, Input::B)],
    input.slice_from(4)
  ));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_or() {
  let input = [Input::A, Input::B, Input::A, Input::C];
  let parser = rep!(or!(literal(Input::A), literal(Input::B)));
  let expected = Ok((
    vec![Input::A, Input::B, Input::A],
    input.slice_from(3)
  ));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_multi_or() {
  let input = [Input::A];
  let parser = or!(literal(Input::A), literal(Input::B), literal(Input::C));
  let expected = Ok( (Input::A, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_or_map() {
  let input = [Input::B];
  let parser = or!(literal(Input::A), literal(Input::B) to |&: x| 5);
  let expected = Ok( (5, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_map() {
  let input = [Input::A];
  let parser = map!(literal(Input::A), |&: a| 5);
  let expected = Ok( (5, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_recursive_or() {
  let input = [Input::A, Input::A, Input::C];
  fn a_seq<'a>() -> Box<Parser<'a, &'a [Input], usize> + 'a> {
    Box::new(or!(
      map!(literal(Input::C), |&: _| 2),
      map!(seq!(literal(Input::A), lazy!(a_seq())), |&: (a, seq)| 1 + seq)
    ))
  }
  let parser = a_seq();
  let expected = Ok( (4, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_repsep() {
  let input = [Input::A, Input::B, Input::C, Input::B, Input::A, Input::A];
  let parser = repsep!(or!(literal(Input::A), literal(Input::C)) , literal(Input::B));
  let expected = Ok((vec![Input::A, Input::C, Input::A], input.slice_from(5)));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_opt() {
  let input = [Input::A, Input::A, Input::B];
  let parser = rep!(seq!(literal(Input::A), opt!(literal(Input::B))));
  let expected = Ok((vec![(Input::A, None), (Input::A, Some(Input::B))], input.slice_from(3)));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_matcher() {
  let input = [Input::A, Input::B, Input::C];
  let parser = rep!(matcher!(Input : Input::A => 4, Input::B => 5));
  let expected = Ok( (vec![4, 5], input.slice_from(2)) );
  assert_eq!( parser.parse(input.as_slice()), expected );

}

<|endoftext|>


<commit_before>use linked_hash_map::LinkedHashMap;
use message::message::{Message, Key};

pub struct Pipeline {
    handlers: LinkedHashMap<String, Box<Handler>>,
}

impl Pipeline {
    fn process(&self, message: Message) {
        let mut context = PipelineContext::new(&self, message);

        for (key, handler) in self.handlers.iter() {
            context.set_handler_key(key);
            handler.handle_downstream(&mut context);
        }

        for (key, handler) in self.handlers.iter().rev() {
            context.set_handler_key(key);
            handler.handle_upstream(&mut context);
        }
    }
}

trait Handler {
    fn handle_downstream(&self, context: &mut PipelineContext);
    fn handle_upstream(&self, context: &mut PipelineContext);
}

struct PipelineBuilder {
    handlers: LinkedHashMap<String, Box<Handler>>,
}

impl PipelineBuilder{
    fn append_handler(&mut self, name: String, handler: Box<Handler>) {
        self.handlers.insert(name, handler);
    }

    fn build(self) -> Pipeline {
        Pipeline { handlers: self.handlers }
    }
}

impl Default for PipelineBuilder {
    fn default() -> Self {
        PipelineBuilder { handlers: Default::default() }
    }
}

pub struct PipelineContext<'c, 'm> {
    message: Message<'m>,
    handler_key: Option<&'c str>,
    pipeline: &'c Pipeline,
}

impl<'c, 'm> PipelineContext<'c, 'm> {

    fn message(&mut self) -> &mut Message<'m> {
        &mut self.message
    }

    fn set_message(&mut self, message: Message<'m>) {
        self.message = message;
    }

    fn handler_key(&self) -> &'c str {
        if let Some(handler_key) = self.handler_key {
            handler_key
        } else {
            panic!("Calls to handler_key are only allowed within a running Pipeline");
        }
    }

    fn set_handler_key(&mut self, handler_key: &'c str) {
        self.handler_key = Some(handler_key)
    }

    fn pipeline(&self) -> &Pipeline {
        self.pipeline
    }

    fn new(pipeline: &'c Pipeline, message: Message<'m>) -> PipelineContext<'c, 'm> {
        PipelineContext {
            message,
            handler_key: None,
            pipeline,
        }
    }
}

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

    struct HeartbeatHandler;

    impl Handler for HeartbeatHandler {
        fn handle_downstream(&self, context: &mut PipelineContext) {
            println!("Handler: {:?} (downstream)", context.handler_key());
            if context.message().headers().contains_key(&Key::from("first")) {
                context.pipeline().process(Message::new());
            }
        }

        fn handle_upstream(&self, context: &mut PipelineContext) {
            println!("Handler: {:?} (upstream)", context.handler_key());
        }
    }

    #[test]
    fn test_api() {
        let mut builder = PipelineBuilder::default();
        builder.append_handler("Heartbeat".to_owned(), Box::new(HeartbeatHandler));

        let pipeline = builder.build();

        let mut message = Message::new();
        message.headers_mut().insert("first", true);
        pipeline.process(message);
    }
}<commit_msg>Expand on Pipeline API test<commit_after>use linked_hash_map::LinkedHashMap;
use message::message::{Message, Key, Value};

pub struct Pipeline {
    handlers: LinkedHashMap<String, Box<Handler>>,
}

impl Pipeline {
    fn process(&self, message: Message) {
        let mut context = PipelineContext::new(&self, message);

        for (key, handler) in self.handlers.iter() {
            context.set_handler_key(key);
            handler.handle_downstream(&mut context);
        }

        for (key, handler) in self.handlers.iter().rev() {
            context.set_handler_key(key);
            handler.handle_upstream(&mut context);
        }
    }
}

trait Handler {
    fn handle_downstream(&self, context: &mut PipelineContext);
    fn handle_upstream(&self, context: &mut PipelineContext);
}

struct PipelineBuilder {
    handlers: LinkedHashMap<String, Box<Handler>>,
}

impl PipelineBuilder{
    fn append_handler(&mut self, name: String, handler: Box<Handler>) {
        self.handlers.insert(name, handler);
    }

    fn build(self) -> Pipeline {
        Pipeline { handlers: self.handlers }
    }
}

impl Default for PipelineBuilder {
    fn default() -> Self {
        PipelineBuilder { handlers: Default::default() }
    }
}

pub struct PipelineContext<'c, 'm> {
    message: Message<'m>,
    handler_key: Option<&'c str>,
    pipeline: &'c Pipeline,
}

impl<'c, 'm> PipelineContext<'c, 'm> {

    fn message(&mut self) -> &mut Message<'m> {
        &mut self.message
    }

    fn set_message(&mut self, message: Message<'m>) {
        self.message = message;
    }

    fn handler_key(&self) -> &'c str {
        if let Some(handler_key) = self.handler_key {
            handler_key
        } else {
            panic!("Calls to handler_key are only allowed within a running Pipeline");
        }
    }

    fn set_handler_key(&mut self, handler_key: &'c str) {
        self.handler_key = Some(handler_key)
    }

    fn pipeline(&self) -> &Pipeline {
        self.pipeline
    }

    fn new(pipeline: &'c Pipeline, message: Message<'m>) -> PipelineContext<'c, 'm> {
        PipelineContext {
            message,
            handler_key: None,
            pipeline,
        }
    }
}

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

    struct HeartbeatHandler;

    impl Handler for HeartbeatHandler {
        fn handle_downstream(&self, context: &mut PipelineContext) {
            println!("Handler: {:?} (downstream)", context.handler_key());
            if context.message().headers().contains_key(&Key::from("first")) {
                context.pipeline().process(Message::new());
            }
        }

        fn handle_upstream(&self, context: &mut PipelineContext) {
            println!("Handler: {:?} (upstream)", context.handler_key());
        }
    }

    struct DebugHandler;

    impl Handler for DebugHandler {
        fn handle_downstream(&self, context: &mut PipelineContext) {
            println!("Handler: {:?} (downstream), Message: {:?}", context.handler_key(), context.message());
        }

        fn handle_upstream(&self, context: &mut PipelineContext) {
        }
    }

    #[test]
    fn test_api() {
        let mut builder = PipelineBuilder::default();
        builder.append_handler("Heartbeat".to_owned(), Box::new(HeartbeatHandler));
        builder.append_handler("Debug".to_owned(), Box::new(DebugHandler));

        let pipeline = builder.build();

        for i in 0 .. 1000 {
            let mut message = Message::new();
            message.set_body(Some(Value::from(i)));
            message.headers_mut().insert("first", true);
            pipeline.process(message);
        }
    }
}<|endoftext|>


<commit_before>use self::super::{Github, SortDirection, State};
use rep::{Pull, PullEdit, PullReq};
use rustc_serialize::json;
use std::default::Default;
use std::fmt;
use std::io::Result;

pub enum Sort {
  Created,
  Updated,
  Popularity,
  LongRunning
}

impl fmt::Display for Sort {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Sort::Created     => "created",
      Sort::Updated     => "updated",
      Sort::Popularity  => "popularity",
      Sort::LongRunning => "long-running"
    })
  }
}

impl Default for Sort {
  fn default() -> Sort {
    Sort::Created
  }
}

pub struct PullRequest<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str,
  number: i64
}

impl<'a> PullRequest<'a> {
  pub fn new(github: &'a Github<'a>, owner: &'static str, repo: &'static str, number: i64) -> PullRequest<'a> {
    PullRequest { github: github, owner: owner, repo: repo, number: number }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/pulls/{}{}", self.owner, self.repo, self.number, more)
  }

  pub fn get(&self) -> Result<Pull> {
    let body = try!(
      self.github.get(
        &self.path("")
      )
    );
    Ok(json::decode::<Pull>(&body).unwrap())
  }

  /// short hand for editing state = open
  pub fn open(&self) -> Result<Pull> {
    self.edit(&PullEdit::new(None, None, Some("open")))
  }

  /// shorthand for editing state = closed
  pub fn close(&self) -> Result<Pull> {
    self.edit(&PullEdit::new(None, None, Some("closed")))
  }

  pub fn edit(&self, pr: &PullEdit) -> Result<Pull> {
    let data = json::encode(&pr).unwrap();
    let body = try!(
      self.github.patch(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Pull>(&body).unwrap())
  }
}

pub struct PullRequests<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str
}

impl<'a> PullRequests<'a> {
  pub fn new(github: &'a Github<'a>, owner: &'static str, repo: &'static str) -> PullRequests<'a> {
    PullRequests { github: github, owner: owner, repo: repo }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/pulls{}", self.owner, self.repo, more)
  }

  pub fn get(&self, number: i64) -> PullRequest {
    PullRequest::new(self.github, self.owner, self.repo, number)
  }

  pub fn create(&self, pr: &PullReq) -> Result<Pull> {
    let data = json::encode(&pr).unwrap();
    let body = try!(
      self.github.post(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Pull>(&body).unwrap())
  }

  pub fn list(
    &self, state: State, sort: Sort, direction: SortDirection) -> Result<Vec<Pull>> {
    let body = try!(
      self.github.get(
        &self.path(
          &format!(
            "?state={}&sort={}&direction={}", state, sort, direction
          )[..]
        )
      )
    );
    Ok(json::decode::<Vec<Pull>>(&body).unwrap())
  }
}
<commit_msg>list builder for pull reqs<commit_after>use self::super::{Github, SortDirection, State};
use rep::{Pull, PullEdit, PullReq};
use rustc_serialize::json;
use std::default::Default;
use std::fmt;
use std::io::Result;

pub enum Sort {
  Created,
  Updated,
  Popularity,
  LongRunning
}

impl fmt::Display for Sort {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", match *self {
      Sort::Created     => "created",
      Sort::Updated     => "updated",
      Sort::Popularity  => "popularity",
      Sort::LongRunning => "long-running"
    })
  }
}

impl Default for Sort {
  fn default() -> Sort {
    Sort::Created
  }
}

pub struct PullRequest<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str,
  number: i64
}

impl<'a> PullRequest<'a> {
  pub fn new(github: &'a Github<'a>, owner: &'static str, repo: &'static str, number: i64) -> PullRequest<'a> {
    PullRequest { github: github, owner: owner, repo: repo, number: number }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/pulls/{}{}", self.owner, self.repo, self.number, more)
  }

  pub fn get(&self) -> Result<Pull> {
    let body = try!(
      self.github.get(
        &self.path("")
      )
    );
    Ok(json::decode::<Pull>(&body).unwrap())
  }

  /// short hand for editing state = open
  pub fn open(&self) -> Result<Pull> {
    self.edit(&PullEdit::new(None, None, Some("open")))
  }

  /// shorthand for editing state = closed
  pub fn close(&self) -> Result<Pull> {
    self.edit(&PullEdit::new(None, None, Some("closed")))
  }

  pub fn edit(&self, pr: &PullEdit) -> Result<Pull> {
    let data = json::encode(&pr).unwrap();
    let body = try!(
      self.github.patch(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Pull>(&body).unwrap())
  }
}

pub struct PullRequests<'a> {
  github: &'a Github<'a>,
  owner: &'static str,
  repo: &'static str
}

pub struct ListBuilder<'a> {
  pulls: &'a PullRequests<'a>,
  state: State,
  sort: Sort,
  direction: SortDirection
}

impl<'a> ListBuilder<'a> {
  pub fn new(pulls: &'a PullRequests<'a>) -> ListBuilder<'a> {
    ListBuilder {
      pulls: pulls,
      state: Default::default(),
      sort: Default::default(),
      direction: Default::default()
    }
  }

  pub fn state(&mut self, state: State) -> &mut ListBuilder<'a> {
    self.state = state;
    self
  }

  pub fn sort(&mut self, sort: Sort) -> &mut ListBuilder<'a> {
    self.sort = sort;
    self
  }

  pub fn direction(&mut self, direction: SortDirection) -> &mut ListBuilder<'a> {
    self.direction = direction;
    self
  }

  pub fn get(&self) -> Result<Vec<Pull>> {
    let body = try!(
      self.pulls.github.get(
        &self.pulls.path(
          &format!(
            "?state={}&sort={}&direction={}", self.state, self.sort, self.direction
          )[..]
        )
      )
    );
    Ok(json::decode::<Vec<Pull>>(&body).unwrap())
  }
}

impl<'a> PullRequests<'a> {
  pub fn new(github: &'a Github<'a>, owner: &'static str, repo: &'static str) -> PullRequests<'a> {
    PullRequests { github: github, owner: owner, repo: repo }
  }

  fn path(&self, more: &str) -> String {
    format!("/repos/{}/{}/pulls{}", self.owner, self.repo, more)
  }

  pub fn get(&self, number: i64) -> PullRequest {
    PullRequest::new(self.github, self.owner, self.repo, number)
  }

  pub fn create(&self, pr: &PullReq) -> Result<Pull> {
    let data = json::encode(&pr).unwrap();
    let body = try!(
      self.github.post(
        &self.path(""),
        data.as_bytes()
      )
    );
    Ok(json::decode::<Pull>(&body).unwrap())
  }

  pub fn list(&self) -> ListBuilder {
    ListBuilder::new(self)
  }
}
<|endoftext|>


<commit_before>use crate::AHasher;
use core::hash::BuildHasher;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;

#[cfg(feature = "compile-time-rng")]
use const_random::const_random;

///This constant come from Kunth's prng
pub(crate) const MULTIPLE: u64 = 6364136223846793005;

// Const random provides randomized starting key with no runtime cost.
#[cfg(feature = "compile-time-rng")]
static SEED: AtomicUsize = AtomicUsize::new(const_random!(u64));

#[cfg(not(feature = "compile-time-rng"))]
static SEED: AtomicUsize = AtomicUsize::new(MULTIPLE as usize);

/// Provides a [Hasher] factory. This is typically used (e.g. by [`HashMap`]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
#[derive(Clone)]
pub struct RandomState {
    pub(crate) k0: u64,
    pub(crate) k1: u64,
}

impl RandomState {
    #[inline]
    pub fn new() -> RandomState {
        //Using a self pointer. When running with ASLR this is a random value.
        let previous = SEED.load(Ordering::Relaxed) as u64;
        let stack_mem_loc = &previous as *const _ as u64;
        //This is similar to the update function in the fallback.
        //only one multiply is needed because memory locations are not under an attackers control.
        let current_seed = previous
            .wrapping_mul(MULTIPLE)
            .wrapping_add(stack_mem_loc)
            .rotate_left(31);
        SEED.store(current_seed as usize, Ordering::Relaxed);
        let (k0, k1) = scramble_keys(&SEED as *const _ as u64, current_seed);
        RandomState { k0, k1 }
    }
}

pub(crate) fn scramble_keys(k0: u64, k1: u64) -> (u64, u64) {
    //Scramble seeds (based on xoroshiro128+)
    //This is intentionally not similar the hash algorithm
    let result1 = k0.wrapping_add(k1);
    let k1 = k1 ^ k0;
    let k0 = k0.rotate_left(24) ^ k1 ^ (k1.wrapping_shl(16));
    let result2 = k0.wrapping_add(k1.rotate_left(37));
    (result2, result1)
}

impl Default for RandomState {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl BuildHasher for RandomState {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on compile time generated constants** and the location
    /// this object was constructed at in memory. This means that two different [BuildHasher]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// ** - only if the `compile-time-rng` feature is enabled.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, RandomState};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = RandomState::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = RandomState::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        AHasher::new_with_keys(self.k0, self.k1)
    }
}
<commit_msg>Allow RandomState to be specified.<commit_after>use crate::AHasher;
use core::hash::BuildHasher;
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;

#[cfg(feature = "compile-time-rng")]
use const_random::const_random;

///This constant come from Kunth's prng
pub(crate) const MULTIPLE: u64 = 6364136223846793005;

// Const random provides randomized starting key with no runtime cost.
#[cfg(feature = "compile-time-rng")]
static SEED: AtomicUsize = AtomicUsize::new(const_random!(u64));

#[cfg(not(feature = "compile-time-rng"))]
static SEED: AtomicUsize = AtomicUsize::new(MULTIPLE as usize);

/// Provides a [Hasher] factory. This is typically used (e.g. by [`HashMap`]) to create
/// [AHasher]s in order to hash the keys of the map. See `build_hasher` below.
///
/// [build_hasher]: ahash::
/// [Hasher]: std::hash::Hasher
/// [BuildHasher]: std::hash::BuildHasher
/// [HashMap]: std::collections::HashMap
#[derive(Clone)]
pub struct RandomState {
    pub(crate) k0: u64,
    pub(crate) k1: u64,
}

impl RandomState {
    #[inline]
    pub fn new() -> RandomState {
        //Using a self pointer. When running with ASLR this is a random value.
        let previous = SEED.load(Ordering::Relaxed) as u64;
        let stack_mem_loc = &previous as *const _ as u64;
        //This is similar to the update function in the fallback.
        //only one multiply is needed because memory locations are not under an attackers control.
        let current_seed = previous
            .wrapping_mul(MULTIPLE)
            .wrapping_add(stack_mem_loc)
            .rotate_left(31);
        SEED.store(current_seed as usize, Ordering::Relaxed);
        let (k0, k1) = scramble_keys(&SEED as *const _ as u64, current_seed);
        RandomState { k0, k1 }
    }

    /// Allows for explicetly setting the seeds to used.
    pub fn with_seeds(k0: u64, k1: u64) -> RandomState {
        RandomState {
            k0,
            k1,
        }
    }

}

pub(crate) fn scramble_keys(k0: u64, k1: u64) -> (u64, u64) {
    //Scramble seeds (based on xoroshiro128+)
    //This is intentionally not similar the hash algorithm
    let result1 = k0.wrapping_add(k1);
    let k1 = k1 ^ k0;
    let k0 = k0.rotate_left(24) ^ k1 ^ (k1.wrapping_shl(16));
    let result2 = k0.wrapping_add(k1.rotate_left(37));
    (result2, result1)
}

impl Default for RandomState {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl BuildHasher for RandomState {
    type Hasher = AHasher;

    /// Constructs a new [AHasher] with keys based on compile time generated constants** and the location
    /// this object was constructed at in memory. This means that two different [BuildHasher]s will will generate
    /// [AHasher]s that will return different hashcodes, but [Hasher]s created from the same [BuildHasher]
    /// will generate the same hashes for the same input data.
    ///
    /// ** - only if the `compile-time-rng` feature is enabled.
    ///
    /// # Examples
    ///
    /// ```
    /// use ahash::{AHasher, RandomState};
    /// use std::hash::{Hasher, BuildHasher};
    ///
    /// let build_hasher = RandomState::new();
    /// let mut hasher_1 = build_hasher.build_hasher();
    /// let mut hasher_2 = build_hasher.build_hasher();
    ///
    /// hasher_1.write_u32(1234);
    /// hasher_2.write_u32(1234);
    ///
    /// assert_eq!(hasher_1.finish(), hasher_2.finish());
    ///
    /// let other_build_hasher = RandomState::new();
    /// let mut different_hasher = other_build_hasher.build_hasher();
    /// different_hasher.write_u32(1234);
    /// assert_ne!(different_hasher.finish(), hasher_1.finish());
    /// ```
    /// [Hasher]: std::hash::Hasher
    /// [BuildHasher]: std::hash::BuildHasher
    /// [HashMap]: std::collections::HashMap
    #[inline]
    fn build_hasher(&self) -> AHasher {
        AHasher::new_with_keys(self.k0, self.k1)
    }

}
<|endoftext|>


<commit_before>//! Colors used for drawing to a Cairo buffer

use std::convert::From;

/// Color to draw to the screen, including the alpha channel.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Color {
    red: u8,
    green: u8,
    blue: u8,
    alpha: u8
}

impl Color {
    /// Makes a new solid color, with no transparency.
    pub fn solid_color(red: u8, green: u8, blue: u8) -> Self {
        Color {
            red: red,
            green: green,
            blue: blue,
            alpha: 255
        }
    }

    /// Gets the values of the colors, in this order:
    /// (Red, Green, Blue, Alpha)
    pub fn values(&self) -> (u8, u8, u8, u8) {
        (self.red, self.green, self.blue, self.alpha)
    }
}

impl From<u32> for Color {
    fn from(mut val: u32) -> Self {
        // Ignore first two bits, we don't care about alpha
        val <<= 2;
        let values = unsafe { ::std::mem::transmute::<u32, [u8; 4]>(val) };
        Color::solid_color(values[2], values[1], values[0])
    }
}
<commit_msg>Fixed colors<commit_after>//! Colors used for drawing to a Cairo buffer

use std::convert::From;

/// Color to draw to the screen, including the alpha channel.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Color {
    red: u8,
    green: u8,
    blue: u8,
    alpha: u8
}

impl Color {
    /// Makes a new solid color, with no transparency.
    pub fn solid_color(red: u8, green: u8, blue: u8) -> Self {
        Color {
            red: red,
            green: green,
            blue: blue,
            alpha: 255
        }
    }

    /// Gets the values of the colors, in this order:
    /// (Red, Green, Blue, Alpha)
    pub fn values(&self) -> (u8, u8, u8, u8) {
        (self.red, self.green, self.blue, self.alpha)
    }
}

impl From<u32> for Color {
    fn from(val: u32) -> Self {
        let blue = ((val & 0xff0000) >> 16) as u8;
        let green = ((val & 0x00ff00) >> 8) as u8;
        let red = (val & 0x0000ff) as u8;
        Color::solid_color(red, green, blue)
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::fmt;
use std::io;
use std::io::Write;

use diff;

use crate::config::{Color, Config, Verbosity};

#[derive(Debug, PartialEq)]
pub enum DiffLine {
    Context(String),
    Expected(String),
    Resulting(String),
}

#[derive(Debug, PartialEq)]
pub struct Mismatch {
    /// The line number in the formatted version.
    pub line_number: u32,
    /// The line number in the original version.
    pub line_number_orig: u32,
    /// The set of lines (context and old/new) in the mismatch.
    pub lines: Vec<DiffLine>,
}

impl Mismatch {
    fn new(line_number: u32, line_number_orig: u32) -> Mismatch {
        Mismatch {
            line_number,
            line_number_orig,
            lines: Vec::new(),
        }
    }
}

/// A single span of changed lines, with 0 or more removed lines
/// and a vector of 0 or more inserted lines.
#[derive(Debug, PartialEq, Eq)]
pub struct ModifiedChunk {
    /// The first to be removed from the original text
    pub line_number_orig: u32,
    /// The number of lines which have been replaced
    pub lines_removed: u32,
    /// The new lines
    pub lines: Vec<String>,
}

/// Set of changed sections of a file.
#[derive(Debug, PartialEq, Eq)]
pub struct ModifiedLines {
    /// The set of changed chunks.
    pub chunks: Vec<ModifiedChunk>,
}

impl From<Vec<Mismatch>> for ModifiedLines {
    fn from(mismatches: Vec<Mismatch>) -> ModifiedLines {
        let chunks = mismatches.into_iter().map(|mismatch| {
            let lines = || mismatch.lines.iter();
            let num_removed = lines()
                .filter(|line| match line {
                    DiffLine::Resulting(_) => true,
                    _ => false,
                })
                .count();

            let new_lines = mismatch.lines.into_iter().filter_map(|line| match line {
                DiffLine::Context(_) | DiffLine::Resulting(_) => None,
                DiffLine::Expected(str) => Some(str),
            });

            ModifiedChunk {
                line_number_orig: mismatch.line_number_orig,
                lines_removed: num_removed as u32,
                lines: new_lines.collect(),
            }
        });

        ModifiedLines {
            chunks: chunks.collect(),
        }
    }
}

// Converts a `Mismatch` into a serialized form, which just includes
// enough information to modify the original file.
// Each section starts with a line with three integers, space separated:
//     lineno num_removed num_added
// followed by (`num_added`) lines of added text. The line numbers are
// relative to the original file.
impl fmt::Display for ModifiedLines {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for chunk in &self.chunks {
            writeln!(
                f,
                "{} {} {}",
                chunk.line_number_orig,
                chunk.lines_removed,
                chunk.lines.iter().count()
            )?;

            for line in &chunk.lines {
                writeln!(f, "{}", line)?;
            }
        }

        Ok(())
    }
}

// Allows to convert `Display`ed `ModifiedLines` back to the structural data.
impl std::str::FromStr for ModifiedLines {
    type Err = ();

    fn from_str(s: &str) -> Result<ModifiedLines, ()> {
        let mut chunks = vec![];

        let mut lines = s.lines();
        while let Some(header) = lines.next() {
            let mut header = header.split_whitespace();
            let (orig, rem, new_lines) = match (header.next(), header.next(), header.next()) {
                (Some(orig), Some(removed), Some(added)) => (orig, removed, added),
                _ => return Err(()),
            };
            let (orig, rem, new_lines): (u32, u32, usize) =
                match (orig.parse(), rem.parse(), new_lines.parse()) {
                    (Ok(a), Ok(b), Ok(c)) => (a, b, c),
                    _ => return Err(()),
                };
            let lines = lines.by_ref().take(new_lines);
            let lines: Vec<_> = lines.map(ToOwned::to_owned).collect();
            if lines.len() != new_lines {
                return Err(());
            }

            chunks.push(ModifiedChunk {
                line_number_orig: orig,
                lines_removed: rem,
                lines,
            });
        }

        Ok(ModifiedLines { chunks })
    }
}

// This struct handles writing output to stdout and abstracts away the logic
// of printing in color, if it's possible in the executing environment.
pub struct OutputWriter {
    terminal: Option<Box<dyn term::Terminal<Output = io::Stdout>>>,
}

impl OutputWriter {
    // Create a new OutputWriter instance based on the caller's preference
    // for colorized output and the capabilities of the terminal.
    pub fn new(color: Color) -> Self {
        if let Some(t) = term::stdout() {
            if color.use_colored_tty() && t.supports_color() {
                return OutputWriter { terminal: Some(t) };
            }
        }
        OutputWriter { terminal: None }
    }

    // Write output in the optionally specified color. The output is written
    // in the specified color if this OutputWriter instance contains a
    // Terminal in its `terminal` field.
    pub fn writeln(&mut self, msg: &str, color: Option<term::color::Color>) {
        match &mut self.terminal {
            Some(ref mut t) => {
                if let Some(color) = color {
                    t.fg(color).unwrap();
                }
                writeln!(t, "{}", msg).unwrap();
                if color.is_some() {
                    t.reset().unwrap();
                }
            }
            None => println!("{}", msg),
        }
    }
}

// Produces a diff between the expected output and actual output of rustfmt.
pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
    let mut line_number = 1;
    let mut line_number_orig = 1;
    let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
    let mut lines_since_mismatch = context_size + 1;
    let mut results = Vec::new();
    let mut mismatch = Mismatch::new(0, 0);

    for result in diff::lines(expected, actual) {
        match result {
            diff::Result::Left(str) => {
                if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
                    results.push(mismatch);
                    mismatch = Mismatch::new(
                        line_number - context_queue.len() as u32,
                        line_number_orig - context_queue.len() as u32,
                    );
                }

                while let Some(line) = context_queue.pop_front() {
                    mismatch.lines.push(DiffLine::Context(line.to_owned()));
                }

                mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
                line_number_orig += 1;
                lines_since_mismatch = 0;
            }
            diff::Result::Right(str) => {
                if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
                    results.push(mismatch);
                    mismatch = Mismatch::new(
                        line_number - context_queue.len() as u32,
                        line_number_orig - context_queue.len() as u32,
                    );
                }

                while let Some(line) = context_queue.pop_front() {
                    mismatch.lines.push(DiffLine::Context(line.to_owned()));
                }

                mismatch.lines.push(DiffLine::Expected(str.to_owned()));
                line_number += 1;
                lines_since_mismatch = 0;
            }
            diff::Result::Both(str, _) => {
                if context_queue.len() >= context_size {
                    let _ = context_queue.pop_front();
                }

                if lines_since_mismatch < context_size {
                    mismatch.lines.push(DiffLine::Context(str.to_owned()));
                } else if context_size > 0 {
                    context_queue.push_back(str);
                }

                line_number += 1;
                line_number_orig += 1;
                lines_since_mismatch += 1;
            }
        }
    }

    results.push(mismatch);
    results.remove(0);

    results
}

pub fn print_diff<F>(diff: Vec<Mismatch>, get_section_title: F, config: &Config)
where
    F: Fn(u32) -> String,
{
    let color = config.color();
    let line_terminator = if config.verbose() == Verbosity::Verbose {
        "⏎"
    } else {
        ""
    };

    let mut writer = OutputWriter::new(color);

    for mismatch in diff {
        let title = get_section_title(mismatch.line_number_orig);
        writer.writeln(&title, None);

        for line in mismatch.lines {
            match line {
                DiffLine::Context(ref str) => {
                    writer.writeln(&format!(" {}{}", str, line_terminator), None)
                }
                DiffLine::Expected(ref str) => writer.writeln(
                    &format!("+{}{}", str, line_terminator),
                    Some(term::color::GREEN),
                ),
                DiffLine::Resulting(ref str) => writer.writeln(
                    &format!("-{}{}", str, line_terminator),
                    Some(term::color::RED),
                ),
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::DiffLine::*;
    use super::{make_diff, Mismatch};
    use super::{ModifiedChunk, ModifiedLines};

    #[test]
    fn diff_simple() {
        let src = "one\ntwo\nthree\nfour\nfive\n";
        let dest = "one\ntwo\ntrois\nfour\nfive\n";
        let diff = make_diff(src, dest, 1);
        assert_eq!(
            diff,
            vec![Mismatch {
                line_number: 2,
                line_number_orig: 2,
                lines: vec![
                    Context("two".to_owned()),
                    Resulting("three".to_owned()),
                    Expected("trois".to_owned()),
                    Context("four".to_owned()),
                ],
            }]
        );
    }

    #[test]
    fn diff_simple2() {
        let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n";
        let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n";
        let diff = make_diff(src, dest, 1);
        assert_eq!(
            diff,
            vec![
                Mismatch {
                    line_number: 2,
                    line_number_orig: 2,
                    lines: vec![
                        Context("two".to_owned()),
                        Resulting("three".to_owned()),
                        Expected("trois".to_owned()),
                        Context("four".to_owned()),
                    ],
                },
                Mismatch {
                    line_number: 5,
                    line_number_orig: 5,
                    lines: vec![
                        Resulting("five".to_owned()),
                        Expected("cinq".to_owned()),
                        Context("six".to_owned()),
                    ],
                },
            ]
        );
    }

    #[test]
    fn diff_zerocontext() {
        let src = "one\ntwo\nthree\nfour\nfive\n";
        let dest = "one\ntwo\ntrois\nfour\nfive\n";
        let diff = make_diff(src, dest, 0);
        assert_eq!(
            diff,
            vec![Mismatch {
                line_number: 3,
                line_number_orig: 3,
                lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())],
            }]
        );
    }

    #[test]
    fn diff_trailing_newline() {
        let src = "one\ntwo\nthree\nfour\nfive";
        let dest = "one\ntwo\nthree\nfour\nfive\n";
        let diff = make_diff(src, dest, 1);
        assert_eq!(
            diff,
            vec![Mismatch {
                line_number: 5,
                line_number_orig: 5,
                lines: vec![Context("five".to_owned()), Expected("".to_owned())],
            }]
        );
    }

    #[test]
    fn modified_lines_from_str() {
        use std::str::FromStr;

        let src = "1 6 2\nfn some() {}\nfn main() {}\n25 3 1\n  struct Test {}";
        let lines = ModifiedLines::from_str(src).unwrap();
        assert_eq!(
            lines,
            ModifiedLines {
                chunks: vec![
                    ModifiedChunk {
                        line_number_orig: 1,
                        lines_removed: 6,
                        lines: vec!["fn some() {}".to_owned(), "fn main() {}".to_owned(),]
                    },
                    ModifiedChunk {
                        line_number_orig: 25,
                        lines_removed: 3,
                        lines: vec!["  struct Test {}".to_owned()]
                    }
                ]
            }
        );

        let src = "1 5 3";
        assert_eq!(ModifiedLines::from_str(src), Err(()));

        let src = "1 5 3\na\nb";
        assert_eq!(ModifiedLines::from_str(src), Err(()));
    }
}
<commit_msg>Remove redundant closure<commit_after>use std::collections::VecDeque;
use std::fmt;
use std::io;
use std::io::Write;

use diff;

use crate::config::{Color, Config, Verbosity};

#[derive(Debug, PartialEq)]
pub enum DiffLine {
    Context(String),
    Expected(String),
    Resulting(String),
}

#[derive(Debug, PartialEq)]
pub struct Mismatch {
    /// The line number in the formatted version.
    pub line_number: u32,
    /// The line number in the original version.
    pub line_number_orig: u32,
    /// The set of lines (context and old/new) in the mismatch.
    pub lines: Vec<DiffLine>,
}

impl Mismatch {
    fn new(line_number: u32, line_number_orig: u32) -> Mismatch {
        Mismatch {
            line_number,
            line_number_orig,
            lines: Vec::new(),
        }
    }
}

/// A single span of changed lines, with 0 or more removed lines
/// and a vector of 0 or more inserted lines.
#[derive(Debug, PartialEq, Eq)]
pub struct ModifiedChunk {
    /// The first to be removed from the original text
    pub line_number_orig: u32,
    /// The number of lines which have been replaced
    pub lines_removed: u32,
    /// The new lines
    pub lines: Vec<String>,
}

/// Set of changed sections of a file.
#[derive(Debug, PartialEq, Eq)]
pub struct ModifiedLines {
    /// The set of changed chunks.
    pub chunks: Vec<ModifiedChunk>,
}

impl From<Vec<Mismatch>> for ModifiedLines {
    fn from(mismatches: Vec<Mismatch>) -> ModifiedLines {
        let chunks = mismatches.into_iter().map(|mismatch| {
            let lines = mismatch.lines.iter();
            let num_removed = lines
                .filter(|line| match line {
                    DiffLine::Resulting(_) => true,
                    _ => false,
                })
                .count();

            let new_lines = mismatch.lines.into_iter().filter_map(|line| match line {
                DiffLine::Context(_) | DiffLine::Resulting(_) => None,
                DiffLine::Expected(str) => Some(str),
            });

            ModifiedChunk {
                line_number_orig: mismatch.line_number_orig,
                lines_removed: num_removed as u32,
                lines: new_lines.collect(),
            }
        });

        ModifiedLines {
            chunks: chunks.collect(),
        }
    }
}

// Converts a `Mismatch` into a serialized form, which just includes
// enough information to modify the original file.
// Each section starts with a line with three integers, space separated:
//     lineno num_removed num_added
// followed by (`num_added`) lines of added text. The line numbers are
// relative to the original file.
impl fmt::Display for ModifiedLines {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for chunk in &self.chunks {
            writeln!(
                f,
                "{} {} {}",
                chunk.line_number_orig,
                chunk.lines_removed,
                chunk.lines.iter().count()
            )?;

            for line in &chunk.lines {
                writeln!(f, "{}", line)?;
            }
        }

        Ok(())
    }
}

// Allows to convert `Display`ed `ModifiedLines` back to the structural data.
impl std::str::FromStr for ModifiedLines {
    type Err = ();

    fn from_str(s: &str) -> Result<ModifiedLines, ()> {
        let mut chunks = vec![];

        let mut lines = s.lines();
        while let Some(header) = lines.next() {
            let mut header = header.split_whitespace();
            let (orig, rem, new_lines) = match (header.next(), header.next(), header.next()) {
                (Some(orig), Some(removed), Some(added)) => (orig, removed, added),
                _ => return Err(()),
            };
            let (orig, rem, new_lines): (u32, u32, usize) =
                match (orig.parse(), rem.parse(), new_lines.parse()) {
                    (Ok(a), Ok(b), Ok(c)) => (a, b, c),
                    _ => return Err(()),
                };
            let lines = lines.by_ref().take(new_lines);
            let lines: Vec<_> = lines.map(ToOwned::to_owned).collect();
            if lines.len() != new_lines {
                return Err(());
            }

            chunks.push(ModifiedChunk {
                line_number_orig: orig,
                lines_removed: rem,
                lines,
            });
        }

        Ok(ModifiedLines { chunks })
    }
}

// This struct handles writing output to stdout and abstracts away the logic
// of printing in color, if it's possible in the executing environment.
pub struct OutputWriter {
    terminal: Option<Box<dyn term::Terminal<Output = io::Stdout>>>,
}

impl OutputWriter {
    // Create a new OutputWriter instance based on the caller's preference
    // for colorized output and the capabilities of the terminal.
    pub fn new(color: Color) -> Self {
        if let Some(t) = term::stdout() {
            if color.use_colored_tty() && t.supports_color() {
                return OutputWriter { terminal: Some(t) };
            }
        }
        OutputWriter { terminal: None }
    }

    // Write output in the optionally specified color. The output is written
    // in the specified color if this OutputWriter instance contains a
    // Terminal in its `terminal` field.
    pub fn writeln(&mut self, msg: &str, color: Option<term::color::Color>) {
        match &mut self.terminal {
            Some(ref mut t) => {
                if let Some(color) = color {
                    t.fg(color).unwrap();
                }
                writeln!(t, "{}", msg).unwrap();
                if color.is_some() {
                    t.reset().unwrap();
                }
            }
            None => println!("{}", msg),
        }
    }
}

// Produces a diff between the expected output and actual output of rustfmt.
pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
    let mut line_number = 1;
    let mut line_number_orig = 1;
    let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
    let mut lines_since_mismatch = context_size + 1;
    let mut results = Vec::new();
    let mut mismatch = Mismatch::new(0, 0);

    for result in diff::lines(expected, actual) {
        match result {
            diff::Result::Left(str) => {
                if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
                    results.push(mismatch);
                    mismatch = Mismatch::new(
                        line_number - context_queue.len() as u32,
                        line_number_orig - context_queue.len() as u32,
                    );
                }

                while let Some(line) = context_queue.pop_front() {
                    mismatch.lines.push(DiffLine::Context(line.to_owned()));
                }

                mismatch.lines.push(DiffLine::Resulting(str.to_owned()));
                line_number_orig += 1;
                lines_since_mismatch = 0;
            }
            diff::Result::Right(str) => {
                if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
                    results.push(mismatch);
                    mismatch = Mismatch::new(
                        line_number - context_queue.len() as u32,
                        line_number_orig - context_queue.len() as u32,
                    );
                }

                while let Some(line) = context_queue.pop_front() {
                    mismatch.lines.push(DiffLine::Context(line.to_owned()));
                }

                mismatch.lines.push(DiffLine::Expected(str.to_owned()));
                line_number += 1;
                lines_since_mismatch = 0;
            }
            diff::Result::Both(str, _) => {
                if context_queue.len() >= context_size {
                    let _ = context_queue.pop_front();
                }

                if lines_since_mismatch < context_size {
                    mismatch.lines.push(DiffLine::Context(str.to_owned()));
                } else if context_size > 0 {
                    context_queue.push_back(str);
                }

                line_number += 1;
                line_number_orig += 1;
                lines_since_mismatch += 1;
            }
        }
    }

    results.push(mismatch);
    results.remove(0);

    results
}

pub fn print_diff<F>(diff: Vec<Mismatch>, get_section_title: F, config: &Config)
where
    F: Fn(u32) -> String,
{
    let color = config.color();
    let line_terminator = if config.verbose() == Verbosity::Verbose {
        "⏎"
    } else {
        ""
    };

    let mut writer = OutputWriter::new(color);

    for mismatch in diff {
        let title = get_section_title(mismatch.line_number_orig);
        writer.writeln(&title, None);

        for line in mismatch.lines {
            match line {
                DiffLine::Context(ref str) => {
                    writer.writeln(&format!(" {}{}", str, line_terminator), None)
                }
                DiffLine::Expected(ref str) => writer.writeln(
                    &format!("+{}{}", str, line_terminator),
                    Some(term::color::GREEN),
                ),
                DiffLine::Resulting(ref str) => writer.writeln(
                    &format!("-{}{}", str, line_terminator),
                    Some(term::color::RED),
                ),
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::DiffLine::*;
    use super::{make_diff, Mismatch};
    use super::{ModifiedChunk, ModifiedLines};

    #[test]
    fn diff_simple() {
        let src = "one\ntwo\nthree\nfour\nfive\n";
        let dest = "one\ntwo\ntrois\nfour\nfive\n";
        let diff = make_diff(src, dest, 1);
        assert_eq!(
            diff,
            vec![Mismatch {
                line_number: 2,
                line_number_orig: 2,
                lines: vec![
                    Context("two".to_owned()),
                    Resulting("three".to_owned()),
                    Expected("trois".to_owned()),
                    Context("four".to_owned()),
                ],
            }]
        );
    }

    #[test]
    fn diff_simple2() {
        let src = "one\ntwo\nthree\nfour\nfive\nsix\nseven\n";
        let dest = "one\ntwo\ntrois\nfour\ncinq\nsix\nseven\n";
        let diff = make_diff(src, dest, 1);
        assert_eq!(
            diff,
            vec![
                Mismatch {
                    line_number: 2,
                    line_number_orig: 2,
                    lines: vec![
                        Context("two".to_owned()),
                        Resulting("three".to_owned()),
                        Expected("trois".to_owned()),
                        Context("four".to_owned()),
                    ],
                },
                Mismatch {
                    line_number: 5,
                    line_number_orig: 5,
                    lines: vec![
                        Resulting("five".to_owned()),
                        Expected("cinq".to_owned()),
                        Context("six".to_owned()),
                    ],
                },
            ]
        );
    }

    #[test]
    fn diff_zerocontext() {
        let src = "one\ntwo\nthree\nfour\nfive\n";
        let dest = "one\ntwo\ntrois\nfour\nfive\n";
        let diff = make_diff(src, dest, 0);
        assert_eq!(
            diff,
            vec![Mismatch {
                line_number: 3,
                line_number_orig: 3,
                lines: vec![Resulting("three".to_owned()), Expected("trois".to_owned())],
            }]
        );
    }

    #[test]
    fn diff_trailing_newline() {
        let src = "one\ntwo\nthree\nfour\nfive";
        let dest = "one\ntwo\nthree\nfour\nfive\n";
        let diff = make_diff(src, dest, 1);
        assert_eq!(
            diff,
            vec![Mismatch {
                line_number: 5,
                line_number_orig: 5,
                lines: vec![Context("five".to_owned()), Expected("".to_owned())],
            }]
        );
    }

    #[test]
    fn modified_lines_from_str() {
        use std::str::FromStr;

        let src = "1 6 2\nfn some() {}\nfn main() {}\n25 3 1\n  struct Test {}";
        let lines = ModifiedLines::from_str(src).unwrap();
        assert_eq!(
            lines,
            ModifiedLines {
                chunks: vec![
                    ModifiedChunk {
                        line_number_orig: 1,
                        lines_removed: 6,
                        lines: vec!["fn some() {}".to_owned(), "fn main() {}".to_owned(),]
                    },
                    ModifiedChunk {
                        line_number_orig: 25,
                        lines_removed: 3,
                        lines: vec!["  struct Test {}".to_owned()]
                    }
                ]
            }
        );

        let src = "1 5 3";
        assert_eq!(ModifiedLines::from_str(src), Err(()));

        let src = "1 5 3\na\nb";
        assert_eq!(ModifiedLines::from_str(src), Err(()));
    }
}
<|endoftext|>