<commit_before>use crate::*;
use bytes::Bytes;
use dashmap::DashMap;
use futures::channel::mpsc::{Receiver, Sender};
use futures::lock::Mutex;
use futures::stream::StreamExt;
use futures::{select, SinkExt};
use futures_util::future::FutureExt;
use std::convert::{TryFrom, TryInto};
use std::sync::Arc;
use tokio::net::TcpStream;
use uuid::Uuid;

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)]
pub(crate) struct PeerIdentity(Vec<u8>);

impl PeerIdentity {
    pub fn new() -> Self {
        let id = Uuid::new_v4();
        Self(id.as_bytes().to_vec())
    }
}

impl TryFrom<Vec<u8>> for PeerIdentity {
    type Error = ZmqError;

    fn try_from(data: Vec<u8>) -> Result<Self, ZmqError> {
        if data.len() == 0 {
            Ok(PeerIdentity::new())
        } else if data.len() > 255 {
            Err(ZmqError::Other(
                "ZMQ_IDENTITY should not be more than 255 bytes long",
            ))
        } else {
            Ok(Self(data))
        }
    }
}

impl From<PeerIdentity> for Vec<u8> {
    fn from(p_id: PeerIdentity) -> Self {
        p_id.0
    }
}

impl From<PeerIdentity> for Bytes {
    fn from(p_id: PeerIdentity) -> Self {
        Bytes::from(p_id.0)
    }
}

pub(crate) struct Peer {
    pub(crate) identity: PeerIdentity,
    pub(crate) send_queue: Sender<Message>,
    pub(crate) recv_queue: Arc<Mutex<Receiver<Message>>>,
    _io_close_handle: futures::channel::oneshot::Sender<bool>,
}

const COMPATIBILITY_MATRIX: [u8; 121] = [
    // PAIR, PUB, SUB, REQ, REP, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // PAIR
    0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, // PUB
    0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, // SUB
    0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, // REQ
    0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, // REP
    0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, // DEALER
    0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, // ROUTER
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, // PULL
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // PUSH
    0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, // XPUB
    0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, // XSUB
];

/// Checks if two sokets are compatible with each other
/// ```
/// use zeromq::SocketType;
/// use zeromq::util::sockets_compatible;
/// assert!(sockets_compatible(SocketType::PUB, SocketType::SUB));
/// assert!(sockets_compatible(SocketType::REQ, SocketType::REP));
/// assert!(sockets_compatible(SocketType::DEALER, SocketType::ROUTER));
/// assert!(!sockets_compatible(SocketType::PUB, SocketType::REP));
/// ```
pub fn sockets_compatible(one: SocketType, another: SocketType) -> bool {
    let row_index = one.to_usize().unwrap();
    let col_index = another.to_usize().unwrap();
    COMPATIBILITY_MATRIX[row_index * 11 + col_index] != 0
}

pub(crate) async fn greet_exchange(socket: &mut Framed<TcpStream, ZmqCodec>) -> ZmqResult<()> {
    socket
        .send(Message::Greeting(ZmqGreeting::default()))
        .await?;

    let greeting: Option<Result<Message, ZmqError>> = socket.next().await;

    match greeting {
        Some(Ok(Message::Greeting(greet))) => match greet.version {
            (3, 0) => Ok(()),
            _ => Err(ZmqError::Other("Unsupported protocol version")),
        },
        _ => Err(ZmqError::Codec("Failed Greeting exchange")),
    }
}

pub(crate) async fn greet_exchange_w_parts(
    sink: &mut tokio_util::codec::FramedWrite<
        tokio::io::WriteHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
    stream: &mut tokio_util::codec::FramedRead<
        tokio::io::ReadHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
) -> ZmqResult<()> {
    sink.send(Message::Greeting(ZmqGreeting::default())).await?;

    let greeting: Option<Result<Message, ZmqError>> = stream.next().await;

    match greeting {
        Some(Ok(Message::Greeting(greet))) => match greet.version {
            (3, 0) => Ok(()),
            _ => Err(ZmqError::Other("Unsupported protocol version")),
        },
        _ => Err(ZmqError::Codec("Failed Greeting exchange")),
    }
}

pub(crate) async fn ready_exchange(
    socket: &mut Framed<TcpStream, ZmqCodec>,
    socket_type: SocketType,
) -> ZmqResult<PeerIdentity> {
    let ready = ZmqCommand::ready(socket_type);
    socket.send(Message::Command(ready)).await?;

    let ready_repl: Option<ZmqResult<Message>> = socket.next().await;
    match ready_repl {
        Some(Ok(Message::Command(command))) => match command.name {
            ZmqCommandName::READY => {
                let other_sock_type = command
                    .properties
                    .get("Socket-Type")
                    .map(|x| SocketType::try_from(x.as_str()))
                    .unwrap_or(Err(ZmqError::Codec("Failed to parse other socket type")))?;

                let peer_id = command.properties.get("Identity").map_or_else(
                    || PeerIdentity::new(),
                    |x| PeerIdentity(x.clone().into_bytes()),
                );

                if sockets_compatible(socket_type, other_sock_type) {
                    Ok(peer_id)
                } else {
                    Err(ZmqError::Other(
                        "Provided sockets combination is not compatible",
                    ))
                }
            }
        },
        Some(Ok(_)) => Err(ZmqError::Codec("Failed to confirm ready state")),
        Some(Err(e)) => Err(e),
        None => Err(ZmqError::Other("No reply from server")),
    }
}

pub(crate) async fn ready_exchange_w_parts(
    sink: &mut tokio_util::codec::FramedWrite<
        tokio::io::WriteHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
    stream: &mut tokio_util::codec::FramedRead<
        tokio::io::ReadHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
    socket_type: SocketType,
) -> ZmqResult<PeerIdentity> {
    let ready = ZmqCommand::ready(socket_type);
    sink.send(Message::Command(ready)).await?;

    let ready_repl: Option<ZmqResult<Message>> = stream.next().await;
    match ready_repl {
        Some(Ok(Message::Command(command))) => match command.name {
            ZmqCommandName::READY => {
                let other_sock_type = command
                    .properties
                    .get("Socket-Type")
                    .map(|x| SocketType::try_from(x.as_str()))
                    .unwrap_or(Err(ZmqError::Codec("Failed to parse other socket type")))?;

                let peer_id = command.properties.get("Identity").map_or_else(
                    || PeerIdentity::new(),
                    |x| x.clone().into_bytes().try_into().unwrap(),
                );

                if sockets_compatible(socket_type, other_sock_type) {
                    Ok(peer_id)
                } else {
                    Err(ZmqError::Other(
                        "Provided sockets combination is not compatible",
                    ))
                }
            }
        },
        Some(Ok(_)) => Err(ZmqError::Codec("Failed to confirm ready state")),
        Some(Err(e)) => Err(e),
        None => Err(ZmqError::Other("No reply from server")),
    }
}

pub(crate) async fn raw_connect(
    socket_type: SocketType,
    endpoint: &str,
) -> ZmqResult<Framed<TcpStream, ZmqCodec>> {
    let addr = endpoint.parse::<SocketAddr>()?;
    let mut raw_socket = Framed::new(TcpStream::connect(addr).await?, ZmqCodec::new());
    greet_exchange(&mut raw_socket).await?;
    ready_exchange(&mut raw_socket, socket_type).await?;
    Ok(raw_socket)
}

pub(crate) async fn peer_connected(
    socket: tokio::net::TcpStream,
    peers: Arc<DashMap<PeerIdentity, Peer>>,
    socket_type: SocketType,
) {
    let (read, write) = tokio::io::split(socket);
    let mut read_part = tokio_util::codec::FramedRead::new(read, ZmqCodec::new());
    let mut write_part = tokio_util::codec::FramedWrite::new(write, ZmqCodec::new());

    greet_exchange_w_parts(&mut write_part, &mut read_part)
        .await
        .expect("Failed to exchange greetings");

    let peer_id = ready_exchange_w_parts(&mut write_part, &mut read_part, socket_type)
        .await
        .expect("Failed to exchange ready messages");
    println!("Peer connected {:?}", peer_id);

    let default_queue_size = 100;
    let (_send_queue, _send_queue_receiver) = futures::channel::mpsc::channel(default_queue_size);
    let (mut _recv_queue, _recv_queue_receiver) =
        futures::channel::mpsc::channel(default_queue_size);
    let (sender, receiver) = futures::channel::oneshot::channel::<bool>();

    let peer = Peer {
        identity: peer_id.clone(),
        send_queue: _send_queue,
        recv_queue: Arc::new(Mutex::new(_recv_queue_receiver)),
        _io_close_handle: sender,
    };

    peers.insert(peer_id.clone(), peer);

    let mut stop_handle = receiver.fuse();
    //let mut write_part = write_part.fuse();
    let mut incoming_queue = read_part.fuse();
    let mut outgoing_queue = _send_queue_receiver.fuse();
    loop {
        futures::select! {
            incoming = incoming_queue.next() => {
                match incoming {
                    Some(Ok(Message::MultipartMessage(message))) => {
                        _recv_queue.send(Message::MultipartMessage(message))
                            .await
                            .expect("Failed to send");
                        println!("Sent message");
                    }
                    None => {
                        println!("Client disconnected {:?}", &peer_id);
                        //peers.remove(&peer_id);
                        break;
                    }
                    _ => todo!(),
                }
            },
            outgoing = outgoing_queue.next() => {
                match outgoing {
                    Some(message) => {
                        let result = write_part.send(message).await;
                        dbg!(result);
                    },
                    None => {
                        println!("Outgoing queue closed. Stopping send coro");
                        break;
                    }
                }
            },
            _ = stop_handle => {
                println!("Stop callback received");
                break;
            }
        }
    }
}

/// Opens port described by endpoint and starts a coroutine to accept new connections on it
/// Returns stop_handle channel that can be used to stop accepting new connections
pub(crate) async fn start_accepting_connections(
    endpoint: &str,
    peers: Arc<DashMap<PeerIdentity, Peer>>,
    socket_type: SocketType,
) -> ZmqResult<futures::channel::oneshot::Sender<bool>> {
    let mut listener = tokio::net::TcpListener::bind(endpoint).await?;
    let (stop_handle, stop_callback) = futures::channel::oneshot::channel::<bool>();
    tokio::spawn(async move {
        let mut stop_callback = stop_callback.fuse();
        loop {
            select! {
                incoming = listener.accept().fuse() => {
                    let (socket, _) = incoming.expect("Failed to accept connection");
                    tokio::spawn(peer_connected(socket, peers.clone(), socket_type));
                },
                _ = stop_callback => {
                    println!("Stop signal received");
                    break
                }
            }
        }
    });
    Ok(stop_handle)
}
<commit_msg>Minor refactoring of io loop coroutine<commit_after>use crate::*;
use bytes::Bytes;
use dashmap::DashMap;
use futures::channel::mpsc::{Receiver, Sender};
use futures::lock::Mutex;
use futures::stream::StreamExt;
use futures::{select, SinkExt};
use futures_util::future::FutureExt;
use std::convert::{TryFrom, TryInto};
use std::sync::Arc;
use tokio::net::TcpStream;
use uuid::Uuid;

#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)]
pub(crate) struct PeerIdentity(Vec<u8>);

impl PeerIdentity {
    pub fn new() -> Self {
        let id = Uuid::new_v4();
        Self(id.as_bytes().to_vec())
    }
}

impl TryFrom<Vec<u8>> for PeerIdentity {
    type Error = ZmqError;

    fn try_from(data: Vec<u8>) -> Result<Self, ZmqError> {
        if data.len() == 0 {
            Ok(PeerIdentity::new())
        } else if data.len() > 255 {
            Err(ZmqError::Other(
                "ZMQ_IDENTITY should not be more than 255 bytes long",
            ))
        } else {
            Ok(Self(data))
        }
    }
}

impl From<PeerIdentity> for Vec<u8> {
    fn from(p_id: PeerIdentity) -> Self {
        p_id.0
    }
}

impl From<PeerIdentity> for Bytes {
    fn from(p_id: PeerIdentity) -> Self {
        Bytes::from(p_id.0)
    }
}

pub(crate) struct Peer {
    pub(crate) identity: PeerIdentity,
    pub(crate) send_queue: Sender<Message>,
    pub(crate) recv_queue: Arc<Mutex<Receiver<Message>>>,
    _io_close_handle: futures::channel::oneshot::Sender<bool>,
}

const COMPATIBILITY_MATRIX: [u8; 121] = [
    // PAIR, PUB, SUB, REQ, REP, DEALER, ROUTER, PULL, PUSH, XPUB, XSUB
    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // PAIR
    0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, // PUB
    0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, // SUB
    0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, // REQ
    0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, // REP
    0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, // DEALER
    0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, // ROUTER
    0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, // PULL
    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // PUSH
    0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, // XPUB
    0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, // XSUB
];

/// Checks if two sokets are compatible with each other
/// ```
/// use zeromq::SocketType;
/// use zeromq::util::sockets_compatible;
/// assert!(sockets_compatible(SocketType::PUB, SocketType::SUB));
/// assert!(sockets_compatible(SocketType::REQ, SocketType::REP));
/// assert!(sockets_compatible(SocketType::DEALER, SocketType::ROUTER));
/// assert!(!sockets_compatible(SocketType::PUB, SocketType::REP));
/// ```
pub fn sockets_compatible(one: SocketType, another: SocketType) -> bool {
    let row_index = one.to_usize().unwrap();
    let col_index = another.to_usize().unwrap();
    COMPATIBILITY_MATRIX[row_index * 11 + col_index] != 0
}

pub(crate) async fn greet_exchange(socket: &mut Framed<TcpStream, ZmqCodec>) -> ZmqResult<()> {
    socket
        .send(Message::Greeting(ZmqGreeting::default()))
        .await?;

    let greeting: Option<Result<Message, ZmqError>> = socket.next().await;

    match greeting {
        Some(Ok(Message::Greeting(greet))) => match greet.version {
            (3, 0) => Ok(()),
            _ => Err(ZmqError::Other("Unsupported protocol version")),
        },
        _ => Err(ZmqError::Codec("Failed Greeting exchange")),
    }
}

pub(crate) async fn greet_exchange_w_parts(
    sink: &mut tokio_util::codec::FramedWrite<
        tokio::io::WriteHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
    stream: &mut tokio_util::codec::FramedRead<
        tokio::io::ReadHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
) -> ZmqResult<()> {
    sink.send(Message::Greeting(ZmqGreeting::default())).await?;

    let greeting: Option<Result<Message, ZmqError>> = stream.next().await;

    match greeting {
        Some(Ok(Message::Greeting(greet))) => match greet.version {
            (3, 0) => Ok(()),
            _ => Err(ZmqError::Other("Unsupported protocol version")),
        },
        _ => Err(ZmqError::Codec("Failed Greeting exchange")),
    }
}

pub(crate) async fn ready_exchange(
    socket: &mut Framed<TcpStream, ZmqCodec>,
    socket_type: SocketType,
) -> ZmqResult<PeerIdentity> {
    let ready = ZmqCommand::ready(socket_type);
    socket.send(Message::Command(ready)).await?;

    let ready_repl: Option<ZmqResult<Message>> = socket.next().await;
    match ready_repl {
        Some(Ok(Message::Command(command))) => match command.name {
            ZmqCommandName::READY => {
                let other_sock_type = command
                    .properties
                    .get("Socket-Type")
                    .map(|x| SocketType::try_from(x.as_str()))
                    .unwrap_or(Err(ZmqError::Codec("Failed to parse other socket type")))?;

                let peer_id = command.properties.get("Identity").map_or_else(
                    || PeerIdentity::new(),
                    |x| PeerIdentity(x.clone().into_bytes()),
                );

                if sockets_compatible(socket_type, other_sock_type) {
                    Ok(peer_id)
                } else {
                    Err(ZmqError::Other(
                        "Provided sockets combination is not compatible",
                    ))
                }
            }
        },
        Some(Ok(_)) => Err(ZmqError::Codec("Failed to confirm ready state")),
        Some(Err(e)) => Err(e),
        None => Err(ZmqError::Other("No reply from server")),
    }
}

pub(crate) async fn ready_exchange_w_parts(
    sink: &mut tokio_util::codec::FramedWrite<
        tokio::io::WriteHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
    stream: &mut tokio_util::codec::FramedRead<
        tokio::io::ReadHalf<tokio::net::TcpStream>,
        ZmqCodec,
    >,
    socket_type: SocketType,
) -> ZmqResult<PeerIdentity> {
    let ready = ZmqCommand::ready(socket_type);
    sink.send(Message::Command(ready)).await?;

    let ready_repl: Option<ZmqResult<Message>> = stream.next().await;
    match ready_repl {
        Some(Ok(Message::Command(command))) => match command.name {
            ZmqCommandName::READY => {
                let other_sock_type = command
                    .properties
                    .get("Socket-Type")
                    .map(|x| SocketType::try_from(x.as_str()))
                    .unwrap_or(Err(ZmqError::Codec("Failed to parse other socket type")))?;

                let peer_id = command.properties.get("Identity").map_or_else(
                    || PeerIdentity::new(),
                    |x| x.clone().into_bytes().try_into().unwrap(),
                );

                if sockets_compatible(socket_type, other_sock_type) {
                    Ok(peer_id)
                } else {
                    Err(ZmqError::Other(
                        "Provided sockets combination is not compatible",
                    ))
                }
            }
        },
        Some(Ok(_)) => Err(ZmqError::Codec("Failed to confirm ready state")),
        Some(Err(e)) => Err(e),
        None => Err(ZmqError::Other("No reply from server")),
    }
}

pub(crate) async fn raw_connect(
    socket_type: SocketType,
    endpoint: &str,
) -> ZmqResult<Framed<TcpStream, ZmqCodec>> {
    let addr = endpoint.parse::<SocketAddr>()?;
    let mut raw_socket = Framed::new(TcpStream::connect(addr).await?, ZmqCodec::new());
    greet_exchange(&mut raw_socket).await?;
    ready_exchange(&mut raw_socket, socket_type).await?;
    Ok(raw_socket)
}

pub(crate) async fn peer_connected(
    socket: tokio::net::TcpStream,
    peers: Arc<DashMap<PeerIdentity, Peer>>,
    socket_type: SocketType,
) {
    let (read, write) = tokio::io::split(socket);
    let mut read_part = tokio_util::codec::FramedRead::new(read, ZmqCodec::new());
    let mut write_part = tokio_util::codec::FramedWrite::new(write, ZmqCodec::new());

    greet_exchange_w_parts(&mut write_part, &mut read_part)
        .await
        .expect("Failed to exchange greetings");

    let peer_id = ready_exchange_w_parts(&mut write_part, &mut read_part, socket_type)
        .await
        .expect("Failed to exchange ready messages");
    println!("Peer connected {:?}", peer_id);

    let default_queue_size = 100;
    let (_send_queue, _send_queue_receiver) = futures::channel::mpsc::channel(default_queue_size);
    let (mut _recv_queue, _recv_queue_receiver) =
        futures::channel::mpsc::channel(default_queue_size);
    let (sender, receiver) = futures::channel::oneshot::channel::<bool>();

    let peer = Peer {
        identity: peer_id.clone(),
        send_queue: _send_queue,
        recv_queue: Arc::new(Mutex::new(_recv_queue_receiver)),
        _io_close_handle: sender,
    };

    peers.insert(peer_id.clone(), peer);

    let mut stop_handle = receiver.fuse();
    let mut incoming_queue = read_part.fuse();
    let mut outgoing_queue = _send_queue_receiver.fuse();
    loop {
        futures::select! {
            incoming = incoming_queue.next() => {
                match incoming {
                    Some(Ok(message)) => {
                        _recv_queue.send(message)
                            .await
                            .expect("Failed to send");
                        println!("Sent message");
                    }
                    None => {
                        println!("Client disconnected {:?}", &peer_id);
                        //peers.remove(&peer_id);
                        break;
                    }
                    _ => todo!(),
                }
            },
            outgoing = outgoing_queue.next() => {
                match outgoing {
                    Some(message) => {
                        let result = write_part.send(message).await;
                        dbg!(result); // TODO add errors processing
                    },
                    None => {
                        println!("Outgoing queue closed. Stopping send coro");
                        break;
                    }
                }
            },
            _ = stop_handle => {
                println!("Stop callback received");
                break;
            }
        }
    }
}

/// Opens port described by endpoint and starts a coroutine to accept new connections on it
/// Returns stop_handle channel that can be used to stop accepting new connections
pub(crate) async fn start_accepting_connections(
    endpoint: &str,
    peers: Arc<DashMap<PeerIdentity, Peer>>,
    socket_type: SocketType,
) -> ZmqResult<futures::channel::oneshot::Sender<bool>> {
    let mut listener = tokio::net::TcpListener::bind(endpoint).await?;
    let (stop_handle, stop_callback) = futures::channel::oneshot::channel::<bool>();
    tokio::spawn(async move {
        let mut stop_callback = stop_callback.fuse();
        loop {
            select! {
                incoming = listener.accept().fuse() => {
                    let (socket, _) = incoming.expect("Failed to accept connection");
                    tokio::spawn(peer_connected(socket, peers.clone(), socket_type));
                },
                _ = stop_callback => {
                    println!("Stop signal received");
                    break
                }
            }
        }
    });
    Ok(stop_handle)
}
<|endoftext|>


<commit_before>use time;
use num::ToPrimitive;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

/// Calculate the exponential weighted moving average for a vector of numbers, with a smoothing
/// factor `alpha` between 0 and 1. A higher `alpha` discounts older observations faster.
pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> f64 {
    samples.iter().fold(samples.first().map_or(0.0, |v| v.to_f64().unwrap()),
                        |avg, sample| alpha * sample.to_f64().unwrap() + (1.0 - alpha) * avg)
}

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

    #[test]
    fn test_ewma_empty_vector() {
        let empty: Vec<u32> = vec!();
        let alpha = 1.0/3.0;
        assert_eq!(ewma(empty, alpha), 0.0);
    }

    #[test]
    fn test_ewma_one_element() {
        let input = vec!(1u32);
        let alpha = 1.0/3.0;
        assert_eq!(ewma(input, alpha), 1.0);
    }

    #[test]
    fn test_exponential_smoothed_moving_average() {
        let input = (1u32..11).collect();
        let alpha = 1.0/3.0;
        let expected = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0];
        assert_eq!(ewma(input, alpha), expected[expected.len() - 1]);
    }
}
<commit_msg>Use larger integers when converting Timespec<commit_after>use time;
use num::ToPrimitive;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000 + t.nsec as i64 / 1000) as u32
}

/// Calculate the exponential weighted moving average for a vector of numbers, with a smoothing
/// factor `alpha` between 0 and 1. A higher `alpha` discounts older observations faster.
pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> f64 {
    samples.iter().fold(samples.first().map_or(0.0, |v| v.to_f64().unwrap()),
                        |avg, sample| alpha * sample.to_f64().unwrap() + (1.0 - alpha) * avg)
}

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

    #[test]
    fn test_ewma_empty_vector() {
        let empty: Vec<u32> = vec!();
        let alpha = 1.0/3.0;
        assert_eq!(ewma(empty, alpha), 0.0);
    }

    #[test]
    fn test_ewma_one_element() {
        let input = vec!(1u32);
        let alpha = 1.0/3.0;
        assert_eq!(ewma(input, alpha), 1.0);
    }

    #[test]
    fn test_exponential_smoothed_moving_average() {
        let input = (1u32..11).collect();
        let alpha = 1.0/3.0;
        let expected = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0];
        assert_eq!(ewma(input, alpha), expected[expected.len() - 1]);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::num;
use std::num::{Zero, One};
use std::path;
use std::vec;

#[inline]
pub fn alloc_dirty_vec<T>(n : uint) -> Vec<T> {
  let mut v : Vec<T> = vec::Vec::with_capacity(n);
  unsafe {
    v.set_len(n);
  }
  v
}

// Ported from JAMA.
// sqrt(a^2 + b^2) without under/overflow.
pub fn hypot<T : Zero + One + Signed + PartialOrd + Float + Clone>(a : T, b : T) -> T {
  if num::abs(a.clone()) > num::abs(b.clone()) {
    let r = b / a;
    return num::abs(a.clone()) * (num::one::<T>() + r * r).sqrt();
  } else if b != Zero::zero() {
    let r = a / b;
    return num::abs(b.clone()) * (num::one::<T>() + r * r).sqrt();
  } else {
    return Zero::zero();
  }
}

pub fn read_csv<T>(file_name : &str, parser : |&str| -> T) -> super::matrix::Matrix<T> {
  let mut data = vec::Vec::with_capacity(16384);
  let mut row_count = 0;
  let mut col_count = None;

  let path = path::Path::new(file_name);
  let mut file = io::BufferedReader::new(io::File::open(&path));
  for line in file.lines() {
    let element_count = data.len();
    for item in line.unwrap().as_slice().split_str(",") {
      data.push(parser(item))
    }
    let line_col_count = data.len() - element_count;

    if col_count == None {
      col_count = Some(line_col_count);
    } else {
      assert!(col_count.unwrap() == line_col_count);
    }

    row_count += 1;
  }

  assert!(col_count != None);

  super::matrix::matrix(row_count, col_count.unwrap(), data)
}

#[test]
fn hypot_test() {
  assert!(hypot(3.0, 4.0) == 5.0);
  assert!(hypot(4.0, 3.0) == 5.0);
  assert!(hypot(4.0, 0.0) == 4.0);
  assert!(hypot(0.0, 4.0) == 4.0);
  assert!(hypot(-3.0, 4.0) == 5.0);
  assert!(hypot(4.0, -3.0) == 5.0);
  assert!(hypot(-4.0, -3.0) == 5.0);
  assert!(hypot(-4.0, 0.0) == 4.0);
  assert!(hypot(0.0, -4.0) == 4.0);
}
<commit_msg>Fix bug in csv parser.<commit_after>use std::io;
use std::num;
use std::num::{Zero, One};
use std::path;
use std::vec;

#[inline]
pub fn alloc_dirty_vec<T>(n : uint) -> Vec<T> {
  let mut v : Vec<T> = vec::Vec::with_capacity(n);
  unsafe {
    v.set_len(n);
  }
  v
}

// Ported from JAMA.
// sqrt(a^2 + b^2) without under/overflow.
pub fn hypot<T : Zero + One + Signed + PartialOrd + Float + Clone>(a : T, b : T) -> T {
  if num::abs(a.clone()) > num::abs(b.clone()) {
    let r = b / a;
    return num::abs(a.clone()) * (num::one::<T>() + r * r).sqrt();
  } else if b != Zero::zero() {
    let r = a / b;
    return num::abs(b.clone()) * (num::one::<T>() + r * r).sqrt();
  } else {
    return Zero::zero();
  }
}

pub fn read_csv<T>(file_name : &str, parser : |&str| -> T) -> super::matrix::Matrix<T> {
  let mut data = vec::Vec::with_capacity(16384);
  let mut row_count = 0;
  let mut col_count = None;

  let path = path::Path::new(file_name);
  let mut file = io::BufferedReader::new(io::File::open(&path));
  for line in file.lines() {
    let element_count = data.len();
    for item in line.unwrap().as_slice().split_str(",") {
      data.push(parser(item.trim()))
    }
    let line_col_count = data.len() - element_count;

    if col_count == None {
      col_count = Some(line_col_count);
    } else {
      assert!(col_count.unwrap() == line_col_count);
    }

    row_count += 1;
  }

  assert!(col_count != None);

  super::matrix::matrix(row_count, col_count.unwrap(), data)
}

#[test]
fn hypot_test() {
  assert!(hypot(3.0, 4.0) == 5.0);
  assert!(hypot(4.0, 3.0) == 5.0);
  assert!(hypot(4.0, 0.0) == 4.0);
  assert!(hypot(0.0, 4.0) == 4.0);
  assert!(hypot(-3.0, 4.0) == 5.0);
  assert!(hypot(4.0, -3.0) == 5.0);
  assert!(hypot(-4.0, -3.0) == 5.0);
  assert!(hypot(-4.0, 0.0) == 4.0);
  assert!(hypot(0.0, -4.0) == 4.0);
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::cmp;
use types::Layout;
use types::Layout::*;

pub fn transpose_data<T: Sized + Clone>(initial_layout: Layout, m: usize, n: usize, input: &[T], ld_input: usize, output: &mut [T], ld_output: usize) {
    let (x, y) = match initial_layout {
        ColMajor => (n, m),
        RowMajor => (m, n),
    };

    for i in 0..cmp::min(y, ld_input) {
        for j in 0..cmp::min(x, ld_output) {
            output[i * ld_output + j] = input[j * ld_input + i].clone();
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use types::Layout::*;
    use util::transpose_data;

    #[test]
    fn transpose() {
        let i: [f64; 6] = [2.0,4.0,7.0,3.0,9.0,4.0];
        let mut buf: [f64; 6] = unsafe {mem::zeroed()};
        let o: [f64; 6] = [2.0,3.0,4.0,9.0,7.0,4.0];

        transpose_data(ColMajor, 3, 2, &i, 3, &mut buf, 2);
        assert_eq!(buf, o);
    }
}
<commit_msg>Use pointers and make unsafe<commit_after>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::cmp;
use std::ptr;
use types::Layout;
use types::Layout::*;

pub unsafe fn transpose_data<T>(initial_layout: Layout, m: isize, n: isize, input: *const T, ld_input: isize, output: *mut T, ld_output: isize) {
    let (x, y) = match initial_layout {
        ColMajor => (n, m),
        RowMajor => (m, n),
    };

    for i in 0..cmp::min(y, ld_input) {
        for j in 0..cmp::min(x, ld_output) {
            ptr::write(
                output.offset(i * ld_output + j),
            ptr::read(
                input.offset(j * ld_input + i)));
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;
    use types::Layout::*;
    use util::transpose_data;

    #[test]
    fn transpose() {
        let i: [f64; 6] = [2.0,4.0,7.0,3.0,9.0,4.0];
        let mut buf: [f64; 6] = unsafe {mem::zeroed()};
        let o: [f64; 6] = [2.0,3.0,4.0,9.0,7.0,4.0];

        unsafe {
            transpose_data(ColMajor, 3, 2, (&i).as_ptr(), 3, (&mut buf).as_mut_ptr(), 2);
        }
        assert_eq!(buf, o);
    }
}
<|endoftext|>


<commit_before>//! Convenient utility methods, mostly for printing `syntect` data structures
//! prettily to the terminal.
use highlighting::Style;
use std::fmt::Write;
#[cfg(feature = "parsing")]
use parsing::ScopeStackOp;

/// Formats the styled fragments using 24-bit colour
/// terminal escape codes. Meant for debugging and testing.
/// It's currently fairly inefficient in its use of escape codes.
///
/// Note that this does not currently ever un-set the colour so that
/// the end of a line will also get highlighted with the background.
/// This means if you might want to use `println!("\x1b[0m");` after
/// to clear the colouring.
///
/// If `bg` is true then the background is also set
pub fn as_24_bit_terminal_escaped(v: &[(Style, &str)], bg: bool) -> String {
    let mut s: String = String::new();
    for &(ref style, text) in v.iter() {
        if bg {
            write!(s,
                   "\x1b[48;2;{};{};{}m",
                   style.background.r,
                   style.background.g,
                   style.background.b)
                .unwrap();
        }
        write!(s,
               "\x1b[38;2;{};{};{}m{}",
               style.foreground.r,
               style.foreground.g,
               style.foreground.b,
               text)
            .unwrap();
    }
    // s.push_str("\x1b[0m");
    s
}

/// Print out the various push and pop operations in a vector
/// with visual alignment to the line. Obviously for debugging.
#[cfg(feature = "parsing")]
pub fn debug_print_ops(line: &str, ops: &[(usize, ScopeStackOp)]) {
    for &(i, ref op) in ops.iter() {
        println!("{}", line.trim_right());
        print!("{: <1$}", "", i);
        match *op {
            ScopeStackOp::Push(s) => {
                println!("^ +{}", s);
            }
            ScopeStackOp::Pop(count) => {
                println!("^ pop {}", count);
            }
            ScopeStackOp::Clear(amount) => {
                println!("^ clear {:?}", amount);
            }
            ScopeStackOp::Restore => println!("^ restore"),
            ScopeStackOp::Noop => println!("noop"),
        }
    }
}
<commit_msg>Add `LinesWithEndings` util for iterating over lines (#196)<commit_after>//! Convenient utility methods, mostly for printing `syntect` data structures
//! prettily to the terminal.
use highlighting::Style;
use std::fmt::Write;
#[cfg(feature = "parsing")]
use parsing::ScopeStackOp;

/// Formats the styled fragments using 24-bit colour
/// terminal escape codes. Meant for debugging and testing.
/// It's currently fairly inefficient in its use of escape codes.
///
/// Note that this does not currently ever un-set the colour so that
/// the end of a line will also get highlighted with the background.
/// This means if you might want to use `println!("\x1b[0m");` after
/// to clear the colouring.
///
/// If `bg` is true then the background is also set
pub fn as_24_bit_terminal_escaped(v: &[(Style, &str)], bg: bool) -> String {
    let mut s: String = String::new();
    for &(ref style, text) in v.iter() {
        if bg {
            write!(s,
                   "\x1b[48;2;{};{};{}m",
                   style.background.r,
                   style.background.g,
                   style.background.b)
                .unwrap();
        }
        write!(s,
               "\x1b[38;2;{};{};{}m{}",
               style.foreground.r,
               style.foreground.g,
               style.foreground.b,
               text)
            .unwrap();
    }
    // s.push_str("\x1b[0m");
    s
}

/// Print out the various push and pop operations in a vector
/// with visual alignment to the line. Obviously for debugging.
#[cfg(feature = "parsing")]
pub fn debug_print_ops(line: &str, ops: &[(usize, ScopeStackOp)]) {
    for &(i, ref op) in ops.iter() {
        println!("{}", line.trim_right());
        print!("{: <1$}", "", i);
        match *op {
            ScopeStackOp::Push(s) => {
                println!("^ +{}", s);
            }
            ScopeStackOp::Pop(count) => {
                println!("^ pop {}", count);
            }
            ScopeStackOp::Clear(amount) => {
                println!("^ clear {:?}", amount);
            }
            ScopeStackOp::Restore => println!("^ restore"),
            ScopeStackOp::Noop => println!("noop"),
        }
    }
}

/// An iterator over the lines of a string, including the line endings.
///
/// This is similar to the standard library's `lines` method on `str`, except
/// that the yielded lines include the trailing newline character(s).
///
/// You can use it if you're parsing/highlighting some text that you have as a
/// string. With this, you can use the "newlines" variant of syntax definitions,
/// which is recommended.
///
/// # Examples
///
/// ```
/// use syntect::util::LinesWithEndings;
///
/// let mut lines = LinesWithEndings::from("foo\nbar\nbaz");
///
/// assert_eq!(Some("foo\n"), lines.next());
/// assert_eq!(Some("bar\n"), lines.next());
/// assert_eq!(Some("baz"), lines.next());
///
/// assert_eq!(None, lines.next());
/// ```
pub struct LinesWithEndings<'a> {
    input: &'a str,
}

impl<'a> LinesWithEndings<'a> {
    pub fn from(input: &'a str) -> LinesWithEndings<'a> {
        LinesWithEndings { input }
    }
}

impl<'a> Iterator for LinesWithEndings<'a> {
    type Item = &'a str;

    #[inline]
    fn next(&mut self) -> Option<&'a str> {
        if self.input.is_empty() {
            return None;
        }
        let split = self.input
            .find('\n')
            .map(|i| i + 1)
            .unwrap_or_else(|| self.input.len());
        let (line, rest) = self.input.split_at(split);
        self.input = rest;
        Some(line)
    }
}

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

    #[test]
    fn test_lines_with_endings() {
        fn lines(s: &str) -> Vec<&str> {
            LinesWithEndings::from(s).collect()
        }

        assert!(lines("").is_empty());
        assert_eq!(lines("f"), vec!["f"]);
        assert_eq!(lines("foo"), vec!["foo"]);
        assert_eq!(lines("foo\n"), vec!["foo\n"]);
        assert_eq!(lines("foo\nbar"), vec!["foo\n", "bar"]);
        assert_eq!(lines("foo\nbar\n"), vec!["foo\n", "bar\n"]);
        assert_eq!(lines("foo\r\nbar"), vec!["foo\r\n", "bar"]);
        assert_eq!(lines("foo\r\nbar\r\n"), vec!["foo\r\n", "bar\r\n"]);
        assert_eq!(lines("\nfoo"), vec!["\n", "foo"]);
        assert_eq!(lines("\n\n\n"), vec!["\n", "\n", "\n"]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::Ident;
use crate::syntax::source_map::Span;
use crate::utils::paths;
use crate::utils::{
    in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
};
use if_chain::if_chain;

#[derive(Clone)]
pub struct Pass;

/// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests
/// `iterator.cloned()` instead
///
/// **Why is this bad?** Readability, this can be written more concisely
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust
/// let x = vec![42, 43];
/// let y = x.iter();
/// let z = y.map(|i| *i);
/// ```
///
/// The correct use would be:
///
/// ```rust
/// let x = vec![42, 43];
/// let y = x.iter();
/// let z = y.cloned();
/// ```
declare_clippy_lint! {
    pub MAP_CLONE,
    style,
    "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types"
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(MAP_CLONE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
        if in_macro(e.span) {
            return;
        }

        if_chain! {
            if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.node;
            if args.len() == 2;
            if method.ident.as_str() == "map";
            let ty = cx.tables.expr_ty(&args[0]);
            if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR);
            if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node;
            let closure_body = cx.tcx.hir().body(body_id);
            let closure_expr = remove_blocks(&closure_body.value);
            then {
                match closure_body.arguments[0].pat.node {
                    hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(
                        hir::BindingAnnotation::Unannotated, _, name, None
                    ) = inner.node {
                        lint(cx, e.span, args[0].span, name, closure_expr);
                    },
                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
                        match closure_expr.node {
                            hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => {
                                if !cx.tables.expr_ty(inner).is_box() {
                                    lint(cx, e.span, args[0].span, name, inner);
                                }
                            },
                            hir::ExprKind::MethodCall(ref method, _, ref obj) => {
                                if method.ident.as_str() == "clone"
                                    && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
                                    lint(cx, e.span, args[0].span, name, &obj[0]);
                                }
                            },
                            _ => {},
                        }
                    },
                    _ => {},
                }
            }
        }
    }
}

fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) {
    if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node {
        if path.segments.len() == 1 && path.segments[0].ident == name {
            let mut applicability = Applicability::MachineApplicable;
            span_lint_and_sugg(
                cx,
                MAP_CLONE,
                replace,
                "You are using an explicit closure for cloning elements",
                "Consider calling the dedicated `cloned` method",
                format!(
                    "{}.cloned()",
                    snippet_with_applicability(cx, root, "..", &mut applicability)
                ),
                applicability,
            )
        }
    }
}
<commit_msg>Auto merge of #3573 - Vlad-Shcherbina:map_clone_caveat, r=flip1995<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc::hir;
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::Ident;
use crate::syntax::source_map::Span;
use crate::utils::paths;
use crate::utils::{
    in_macro, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg,
};
use if_chain::if_chain;

#[derive(Clone)]
pub struct Pass;

/// **What it does:** Checks for usage of `iterator.map(|x| x.clone())` and suggests
/// `iterator.cloned()` instead
///
/// **Why is this bad?** Readability, this can be written more concisely
///
/// **Known problems:** Sometimes `.cloned()` requires stricter trait
/// bound than `.map(|e| e.clone())` (which works because of the coercion).
/// See [#498](https://github.com/rust-lang-nursery/rust-clippy/issues/498).
///
/// **Example:**
///
/// ```rust
/// let x = vec![42, 43];
/// let y = x.iter();
/// let z = y.map(|i| *i);
/// ```
///
/// The correct use would be:
///
/// ```rust
/// let x = vec![42, 43];
/// let y = x.iter();
/// let z = y.cloned();
/// ```
declare_clippy_lint! {
    pub MAP_CLONE,
    style,
    "using `iterator.map(|x| x.clone())`, or dereferencing closures for `Copy` types"
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(MAP_CLONE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
        if in_macro(e.span) {
            return;
        }

        if_chain! {
            if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.node;
            if args.len() == 2;
            if method.ident.as_str() == "map";
            let ty = cx.tables.expr_ty(&args[0]);
            if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR);
            if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].node;
            let closure_body = cx.tcx.hir().body(body_id);
            let closure_expr = remove_blocks(&closure_body.value);
            then {
                match closure_body.arguments[0].pat.node {
                    hir::PatKind::Ref(ref inner, _) => if let hir::PatKind::Binding(
                        hir::BindingAnnotation::Unannotated, _, name, None
                    ) = inner.node {
                        lint(cx, e.span, args[0].span, name, closure_expr);
                    },
                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
                        match closure_expr.node {
                            hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner) => {
                                if !cx.tables.expr_ty(inner).is_box() {
                                    lint(cx, e.span, args[0].span, name, inner);
                                }
                            },
                            hir::ExprKind::MethodCall(ref method, _, ref obj) => {
                                if method.ident.as_str() == "clone"
                                    && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
                                    lint(cx, e.span, args[0].span, name, &obj[0]);
                                }
                            },
                            _ => {},
                        }
                    },
                    _ => {},
                }
            }
        }
    }
}

fn lint(cx: &LateContext<'_, '_>, replace: Span, root: Span, name: Ident, path: &hir::Expr) {
    if let hir::ExprKind::Path(hir::QPath::Resolved(None, ref path)) = path.node {
        if path.segments.len() == 1 && path.segments[0].ident == name {
            let mut applicability = Applicability::MachineApplicable;
            span_lint_and_sugg(
                cx,
                MAP_CLONE,
                replace,
                "You are using an explicit closure for cloning elements",
                "Consider calling the dedicated `cloned` method",
                format!(
                    "{}.cloned()",
                    snippet_with_applicability(cx, root, "..", &mut applicability)
                ),
                applicability,
            )
        }
    }
}
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle, Color};
use {Fill, Clear, BackEnd};
use triangulation::{rect_tri_list_xy_f32, rect_tri_list_rgba_f32};

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for RectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_rgba_f32() {
            let rect = self.rect.get();
            let rect: [f32, ..4] = [rect[0] as f32, rect[1] as f32, rect[2] as f32, rect[3] as f32];
            let color = self.color.get();
            let color: [f32, ..4] = [color[0] as f32, color[1] as f32, color[2] as f32, color[3] as f32];
            back_end.tri_list_xy_rgba_f32(
                rect_tri_list_xy_f32(rect),
                rect_tri_list_rgba_f32(color)
            );
        } else {
            unimplemented!();
        }
    }
}

impl<'a> Clear for RectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}
<commit_msg>Casting to f32 not required<commit_after>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle, Color};
use {Fill, Clear, BackEnd};
use triangulation::{rect_tri_list_xy_f32, rect_tri_list_rgba_f32};

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for RectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_rgba_f32() {
            let rect = self.rect.get();
            let rect: [f32, ..4] = [rect[0] as f32, rect[1] as f32, rect[2] as f32, rect[3] as f32];
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            back_end.tri_list_xy_rgba_f32(
                rect_tri_list_xy_f32(rect),
                rect_tri_list_rgba_f32(color)
            );
        } else {
            unimplemented!();
        }
    }
}

impl<'a> Clear for RectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}
<|endoftext|>


<commit_before>//! Client Requests
use std::marker::PhantomData;
use std::io::{self, Write, BufWriter};

use url::Url;

use method::{self, Method};
use header::Headers;
use header::{self, Host};
use net::{NetworkStream, NetworkConnector, HttpConnector, Fresh, Streaming};
use http::{HttpWriter, LINE_ENDING};
use http::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter};
use version;
use client::{Response, get_host_and_port};

/// A client request to a remote server.
pub struct Request<W> {
    /// The target URI for this request.
    pub url: Url,

    /// The HTTP version of this request.
    pub version: version::HttpVersion,

    body: HttpWriter<BufWriter<Box<NetworkStream + Send>>>,
    headers: Headers,
    method: method::Method,

    _marker: PhantomData<W>,
}

impl<W> Request<W> {
    /// Read the Request headers.
    #[inline]
    pub fn headers(&self) -> &Headers { &self.headers }

    /// Read the Request method.
    #[inline]
    pub fn method(&self) -> method::Method { self.method.clone() }
}

impl Request<Fresh> {
    /// Create a new client request.
    pub fn new(method: method::Method, url: Url) -> ::Result<Request<Fresh>> {
        let mut conn = HttpConnector(None);
        Request::with_connector(method, url, &mut conn)
    }

    /// Create a new client request with a specific underlying NetworkStream.
    pub fn with_connector<C, S>(method: method::Method, url: Url, connector: &C)
        -> ::Result<Request<Fresh>> where
        C: NetworkConnector<Stream=S>,
        S: Into<Box<NetworkStream + Send>> {
        let (host, port) = try!(get_host_and_port(&url));

        let stream = try!(connector.connect(&*host, port, &*url.scheme)).into();
        let stream = ThroughWriter(BufWriter::new(stream));

        let mut headers = Headers::new();
        headers.set(Host {
            hostname: host,
            port: Some(port),
        });

        Ok(Request {
            method: method,
            headers: headers,
            url: url,
            version: version::HttpVersion::Http11,
            body: stream,
            _marker: PhantomData,
        })
    }

    /// Consume a Fresh Request, writing the headers and method,
    /// returning a Streaming Request.
    pub fn start(mut self) -> ::Result<Request<Streaming>> {
        let mut uri = self.url.serialize_path().unwrap();
        //TODO: this needs a test
        if let Some(ref q) = self.url.query {
            uri.push('?');
            uri.push_str(&q[..]);
        }

        debug!("request line: {:?} {:?} {:?}", self.method, uri, self.version);
        try!(write!(&mut self.body, "{} {} {}{}",
                    self.method, uri, self.version, LINE_ENDING));

        let stream = match self.method {
            Method::Get | Method::Head => {
                debug!("headers={:?}", self.headers);
                try!(write!(&mut self.body, "{}{}", self.headers, LINE_ENDING));
                EmptyWriter(self.body.into_inner())
            },
            _ => {
                let mut chunked = true;
                let mut len = 0;

                match self.headers.get::<header::ContentLength>() {
                    Some(cl) => {
                        chunked = false;
                        len = **cl;
                    },
                    None => ()
                };

                // can't do in match above, thanks borrowck
                if chunked {
                    let encodings = match self.headers.get_mut::<header::TransferEncoding>() {
                        Some(&mut header::TransferEncoding(ref mut encodings)) => {
                            //TODO: check if chunked is already in encodings. use HashSet?
                            encodings.push(header::Encoding::Chunked);
                            false
                        },
                        None => true
                    };

                    if encodings {
                        self.headers.set::<header::TransferEncoding>(
                            header::TransferEncoding(vec![header::Encoding::Chunked]))
                    }
                }

                debug!("headers={:?}", self.headers);
                try!(write!(&mut self.body, "{}{}", self.headers, LINE_ENDING));

                if chunked {
                    ChunkedWriter(self.body.into_inner())
                } else {
                    SizedWriter(self.body.into_inner(), len)
                }
            }
        };

        Ok(Request {
            method: self.method,
            headers: self.headers,
            url: self.url,
            version: self.version,
            body: stream,
            _marker: PhantomData,
        })
    }

    /// Get a mutable reference to the Request headers.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut Headers { &mut self.headers }
}

impl Request<Streaming> {
    /// Completes writing the request, and returns a response to read from.
    ///
    /// Consumes the Request.
    pub fn send(self) -> ::Result<Response> {
        let raw = try!(self.body.end()).into_inner().unwrap(); // end() already flushes
        Response::new(raw)
    }
}

impl Write for Request<Streaming> {
    #[inline]
    fn write(&mut self, msg: &[u8]) -> io::Result<usize> {
        self.body.write(msg)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.body.flush()
    }
}

#[cfg(test)]
mod tests {
    use std::str::from_utf8;
    use url::Url;
    use method::Method::{Get, Head};
    use mock::{MockStream, MockConnector};
    use super::Request;

    #[test]
    fn test_get_empty_body() {
        let req = Request::with_connector(
            Get, Url::parse("http://example.dom").unwrap(), &mut MockConnector
        ).unwrap();
        let req = req.start().unwrap();
        let stream = *req.body.end().unwrap()
            .into_inner().unwrap().downcast::<MockStream>().ok().unwrap();
        let bytes = stream.write;
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(!s.contains("Content-Length:"));
        assert!(!s.contains("Transfer-Encoding:"));
    }

    #[test]
    fn test_head_empty_body() {
        let req = Request::with_connector(
            Head, Url::parse("http://example.dom").unwrap(), &mut MockConnector
        ).unwrap();
        let req = req.start().unwrap();
        let stream = *req.body.end().unwrap()
            .into_inner().unwrap().downcast::<MockStream>().ok().unwrap();
        let bytes = stream.write;
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(!s.contains("Content-Length:"));
        assert!(!s.contains("Transfer-Encoding:"));
    }
}
<commit_msg>test(request): increasing test coverage of request module<commit_after>//! Client Requests
use std::marker::PhantomData;
use std::io::{self, Write, BufWriter};

use url::Url;

use method::{self, Method};
use header::Headers;
use header::{self, Host};
use net::{NetworkStream, NetworkConnector, HttpConnector, Fresh, Streaming};
use http::{HttpWriter, LINE_ENDING};
use http::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter};
use version;
use client::{Response, get_host_and_port};

/// A client request to a remote server.
/// The W type tracks the state of the request, Fresh vs Streaming.
pub struct Request<W> {
    /// The target URI for this request.
    pub url: Url,

    /// The HTTP version of this request.
    pub version: version::HttpVersion,

    body: HttpWriter<BufWriter<Box<NetworkStream + Send>>>,
    headers: Headers,
    method: method::Method,

    _marker: PhantomData<W>,
}

impl<W> Request<W> {
    /// Read the Request headers.
    #[inline]
    pub fn headers(&self) -> &Headers { &self.headers }

    /// Read the Request method.
    #[inline]
    pub fn method(&self) -> method::Method { self.method.clone() }
}

impl Request<Fresh> {
    /// Create a new client request.
    pub fn new(method: method::Method, url: Url) -> ::Result<Request<Fresh>> {
        let mut conn = HttpConnector(None);
        Request::with_connector(method, url, &mut conn)
    }

    /// Create a new client request with a specific underlying NetworkStream.
    pub fn with_connector<C, S>(method: method::Method, url: Url, connector: &C)
        -> ::Result<Request<Fresh>> where
        C: NetworkConnector<Stream=S>,
        S: Into<Box<NetworkStream + Send>> {
        let (host, port) = try!(get_host_and_port(&url));

        let stream = try!(connector.connect(&*host, port, &*url.scheme)).into();
        let stream = ThroughWriter(BufWriter::new(stream));

        let mut headers = Headers::new();
        headers.set(Host {
            hostname: host,
            port: Some(port),
        });

        Ok(Request {
            method: method,
            headers: headers,
            url: url,
            version: version::HttpVersion::Http11,
            body: stream,
            _marker: PhantomData,
        })
    }

    /// Consume a Fresh Request, writing the headers and method,
    /// returning a Streaming Request.
    pub fn start(mut self) -> ::Result<Request<Streaming>> {
        let mut uri = self.url.serialize_path().unwrap();
        if let Some(ref q) = self.url.query {
            uri.push('?');
            uri.push_str(&q[..]);
        }

        debug!("request line: {:?} {:?} {:?}", self.method, uri, self.version);
        try!(write!(&mut self.body, "{} {} {}{}",
                    self.method, uri, self.version, LINE_ENDING));

        let stream = match self.method {
            Method::Get | Method::Head => {
                debug!("headers={:?}", self.headers);
                try!(write!(&mut self.body, "{}{}", self.headers, LINE_ENDING));
                EmptyWriter(self.body.into_inner())
            },
            _ => {
                let mut chunked = true;
                let mut len = 0;

                match self.headers.get::<header::ContentLength>() {
                    Some(cl) => {
                        chunked = false;
                        len = **cl;
                    },
                    None => ()
                };

                // can't do in match above, thanks borrowck
                if chunked {
                    let encodings = match self.headers.get_mut::<header::TransferEncoding>() {
                        Some(&mut header::TransferEncoding(ref mut encodings)) => {
                            //TODO: check if chunked is already in encodings. use HashSet?
                            encodings.push(header::Encoding::Chunked);
                            false
                        },
                        None => true
                    };

                    if encodings {
                        self.headers.set::<header::TransferEncoding>(
                            header::TransferEncoding(vec![header::Encoding::Chunked]))
                    }
                }

                debug!("headers={:?}", self.headers);
                try!(write!(&mut self.body, "{}{}", self.headers, LINE_ENDING));

                if chunked {
                    ChunkedWriter(self.body.into_inner())
                } else {
                    SizedWriter(self.body.into_inner(), len)
                }
            }
        };

        Ok(Request {
            method: self.method,
            headers: self.headers,
            url: self.url,
            version: self.version,
            body: stream,
            _marker: PhantomData,
        })
    }

    /// Get a mutable reference to the Request headers.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut Headers { &mut self.headers }
}

impl Request<Streaming> {
    /// Completes writing the request, and returns a response to read from.
    ///
    /// Consumes the Request.
    pub fn send(self) -> ::Result<Response> {
        let raw = try!(self.body.end()).into_inner().unwrap(); // end() already flushes
        Response::new(raw)
    }
}

impl Write for Request<Streaming> {
    #[inline]
    fn write(&mut self, msg: &[u8]) -> io::Result<usize> {
        self.body.write(msg)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        self.body.flush()
    }
}

#[cfg(test)]
mod tests {
    use std::str::from_utf8;
    use url::Url;
    use method::Method::{Get, Head, Post};
    use mock::{MockStream, MockConnector};
    use net::Fresh;
    use header::{ContentLength,TransferEncoding,Encoding};
    use url::form_urlencoded;
    use super::Request;

    fn run_request(req: Request<Fresh>) -> Vec<u8> {
        let req = req.start().unwrap();
        let stream = *req.body.end().unwrap()
            .into_inner().unwrap().downcast::<MockStream>().ok().unwrap();
        stream.write
    }

    fn assert_no_body(s: &str) {
        assert!(!s.contains("Content-Length:"));
        assert!(!s.contains("Transfer-Encoding:"));
    }

    #[test]
    fn test_get_empty_body() {
        let req = Request::with_connector(
            Get, Url::parse("http://example.dom").unwrap(), &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert_no_body(s);
    }

    #[test]
    fn test_head_empty_body() {
        let req = Request::with_connector(
            Head, Url::parse("http://example.dom").unwrap(), &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert_no_body(s);
    }

    #[test]
    fn test_url_query() {
        let url = Url::parse("http://example.dom?q=value").unwrap();
        let req = Request::with_connector(
            Get, url, &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(s.contains("?q=value"));
    }

    #[test]
    fn test_post_content_length() {
        let url = Url::parse("http://example.dom").unwrap();
        let mut req = Request::with_connector(
            Post, url, &mut MockConnector
        ).unwrap();
        let body = form_urlencoded::serialize(vec!(("q","value")).into_iter());
        req.headers_mut().set(ContentLength(body.len() as u64));
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(s.contains("Content-Length:"));
    }

    #[test]
    fn test_post_chunked() {
        let url = Url::parse("http://example.dom").unwrap();
        let req = Request::with_connector(
            Post, url, &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(!s.contains("Content-Length:"));
    }

    #[test]
    fn test_post_chunked_with_encoding() {
        let url = Url::parse("http://example.dom").unwrap();
        let mut req = Request::with_connector(
            Post, url, &mut MockConnector
        ).unwrap();
        req.headers_mut().set(TransferEncoding(vec![Encoding::Chunked]));
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(!s.contains("Content-Length:"));
        assert!(s.contains("Transfer-Encoding:"));
    }
}
<|endoftext|>


<commit_before>//! Encoding and decoding of the (15, 11, 3) standard and (10, 6, 3) shortened Hamming
//! codes described by P25.
//!
//! Both codes can correct up to 1 error. These algorithms are sourced from \[1].
//!
//! \[1]: "Coding Theory and Cryptography: The Essentials", 2nd ed, Hankerson, Hoffman, et
//! al, 2000

/// Encoding and decoding of the (15, 11, 3) code.
pub mod standard {
    /// Encode the 11 bits of data to a 15-bit codeword.
    pub fn encode(data: u16) -> u16 {
        assert!(data >> 11 == 0);
        matrix_mul_systematic!(data, GEN, u16)
    }

    /// Try to decode the 15-bit word to the nearest codeword, correcting up to 1 error.
    /// Return `Some((data, err))`, where `data` are the 11 data bits and `err` is the
    /// number of errors, on success and `None` on an unrecoverable error.
    pub fn decode(word: u16) -> Option<(u16, usize)> {
        assert!(word >> 15 == 0);
        super::decode_hamming::<StandardHamming>(word)
    }

    /// Generator patterns for 4 parity bits.
    const GEN: [u16; 4] = [
        0b11111110000,
        0b11110001110,
        0b11001101101,
        0b10101011011,
    ];

    /// Parity-check patterns for 4 syndromes.
    const PAR: [u16; 4] = [
        0b111111100001000,
        0b111100011100100,
        0b110011011010010,
        0b101010110110001,
    ];

    /// Maps 4-bit syndrome values to bit error locations.
    const LOCATIONS: [u16; 16] = [
        0,
        0b0000000000000001,
        0b0000000000000010,
        0b0000000000010000,
        0b0000000000000100,
        0b0000000000100000,
        0b0000000001000000,
        0b0000000010000000,
        0b0000000000001000,
        0b0000000100000000,
        0b0000001000000000,
        0b0000010000000000,
        0b0000100000000000,
        0b0001000000000000,
        0b0010000000000000,
        0b0100000000000000,
    ];

    struct StandardHamming;

    impl super::HammingDecoder for StandardHamming {
        type Data = u16;

        fn data(word: u16) -> u16 { word >> 4 }
        fn par() -> [u16; 4] { PAR }
        fn locs() -> [u16; 16] { LOCATIONS }
    }
}

/// Encoding and decoding of the (10, 6, 3) code.
pub mod shortened {
    /// Encode the 6 data bits to a 10-bit codeword.
    pub fn encode(data: u8) -> u16 {
        assert!(data >> 6 == 0);
        matrix_mul_systematic!(data, GEN, u16)
    }

    /// Try to decode the 10-bit word to the nearest codeword, correcting up to 1 error.
    /// Return `Some((data, err))`, where `data` are the 6 data bits and `err` is the
    /// number of errors, on success and `None` on an unrecoverable error.
    pub fn decode(word: u16) -> Option<(u8, usize)> {
        assert!(word >> 10 == 0);
        super::decode_hamming::<ShortHamming>(word)
    }

    const GEN: [u8; 4] = [
        0b111001,
        0b110101,
        0b101110,
        0b011110,
    ];

    const PAR: [u16; 4] = [
        0b1110011000,
        0b1101010100,
        0b1011100010,
        0b0111100001,
    ];

    const LOCATIONS: [u16; 16] = [
        0,
        0b0000000000000001,
        0b0000000000000010,
        0b0000000000100000,
        0b0000000000000100,
        0,
        0,
        0b0000000001000000,
        0b0000000000001000,
        0,
        0,
        0b0000000010000000,
        0b0000000000010000,
        0b0000000100000000,
        0b0000001000000000,
        0,
    ];

    struct ShortHamming;

    impl super::HammingDecoder for ShortHamming {
        type Data = u8;

        fn data(word: u16) -> u8 { (word >> 4) as u8 }
        fn par() -> [u16; 4] { PAR }
        fn locs() -> [u16; 16] { LOCATIONS }
    }
}

/// Defines code-specific decoding functions.
trait HammingDecoder {
    /// The type of the data bit output.
    type Data;

    /// Convert the codeword to data bits.
    fn data(word: u16) -> Self::Data;

    /// Return the parity-check patterns for 4 syndromes.
    fn par() -> [u16; 4];

    /// Return the syndrome-error location map.
    fn locs() -> [u16; 16];
}

/// Use the given decoder to decode the given word.
fn decode_hamming<H: HammingDecoder>(word: u16) -> Option<(H::Data, usize)> {
    // Compute the 4-bit syndrome.
    let s = matrix_mul!(word, H::par(), u8);

    // A zero syndrome means it's a valid codeword (possibly different from the
    // transmitted codeword.)
    if s == 0 {
        return Some((H::data(word), 0));
    }

    match H::locs().get(s as usize) {
        // More than one error/unrecoverable error.
        Some(&0) | None => None,
        // Valid location means the error can be corrected.
        Some(&loc) => Some((H::data(word ^ loc), 1)),
    }
}

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

    #[test]
    fn test_standard() {
        let w = 0b10101010101;
        let e = standard::encode(w);
        assert_eq!(standard::decode(e^0b000000000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000000001).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000000010).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000000100).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000001000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000010000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000100000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000001000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000010000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000100000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000001000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000010000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000100000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b001000000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b010000000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b100000000000000).unwrap().0, w);

        for i in 0..1<<11 {
            assert_eq!(standard::decode(standard::encode(i)).unwrap().0, i);
        }
    }

    #[test]
    fn test_shortened() {
        let w = 0b110011;
        let e = shortened::encode(w);
        assert_eq!(shortened::decode(e ^ 0b0000000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000000001).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000000010).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000000100).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000001000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000010000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000100000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0001000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0010000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0100000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b1000000000).unwrap().0, w);

        for i in 0..1<<6 {
            assert_eq!(shortened::decode(shortened::encode(i)).unwrap().0, i);
        }
    }
}
<commit_msg>Use a trait method rather than free function<commit_after>//! Encoding and decoding of the (15, 11, 3) standard and (10, 6, 3) shortened Hamming
//! codes described by P25.
//!
//! Both codes can correct up to 1 error. These algorithms are sourced from \[1].
//!
//! \[1]: "Coding Theory and Cryptography: The Essentials", 2nd ed, Hankerson, Hoffman, et
//! al, 2000

/// Encoding and decoding of the (15, 11, 3) code.
pub mod standard {
    use super::HammingDecoder;

    /// Encode the 11 bits of data to a 15-bit codeword.
    pub fn encode(data: u16) -> u16 {
        assert!(data >> 11 == 0);
        matrix_mul_systematic!(data, GEN, u16)
    }

    /// Try to decode the 15-bit word to the nearest codeword, correcting up to 1 error.
    /// Return `Some((data, err))`, where `data` are the 11 data bits and `err` is the
    /// number of errors, on success and `None` on an unrecoverable error.
    pub fn decode(word: u16) -> Option<(u16, usize)> {
        assert!(word >> 15 == 0);
        StandardHamming::decode(word)
    }

    /// Generator patterns for 4 parity bits.
    const GEN: [u16; 4] = [
        0b11111110000,
        0b11110001110,
        0b11001101101,
        0b10101011011,
    ];

    /// Parity-check patterns for 4 syndromes.
    const PAR: [u16; 4] = [
        0b111111100001000,
        0b111100011100100,
        0b110011011010010,
        0b101010110110001,
    ];

    /// Maps 4-bit syndrome values to bit error locations.
    const LOCATIONS: [u16; 16] = [
        0,
        0b0000000000000001,
        0b0000000000000010,
        0b0000000000010000,
        0b0000000000000100,
        0b0000000000100000,
        0b0000000001000000,
        0b0000000010000000,
        0b0000000000001000,
        0b0000000100000000,
        0b0000001000000000,
        0b0000010000000000,
        0b0000100000000000,
        0b0001000000000000,
        0b0010000000000000,
        0b0100000000000000,
    ];

    struct StandardHamming;

    impl super::HammingDecoder for StandardHamming {
        type Data = u16;

        fn data(word: u16) -> u16 { word >> 4 }
        fn par() -> [u16; 4] { PAR }
        fn locs() -> [u16; 16] { LOCATIONS }
    }
}

/// Encoding and decoding of the (10, 6, 3) code.
pub mod shortened {
    use super::HammingDecoder;

    /// Encode the 6 data bits to a 10-bit codeword.
    pub fn encode(data: u8) -> u16 {
        assert!(data >> 6 == 0);
        matrix_mul_systematic!(data, GEN, u16)
    }

    /// Try to decode the 10-bit word to the nearest codeword, correcting up to 1 error.
    /// Return `Some((data, err))`, where `data` are the 6 data bits and `err` is the
    /// number of errors, on success and `None` on an unrecoverable error.
    pub fn decode(word: u16) -> Option<(u8, usize)> {
        assert!(word >> 10 == 0);
        ShortHamming::decode(word)
    }

    const GEN: [u8; 4] = [
        0b111001,
        0b110101,
        0b101110,
        0b011110,
    ];

    const PAR: [u16; 4] = [
        0b1110011000,
        0b1101010100,
        0b1011100010,
        0b0111100001,
    ];

    const LOCATIONS: [u16; 16] = [
        0,
        0b0000000000000001,
        0b0000000000000010,
        0b0000000000100000,
        0b0000000000000100,
        0,
        0,
        0b0000000001000000,
        0b0000000000001000,
        0,
        0,
        0b0000000010000000,
        0b0000000000010000,
        0b0000000100000000,
        0b0000001000000000,
        0,
    ];

    struct ShortHamming;

    impl super::HammingDecoder for ShortHamming {
        type Data = u8;

        fn data(word: u16) -> u8 { (word >> 4) as u8 }
        fn par() -> [u16; 4] { PAR }
        fn locs() -> [u16; 16] { LOCATIONS }
    }
}

/// Defines code-specific decoding functions.
trait HammingDecoder {
    /// The type of the data bit output.
    type Data;

    /// Convert the codeword to data bits.
    fn data(word: u16) -> Self::Data;

    /// Return the parity-check patterns for 4 syndromes.
    fn par() -> [u16; 4];

    /// Return the syndrome-error location map.
    fn locs() -> [u16; 16];

    /// Use the current decoder to decode the given word.
    fn decode(word: u16) -> Option<(Self::Data, usize)> {
        // Compute the 4-bit syndrome.
        let s = matrix_mul!(word, Self::par(), u8);

        // A zero syndrome means it's a valid codeword (possibly different from the
        // transmitted codeword.)
        if s == 0 {
            return Some((Self::data(word), 0));
        }

        match Self::locs().get(s as usize) {
            // More than one error/unrecoverable error.
            Some(&0) | None => None,
            // Valid location means the error can be corrected.
            Some(&loc) => Some((Self::data(word ^ loc), 1)),
        }
    }
}

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

    #[test]
    fn test_standard() {
        let w = 0b10101010101;
        let e = standard::encode(w);
        assert_eq!(standard::decode(e^0b000000000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000000001).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000000010).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000000100).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000001000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000010000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000000100000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000001000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000010000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000000100000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000001000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000010000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b000100000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b001000000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b010000000000000).unwrap().0, w);
        assert_eq!(standard::decode(e^0b100000000000000).unwrap().0, w);

        for i in 0..1<<11 {
            assert_eq!(standard::decode(standard::encode(i)).unwrap().0, i);
        }
    }

    #[test]
    fn test_shortened() {
        let w = 0b110011;
        let e = shortened::encode(w);
        assert_eq!(shortened::decode(e ^ 0b0000000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000000001).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000000010).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000000100).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000001000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000010000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0000100000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0001000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0010000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b0100000000).unwrap().0, w);
        assert_eq!(shortened::decode(e ^ 0b1000000000).unwrap().0, w);

        for i in 0..1<<6 {
            assert_eq!(shortened::decode(shortened::encode(i)).unwrap().0, i);
        }
    }
}
<|endoftext|>


<commit_before>use cocoa::base::{YES, id, nil};
use cocoa::foundation::NSString;
use std::borrow::Cow;
use std::convert::AsRef;
use std::ffi::CStr;
#[cfg(feature = "time2")]
use std::time::Instant;
use sys::{MTLCommandBuffer, MTLCommandBufferStatus};
use {AsRaw, Drawable};

pub struct CommandBuffer(id);

unsafe impl Send for CommandBuffer {}
unsafe impl Sync for CommandBuffer {}

impl CommandBuffer {
    pub fn enqueue(&mut self) {
        unsafe { self.0.enqueue() }
    }

    pub fn commit(&mut self) -> Result<(), CommandBufferError> {
        unsafe {
            self.0.commit();
            let error = self.0.error();
            if error != nil { Err(CommandBufferError) } else { Ok(()) }
        }
    }

    pub fn present_drawable(&mut self, drawable: &mut Drawable) {
        unsafe { self.0.presentDrawable(*drawable.as_raw_mut()) }
    }

    #[cfg(feature = "time2")]
    pub fn present_drawable_at_time(&mut self, drawable: &mut Drawable, time: Instant) {
        unsafe { self.0.presentDrawable(*drawable.as_raw_mut(), time.elapsed().as_seconds()) }
    }

    pub fn present_drawable_at_time_secs(&mut self, drawable: &mut Drawable, time: f64) {
        unsafe { self.0.presentDrawable_atTime(*drawable.as_raw_mut(), time) }
    }

    pub fn wait_until_scheduled(&mut self) {
        unsafe { self.0.waitUntilScheduled() }
    }

    pub fn wait_until_completed(&mut self) {
        unsafe { self.0.waitUntilCompleted() }
    }

    pub fn status(&self) -> CommandBufferStatus {
        unsafe { self.0.status().into() }
    }

    pub fn has_retained_references(&self) -> bool {
        unsafe { self.0.retainedReferences() == YES }
    }

    pub fn set_label(&mut self, label: &AsRef<str>) {
        unsafe { MTLCommandBuffer::setLabel(self.0, NSString::alloc(nil).init_str(label.as_ref())) }
    }

    pub fn label(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(MTLCommandBuffer::label(self.0).UTF8String()).to_string_lossy() }
    }
}

impl_from_into_raw!(CommandBuffer, of protocol "MTLCommandBuffer");

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    pub enum CommandBufferStatus : MTLCommandBufferStatus {
        CommandBufferStatusNotEnqueued => MTLCommandBufferStatusNotEnqueued,
        CommandBufferStatusEnqueued => MTLCommandBufferStatusEnqueued,
        CommandBufferStatusCommitted => MTLCommandBufferStatusCommitted,
        CommandBufferStatusScheduled => MTLCommandBufferStatusScheduled,
        CommandBufferStatusCompleted => MTLCommandBufferStatusCompleted,
        CommandBufferStatusError => MTLCommandBufferStatusError
    }
}

pub struct CommandBufferError;
<commit_msg>Whitespace<commit_after>use cocoa::base::{YES, id, nil};
use cocoa::foundation::NSString;
use std::borrow::Cow;
use std::convert::AsRef;
use std::ffi::CStr;
#[cfg(feature = "time2")]
use std::time::Instant;
use sys::{MTLCommandBuffer, MTLCommandBufferStatus};
use {AsRaw, Drawable};

pub struct CommandBuffer(id);

unsafe impl Send for CommandBuffer {}
unsafe impl Sync for CommandBuffer {}

impl CommandBuffer {
    pub fn enqueue(&mut self) {
        unsafe { self.0.enqueue() }
    }

    pub fn commit(&mut self) -> Result<(), CommandBufferError> {
        unsafe {
            self.0.commit();
            let error = self.0.error();
            if error != nil { Err(CommandBufferError) } else { Ok(()) }
        }
    }

    pub fn present_drawable(&mut self, drawable: &mut Drawable) {
        unsafe { self.0.presentDrawable(*drawable.as_raw_mut()) }
    }

    #[cfg(feature = "time2")]
    pub fn present_drawable_at_time(&mut self, drawable: &mut Drawable, time: Instant) {
        unsafe { self.0.presentDrawable(*drawable.as_raw_mut(), time.elapsed().as_seconds()) }
    }

    pub fn present_drawable_at_time_secs(&mut self, drawable: &mut Drawable, time: f64) {
        unsafe { self.0.presentDrawable_atTime(*drawable.as_raw_mut(), time) }
    }

    pub fn wait_until_scheduled(&mut self) {
        unsafe { self.0.waitUntilScheduled() }
    }

    pub fn wait_until_completed(&mut self) {
        unsafe { self.0.waitUntilCompleted() }
    }

    pub fn status(&self) -> CommandBufferStatus {
        unsafe { self.0.status().into() }
    }

    pub fn has_retained_references(&self) -> bool {
        unsafe { self.0.retainedReferences() == YES }
    }

    pub fn set_label(&mut self, label: &AsRef<str>) {
        unsafe { MTLCommandBuffer::setLabel(self.0, NSString::alloc(nil).init_str(label.as_ref())) }
    }

    pub fn label(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(MTLCommandBuffer::label(self.0).UTF8String()).to_string_lossy() }
    }
}

impl_from_into_raw!(CommandBuffer, of protocol "MTLCommandBuffer");

convertible_enum! {
    #[derive(Clone, Copy, Eq, Hash, PartialEq)]
    pub enum CommandBufferStatus: MTLCommandBufferStatus {
        CommandBufferStatusNotEnqueued => MTLCommandBufferStatusNotEnqueued,
        CommandBufferStatusEnqueued => MTLCommandBufferStatusEnqueued,
        CommandBufferStatusCommitted => MTLCommandBufferStatusCommitted,
        CommandBufferStatusScheduled => MTLCommandBufferStatusScheduled,
        CommandBufferStatusCompleted => MTLCommandBufferStatusCompleted,
        CommandBufferStatusError => MTLCommandBufferStatusError
    }
}

pub struct CommandBufferError;
<|endoftext|>