<commit_before>//! Provides functions for escaping literals and identifiers for use
//! in SQL queries.
//!
//! Prefer parameterized queries where possible; see
//! [`Client::query`](crate::Client::query). Do not escape parameters.

#[cfg(test)]
mod test;

/// Escape a literal and surround result with single quotes. Not
/// recommended in most cases.
///
/// If input contains backslashes, result will be of the form `
/// E'...'` so it is safe to use regardless of the setting of
/// standard_conforming_strings.
pub fn escape_literal(input: &str) -> String {
    escape_internal(input, false)
}

/// Escape an identifier and surround result with double quotes.
pub fn escape_identifier(input: &str) -> String {
    escape_internal(input, true)
}

// Translation of PostgreSQL libpq's PQescapeInternal(). Does not
// require a connection because input string is known to be valid
// UTF-8.
//
// Escape arbitrary strings.  If as_ident is true, we escape the
// result as an identifier; if false, as a literal.  The result is
// returned in a newly allocated buffer.  If we fail due to an
// encoding violation or out of memory condition, we return NULL,
// storing an error message into conn.
fn escape_internal(input: &str, as_ident: bool) -> String {
    let mut num_backslashes = 0;
    let mut num_quotes = 0;
    let quote_char = if as_ident { '"' } else { '\'' };

    // Scan the string for characters that must be escaped.
    for ch in input.chars() {
        if ch == quote_char {
            num_quotes += 1;
        } else if ch == '\\' {
            num_backslashes += 1;
        }
    }

    // Allocate output String.
    let mut result_size = input.len() + num_quotes + 3; // two quotes, plus a NUL
    if !as_ident && num_backslashes > 0 {
        result_size += num_backslashes + 2;
    }

    let mut output = String::with_capacity(result_size);

    // If we are escaping a literal that contains backslashes, we use
    // the escape string syntax so that the result is correct under
    // either value of standard_conforming_strings.  We also emit a
    // leading space in this case, to guard against the possibility
    // that the result might be interpolated immediately following an
    // identifier.
    if !as_ident && num_backslashes > 0 {
        output.push(' ');
        output.push('E');
    }

    // Opening quote.
    output.push(quote_char);

    // Use fast path if possible.
    //
    // We've already verified that the input string is well-formed in
    // the current encoding.  If it contains no quotes and, in the
    // case of literal-escaping, no backslashes, then we can just copy
    // it directly to the output buffer, adding the necessary quotes.
    //
    // If not, we must rescan the input and process each character
    // individually.
    if num_quotes == 0 && (num_backslashes == 0 || as_ident) {
        output.push_str(input);
    } else {
        for ch in input.chars() {
            if ch == quote_char || (!as_ident && ch == '\\') {
                output.push(ch);
            }
            output.push(ch);
        }
    }

    output.push(quote_char);

    output
}
<commit_msg>Documentation fixup.<commit_after>//! Provides functions for escaping literals and identifiers for use
//! in SQL queries.
//!
//! Prefer parameterized queries where possible. Do not escape
//! parameters in a parameterized query.

#[cfg(test)]
mod test;

/// Escape a literal and surround result with single quotes. Not
/// recommended in most cases.
///
/// If input contains backslashes, result will be of the form `
/// E'...'` so it is safe to use regardless of the setting of
/// standard_conforming_strings.
pub fn escape_literal(input: &str) -> String {
    escape_internal(input, false)
}

/// Escape an identifier and surround result with double quotes.
pub fn escape_identifier(input: &str) -> String {
    escape_internal(input, true)
}

// Translation of PostgreSQL libpq's PQescapeInternal(). Does not
// require a connection because input string is known to be valid
// UTF-8.
//
// Escape arbitrary strings.  If as_ident is true, we escape the
// result as an identifier; if false, as a literal.  The result is
// returned in a newly allocated buffer.  If we fail due to an
// encoding violation or out of memory condition, we return NULL,
// storing an error message into conn.
fn escape_internal(input: &str, as_ident: bool) -> String {
    let mut num_backslashes = 0;
    let mut num_quotes = 0;
    let quote_char = if as_ident { '"' } else { '\'' };

    // Scan the string for characters that must be escaped.
    for ch in input.chars() {
        if ch == quote_char {
            num_quotes += 1;
        } else if ch == '\\' {
            num_backslashes += 1;
        }
    }

    // Allocate output String.
    let mut result_size = input.len() + num_quotes + 3; // two quotes, plus a NUL
    if !as_ident && num_backslashes > 0 {
        result_size += num_backslashes + 2;
    }

    let mut output = String::with_capacity(result_size);

    // If we are escaping a literal that contains backslashes, we use
    // the escape string syntax so that the result is correct under
    // either value of standard_conforming_strings.  We also emit a
    // leading space in this case, to guard against the possibility
    // that the result might be interpolated immediately following an
    // identifier.
    if !as_ident && num_backslashes > 0 {
        output.push(' ');
        output.push('E');
    }

    // Opening quote.
    output.push(quote_char);

    // Use fast path if possible.
    //
    // We've already verified that the input string is well-formed in
    // the current encoding.  If it contains no quotes and, in the
    // case of literal-escaping, no backslashes, then we can just copy
    // it directly to the output buffer, adding the necessary quotes.
    //
    // If not, we must rescan the input and process each character
    // individually.
    if num_quotes == 0 && (num_backslashes == 0 || as_ident) {
        output.push_str(input);
    } else {
        for ch in input.chars() {
            if ch == quote_char || (!as_ident && ch == '\\') {
                output.push(ch);
            }
            output.push(ch);
        }
    }

    output.push(quote_char);

    output
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::fmt::{self, Debug};
use std::io::Error;
use std::thread;
use std::time::{Duration, Instant};
use std::net::{Ipv6Addr, TcpStream};
use std::str::FromStr;
use std::time::{UNIX_EPOCH, SystemTime};

use multiqueue::{BroadcastReceiver, BroadcastSender};

use bitcrust_net::{BitcoinNetworkConnection, BitcoinNetworkError, NetAddr, Message, AddrMessage, Services,
                   VersionMessage};

use client_message::ClientMessage;
use config::Config;
#[cfg(test)]
mod tests {}

/// Peer bootstrapping follows the following sequence:
/// New client == -->
/// Remote peer == <--
///
/// --> Version
/// <-- Version
/// --> Verack
///
/// After the handshake, other communication can occur
pub struct Peer {
    config: Config,
    host: String,
    network_connection: BitcoinNetworkConnection,
    send_compact: bool,
    send_headers: bool,
    version_sent: bool,
    acked: bool,
    addrs: HashSet<NetAddr>,
    version: Option<VersionMessage>,
    sender: BroadcastSender<ClientMessage>,
    receiver: BroadcastReceiver<ClientMessage>,
    inbound_messages: usize,
    bad_messages: usize,
    peers_connected: u64,
    closed: bool,
    last_read: Instant,
    thread_speed: Duration,
}

impl Debug for Peer {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {

        write!(f,
               r"Peer {{
    host: {},
    send_compact: {},
    send_headers: {},
    version _sent: {},
    acked: {},
    addrs: Vec<NetAddr>,
    inbound_messages: {},
    bad_messages: {},
    peers_connected: {},
    closed: {},
    version: {:?}}}",
               self.host,
               self.send_compact,
               self.send_headers,
               self.version_sent,
               self.acked,
               self.inbound_messages,
               self.bad_messages,
               self.peers_connected,
               self.closed,
               self.version)
    }
}

impl Peer {
    pub fn new<T: Into<String>>(host: T,
                                sender: &BroadcastSender<ClientMessage>,
                                receiver: &BroadcastReceiver<ClientMessage>,
                                config: &Config)
                                -> Result<Peer, Error> {
        Peer::new_with_addrs(host, HashSet::with_capacity(1000), sender, receiver, config)
    }

    pub fn with_stream<T: Into<String>>(host: T,
                                        socket: TcpStream,
                                        sender: &BroadcastSender<ClientMessage>,
                                        receiver: &BroadcastReceiver<ClientMessage>,
                                        config: &Config) -> Result<Peer, Error> {
        let host = host.into();
        debug!("Initialized incoming peer with host: {}", host);
        let connection = BitcoinNetworkConnection::with_stream(host.clone(), socket)?;
        Ok(Peer {
            config: config.clone(),
            host: host,
            network_connection: connection,
            send_compact: false,
            send_headers: false,
            version_sent: false,
            acked: false,
            addrs: HashSet::with_capacity(1000),
            version: None,
            sender: sender.clone(),
            receiver: receiver.add_stream(),
            inbound_messages: 0,
            bad_messages: 0,
            peers_connected: 0,
            last_read: Instant::now(),
            closed: false,
            thread_speed: Duration::from_millis(250),
        })
    }

    pub fn new_with_addrs<T: Into<String>>(host: T,
                                           addrs: HashSet<NetAddr>,
                                           sender: &BroadcastSender<ClientMessage>,
                                           receiver: &BroadcastReceiver<ClientMessage>,
                                           config: &Config)
                                           -> Result<Peer, Error> {
        let host = host.into();
        let connection = BitcoinNetworkConnection::new(host.clone())?;
        Ok(Peer {
            config: config.clone(),
            host: host,
            network_connection: connection,
            send_compact: false,
            send_headers: false,
            version_sent: false,
            acked: false,
            addrs: addrs,
            version: None,
            sender: sender.clone(),
            receiver: receiver.add_stream(),
            inbound_messages: 0,
            bad_messages: 0,
            peers_connected: 0,
            last_read: Instant::now(),
            closed: false,
            thread_speed: Duration::from_millis(250),
        })
    }

    pub fn connected_peers(&mut self, peers: u64) {
        self.peers_connected = peers;
    }

    fn handle_message(&mut self, message: Message) {
        self.inbound_messages += 1;
        if self.version.is_none() {
            match message {
                Message::Version(_) => {}
                _ => {
                    debug!("Received {:?} prior to VERSION", message);
                    return;
                }
            }
        }
        match message {
            Message::Version(v) => {
                match self.version {
                    None => {
                        self.version = Some(v);
                        if self.version_sent {
                            let _ = self.send(Message::Verack);
                            if self.addrs.len() < 100 {
                                let _ = self.send(Message::GetAddr);
                            }
                        } else {
                            let _ = self.send(Peer::version());
                        }
                    }
                    Some(_) => {
                        let _ = self.send(Peer::version());
                    }
                }
            }
            Message::Ping(nonce) => {
                debug!("[{}] Ping", self.host);
                let _ = self.send(Message::Pong(nonce));
            }
            Message::SendCompact(msg) => {
                self.send_compact = msg.send_compact;
            }
            Message::Addr(addrs) => {
                let _ = self.sender.try_send(ClientMessage::Addrs(addrs.addrs.clone()));
                // Ensure that we don't realocate repeatedly in here
                self.addrs.reserve(addrs.addrs.len());
                for addr in addrs.addrs {
                    self.addrs.insert(addr);
                }
            }
            Message::GetAddr => {
                let msg = AddrMessage { addrs: self.addrs.iter().cloned().collect() };
                let _ = self.send(Message::Addr(msg));
            }
            Message::SendHeaders => {
                self.send_headers = true;
            }
            Message::GetHeaders(_msg) => {}
            Message::Verack => {
                self.acked = true;
            }
            Message::Inv(_inv) => {}
            Message::BitcrustPeerCountRequest(msg) => {
                if msg.valid(&self.config.key()) {
                    let count = self.peers_connected;
                    let _ = self.send(Message::BitcrustPeerCount(count));
                } else {
                    warn!("Message: {:?}", msg);
                    warn!("Invalid authenticated request!");
                    self.closed = true;
                }
            }
            Message::Unparsed(name, message) => {
                // Support for alert messages has been removed from bitcoin core in March 2016.
                // Read more at https://github.com/bitcoin/bitcoin/pull/7692
                if name != "alert" {
                    debug!("{} : Not handling {} yet ({:?})",
                           self.host,
                           name,
                           to_hex_string(&message))
                }
            }
            _ => {
                debug!("Not handling {:?} yet", message);
            }
        };
    }

    pub fn run(mut self, send_version: bool) -> thread::JoinHandle<()> {
        thread::spawn(move || {
            let mut last_cleanup = Instant::now();
            if send_version {
                let _ = self.send(Peer::version());
                self.version_sent = true;
            }

            loop {
                // Handle messages coming in from the network
                self.handle_remote_peer_messages();
                // Handle messages from other local peer connections
                self.handle_local_peer_message();
                // check if this is a bad peer
                if last_cleanup.elapsed() > self.thread_speed * 5 {
                    last_cleanup = Instant::now();
                    self.inbound_messages = match self.inbound_messages.checked_sub(1) {
                        Some(u) => u,
                        None => self.inbound_messages,
                    };
                    self.bad_messages = match self.bad_messages.checked_sub(2) {
                        Some(u) => u,
                        None => self.bad_messages,
                    };
                    if self.inbound_messages > 0 {
                        if self.bad_messages >= self.inbound_messages * 2 {
                            warn!("{} sent us {} requests, and {} bad ones",
                                  self.host,
                                  self.inbound_messages,
                                  self.bad_messages);
                            break;
                        }
                    }
                }
                if self.closed {
                    break;
                }
            }
            let _ = self.sender.try_send(ClientMessage::Closing(self.host));
        })

    }

    fn handle_remote_peer_messages(&mut self) {
        if self.last_read.elapsed() < self.thread_speed {
            let time = self.thread_speed - self.last_read.elapsed();
            thread::sleep(time);
        }
        self.last_read = Instant::now();
        while let Some(msg) = self.network_connection.try_recv() {
            match msg {
                Ok(msg) => self.handle_message(msg),
                Err(e) => {
                    match e {
                        BitcoinNetworkError::BadBytes => {
                            self.bad_messages += 1;
                        }
                        BitcoinNetworkError::Closed => self.closed = true,
                        BitcoinNetworkError::ReadTimeout => {}
                    }
                    return
                },
            }

        }
    }

    fn handle_local_peer_message(&mut self) {
        while let Ok(msg) = self.receiver.try_recv() {
            match msg {
                ClientMessage::Addrs(addrs) => {
                    // We only want to send `Addr`s that we don't think the remote
                    // peer knows about already
                    let mut addrs_to_send = Vec::with_capacity(addrs.len());
                    for addr in addrs {
                        if !self.addrs.insert(addr.clone()) {
                            addrs_to_send.push(addr);
                        }
                    }
                    let _ = self.send(Message::Addr(AddrMessage { addrs: addrs_to_send }));
                }
                ClientMessage::PeersConnected(count) => {
                    self.peers_connected = count;
                }
                ClientMessage::Closing(_) => {}
                // _ => info!("Ignoring msg: {:?}", msg),
            }
        }
    }

    fn send(&mut self, message: Message) -> Result<(), Error> {
        self.network_connection.try_send(message)
    }

    pub fn version() -> Message {
        Message::Version(VersionMessage {
            version: 70015,
            services: Services::from(1),
            timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64,
            addr_recv: Peer::addr(Ipv6Addr::from_str("::ffff:127.0.0.1").unwrap(), 8333, None),
            addr_send: Peer::addr(Ipv6Addr::from_str("::ffff:127.0.0.1").unwrap(), 8333, None),
            nonce: 1,
            user_agent: "/bitcrust:0.1.0/".into(),
            start_height: 0,
            relay: false,
        })
    }

    fn addr(ip: Ipv6Addr, port: u16, time: Option<u32>) -> NetAddr {
        NetAddr {
            time: time,
            services: Services::from(1),
            ip: ip,
            port: port,
        }
    }
}

fn to_hex_string(bytes: &[u8]) -> String {
    let strs: Vec<String> = bytes.iter()
        .map(|b| format!("{:02X}", b))
        .collect();
    strs.join(" ")
}
<commit_msg>Add the missing message types to the `Peer`<commit_after>use std::collections::HashSet;
use std::fmt::{self, Debug};
use std::io::Error;
use std::thread;
use std::time::{Duration, Instant};
use std::net::{Ipv6Addr, TcpStream};
use std::str::FromStr;
use std::time::{UNIX_EPOCH, SystemTime};

use multiqueue::{BroadcastReceiver, BroadcastSender};

use bitcrust_net::{BitcoinNetworkConnection, BitcoinNetworkError, NetAddr, Message, AddrMessage, Services,
                   VersionMessage};

use client_message::ClientMessage;
use config::Config;
#[cfg(test)]
mod tests {}

/// Peer bootstrapping follows the following sequence:
/// New client == -->
/// Remote peer == <--
///
/// --> Version
/// <-- Version
/// --> Verack
///
/// After the handshake, other communication can occur
pub struct Peer {
    config: Config,
    host: String,
    network_connection: BitcoinNetworkConnection,
    send_compact: bool,
    send_headers: bool,
    version_sent: bool,
    acked: bool,
    addrs: HashSet<NetAddr>,
    version: Option<VersionMessage>,
    sender: BroadcastSender<ClientMessage>,
    receiver: BroadcastReceiver<ClientMessage>,
    inbound_messages: usize,
    bad_messages: usize,
    peers_connected: u64,
    closed: bool,
    last_read: Instant,
    thread_speed: Duration,
}

impl Debug for Peer {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {

        write!(f,
               r"Peer {{
    host: {},
    send_compact: {},
    send_headers: {},
    version _sent: {},
    acked: {},
    addrs: Vec<NetAddr>,
    inbound_messages: {},
    bad_messages: {},
    peers_connected: {},
    closed: {},
    version: {:?}}}",
               self.host,
               self.send_compact,
               self.send_headers,
               self.version_sent,
               self.acked,
               self.inbound_messages,
               self.bad_messages,
               self.peers_connected,
               self.closed,
               self.version)
    }
}

impl Peer {
    pub fn new<T: Into<String>>(host: T,
                                sender: &BroadcastSender<ClientMessage>,
                                receiver: &BroadcastReceiver<ClientMessage>,
                                config: &Config)
                                -> Result<Peer, Error> {
        Peer::new_with_addrs(host, HashSet::with_capacity(1000), sender, receiver, config)
    }

    pub fn with_stream<T: Into<String>>(host: T,
                                        socket: TcpStream,
                                        sender: &BroadcastSender<ClientMessage>,
                                        receiver: &BroadcastReceiver<ClientMessage>,
                                        config: &Config) -> Result<Peer, Error> {
        let host = host.into();
        debug!("Initialized incoming peer with host: {}", host);
        let connection = BitcoinNetworkConnection::with_stream(host.clone(), socket)?;
        Ok(Peer {
            config: config.clone(),
            host: host,
            network_connection: connection,
            send_compact: false,
            send_headers: false,
            version_sent: false,
            acked: false,
            addrs: HashSet::with_capacity(1000),
            version: None,
            sender: sender.clone(),
            receiver: receiver.add_stream(),
            inbound_messages: 0,
            bad_messages: 0,
            peers_connected: 0,
            last_read: Instant::now(),
            closed: false,
            thread_speed: Duration::from_millis(250),
        })
    }

    pub fn new_with_addrs<T: Into<String>>(host: T,
                                           addrs: HashSet<NetAddr>,
                                           sender: &BroadcastSender<ClientMessage>,
                                           receiver: &BroadcastReceiver<ClientMessage>,
                                           config: &Config)
                                           -> Result<Peer, Error> {
        let host = host.into();
        let connection = BitcoinNetworkConnection::new(host.clone())?;
        Ok(Peer {
            config: config.clone(),
            host: host,
            network_connection: connection,
            send_compact: false,
            send_headers: false,
            version_sent: false,
            acked: false,
            addrs: addrs,
            version: None,
            sender: sender.clone(),
            receiver: receiver.add_stream(),
            inbound_messages: 0,
            bad_messages: 0,
            peers_connected: 0,
            last_read: Instant::now(),
            closed: false,
            thread_speed: Duration::from_millis(250),
        })
    }

    pub fn connected_peers(&mut self, peers: u64) {
        self.peers_connected = peers;
    }

    fn handle_message(&mut self, message: Message) {
        self.inbound_messages += 1;
        if self.version.is_none() {
            match message {
                Message::Version(_) => {}
                _ => {
                    debug!("Received {:?} prior to VERSION", message);
                    return;
                }
            }
        }
        match message {
            Message::Version(v) => {
                match self.version {
                    None => {
                        self.version = Some(v);
                        if self.version_sent {
                            let _ = self.send(Message::Verack);
                            if self.addrs.len() < 100 {
                                let _ = self.send(Message::GetAddr);
                            }
                        } else {
                            let _ = self.send(Peer::version());
                        }
                    }
                    Some(_) => {
                        let _ = self.send(Peer::version());
                    }
                }
            }
            Message::Verack => {
                self.acked = true;
            }
            Message::FeeFilter(_fee) => {}
            Message::Ping(nonce) => {
                debug!("[{}] Ping", self.host);
                let _ = self.send(Message::Pong(nonce));
            }
            Message::Pong(_nonce) => {}
            Message::SendCompact(msg) => {
                self.send_compact = msg.send_compact;
            }
            Message::Addr(addrs) => {
                let _ = self.sender.try_send(ClientMessage::Addrs(addrs.addrs.clone()));
                // Ensure that we don't realocate repeatedly in here
                self.addrs.reserve(addrs.addrs.len());
                for addr in addrs.addrs {
                    self.addrs.insert(addr);
                }
            }
            Message::GetAddr => {
                let msg = AddrMessage { addrs: self.addrs.iter().cloned().collect() };
                let _ = self.send(Message::Addr(msg));
            }
            Message::SendHeaders => {
                self.send_headers = true;
            }
            Message::GetHeaders(_msg) => {}
            Message::Header(_header) => {}
            Message::Inv(_inv) => {}
            Message::Tx(_transaction) => {}
            Message::GetBlocks(_get_blocks) => {}
            Message::GetData(_data) => {}
            Message::Block(_block) => {}
            Message::NotFound(_not_found) => {}
            Message::Unparsed(name, message) => {
                // Support for alert messages has been removed from bitcoin core in March 2016.
                // Read more at https://github.com/bitcoin/bitcoin/pull/7692
                if name != "alert" {
                    debug!("{} : Not handling {} yet ({:?})",
                           self.host,
                           name,
                           to_hex_string(&message))
                }
            }
            /// Bitcrust Specific Messages
            Message::BitcrustPeerCountRequest(msg) => {
                if msg.valid(&self.config.key()) {
                    let count = self.peers_connected;
                    let _ = self.send(Message::BitcrustPeerCount(count));
                } else {
                    warn!("Message: {:?}", msg);
                    warn!("Invalid authenticated request!");
                    self.closed = true;
                }
            }
            Message::BitcrustPeerCount(_count) => {}
            _ => {
                debug!("Not handling {:?} yet", message);
            }
        };
    }

    pub fn run(mut self, send_version: bool) -> thread::JoinHandle<()> {
        thread::spawn(move || {
            let mut last_cleanup = Instant::now();
            if send_version {
                let _ = self.send(Peer::version());
                self.version_sent = true;
            }

            loop {
                // Handle messages coming in from the network
                self.handle_remote_peer_messages();
                // Handle messages from other local peer connections
                self.handle_local_peer_message();
                // check if this is a bad peer
                if last_cleanup.elapsed() > self.thread_speed * 5 {
                    last_cleanup = Instant::now();
                    self.inbound_messages = match self.inbound_messages.checked_sub(1) {
                        Some(u) => u,
                        None => self.inbound_messages,
                    };
                    self.bad_messages = match self.bad_messages.checked_sub(2) {
                        Some(u) => u,
                        None => self.bad_messages,
                    };
                    if self.inbound_messages > 0 {
                        if self.bad_messages >= self.inbound_messages * 2 {
                            warn!("{} sent us {} requests, and {} bad ones",
                                  self.host,
                                  self.inbound_messages,
                                  self.bad_messages);
                            break;
                        }
                    }
                }
                if self.closed {
                    break;
                }
            }
            let _ = self.sender.try_send(ClientMessage::Closing(self.host));
        })

    }

    fn handle_remote_peer_messages(&mut self) {
        if self.last_read.elapsed() < self.thread_speed {
            let time = self.thread_speed - self.last_read.elapsed();
            thread::sleep(time);
        }
        self.last_read = Instant::now();
        while let Some(msg) = self.network_connection.try_recv() {
            match msg {
                Ok(msg) => self.handle_message(msg),
                Err(e) => {
                    match e {
                        BitcoinNetworkError::BadBytes => {
                            self.bad_messages += 1;
                        }
                        BitcoinNetworkError::Closed => self.closed = true,
                        BitcoinNetworkError::ReadTimeout => {}
                    }
                    return
                },
            }

        }
    }

    fn handle_local_peer_message(&mut self) {
        while let Ok(msg) = self.receiver.try_recv() {
            match msg {
                ClientMessage::Addrs(addrs) => {
                    // We only want to send `Addr`s that we don't think the remote
                    // peer knows about already
                    let mut addrs_to_send = Vec::with_capacity(addrs.len());
                    for addr in addrs {
                        if !self.addrs.insert(addr.clone()) {
                            addrs_to_send.push(addr);
                        }
                    }
                    let _ = self.send(Message::Addr(AddrMessage { addrs: addrs_to_send }));
                }
                ClientMessage::PeersConnected(count) => {
                    self.peers_connected = count;
                }
                ClientMessage::Closing(_) => {}
                // _ => info!("Ignoring msg: {:?}", msg),
            }
        }
    }

    fn send(&mut self, message: Message) -> Result<(), Error> {
        self.network_connection.try_send(message)
    }

    pub fn version() -> Message {
        Message::Version(VersionMessage {
            version: 70015,
            services: Services::from(1),
            timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64,
            addr_recv: Peer::addr(Ipv6Addr::from_str("::ffff:127.0.0.1").unwrap(), 8333, None),
            addr_send: Peer::addr(Ipv6Addr::from_str("::ffff:127.0.0.1").unwrap(), 8333, None),
            nonce: 1,
            user_agent: "/bitcrust:0.1.0/".into(),
            start_height: 0,
            relay: false,
        })
    }

    fn addr(ip: Ipv6Addr, port: u16, time: Option<u32>) -> NetAddr {
        NetAddr {
            time: time,
            services: Services::from(1),
            ip: ip,
            port: port,
        }
    }
}

fn to_hex_string(bytes: &[u8]) -> String {
    let strs: Vec<String> = bytes.iter()
        .map(|b| format!("{:02X}", b))
        .collect();
    strs.join(" ")
}
<|endoftext|>


<commit_before>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, ItemTrait};

#[test]
fn test_macro_variable_attr() {
    // mimics the token stream corresponding to `$attr fn f() {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
        TokenTree::Ident(Ident::new("fn", Span::call_site())),
        TokenTree::Ident(Ident::new("f", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Fn {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "test",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        vis: Inherited,
        sig: Signature {
            ident: "f",
            generics: Generics,
            output: Default,
        },
        block: Block,
    }
    "###);
}

#[test]
fn test_negative_impl() {
    // Rustc parses all of the following.

    #[cfg(any())]
    impl ! {}
    let tokens = quote! {
        impl ! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Type::Never,
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !Trait {}
    let tokens = quote! {
        impl !Trait {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! Trait`),
    }
    "###);

    #[cfg(any())]
    impl !Trait for T {}
    let tokens = quote! {
        impl !Trait for T {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            Some,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "T",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !! {}
    let tokens = quote! {
        impl !! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! !`),
    }
    "###);
}

#[test]
fn test_macro_variable_impl() {
    // mimics the token stream corresponding to `impl $trait for $ty {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("impl", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
        TokenTree::Ident(Ident::new("for", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            None,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Group {
            elem: Type::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Type",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_supertraits() {
    // Rustc parses all of the following.

    #[rustfmt::skip]
    let tokens = quote!(trait Trait where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized + where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}

#[test]
fn test_type_empty_bounds() {
    #[rustfmt::skip]
    let tokens = quote! {
        trait Foo {
            type Bar: ;
        }
    };

    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Foo",
        generics: Generics,
        items: [
            TraitItem::Type {
                ident: "Bar",
                generics: Generics,
                colon_token: Some,
            },
        ],
    }
    "###);
}

#[test]
fn test_impl_visibility() {
    let tokens = quote! {
        pub default unsafe impl union {}
    };

    snapshot!(tokens as Item, @"Verbatim(`pub default unsafe impl union { }`)");
}
<commit_msg>Add impl type parameter defaults test<commit_after>#[macro_use]
mod macros;

use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
use quote::quote;
use std::iter::FromIterator;
use syn::{Item, ItemTrait};

#[test]
fn test_macro_variable_attr() {
    // mimics the token stream corresponding to `$attr fn f() {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Group(Group::new(Delimiter::None, quote! { #[test] })),
        TokenTree::Ident(Ident::new("fn", Span::call_site())),
        TokenTree::Ident(Ident::new("f", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Fn {
        attrs: [
            Attribute {
                style: Outer,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "test",
                            arguments: None,
                        },
                    ],
                },
                tokens: TokenStream(``),
            },
        ],
        vis: Inherited,
        sig: Signature {
            ident: "f",
            generics: Generics,
            output: Default,
        },
        block: Block,
    }
    "###);
}

#[test]
fn test_negative_impl() {
    // Rustc parses all of the following.

    #[cfg(any())]
    impl ! {}
    let tokens = quote! {
        impl ! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Type::Never,
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !Trait {}
    let tokens = quote! {
        impl !Trait {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! Trait`),
    }
    "###);

    #[cfg(any())]
    impl !Trait for T {}
    let tokens = quote! {
        impl !Trait for T {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            Some,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Path {
            path: Path {
                segments: [
                    PathSegment {
                        ident: "T",
                        arguments: None,
                    },
                ],
            },
        },
    }
    "###);

    #[cfg(any())]
    #[rustfmt::skip]
    impl !! {}
    let tokens = quote! {
        impl !! {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        self_ty: Verbatim(`! !`),
    }
    "###);
}

#[test]
fn test_macro_variable_impl() {
    // mimics the token stream corresponding to `impl $trait for $ty {}`
    let tokens = TokenStream::from_iter(vec![
        TokenTree::Ident(Ident::new("impl", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Trait))),
        TokenTree::Ident(Ident::new("for", Span::call_site())),
        TokenTree::Group(Group::new(Delimiter::None, quote!(Type))),
        TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
    ]);

    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics,
        trait_: Some((
            None,
            Path {
                segments: [
                    PathSegment {
                        ident: "Trait",
                        arguments: None,
                    },
                ],
            },
        )),
        self_ty: Type::Group {
            elem: Type::Path {
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Type",
                            arguments: None,
                        },
                    ],
                },
            },
        },
    }
    "###);
}

#[test]
fn test_supertraits() {
    // Rustc parses all of the following.

    #[rustfmt::skip]
    let tokens = quote!(trait Trait where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);

    #[rustfmt::skip]
    let tokens = quote!(trait Trait: Sized + where {});
    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Trait",
        generics: Generics {
            where_clause: Some(WhereClause),
        },
        colon_token: Some,
        supertraits: [
            Trait(TraitBound {
                modifier: None,
                path: Path {
                    segments: [
                        PathSegment {
                            ident: "Sized",
                            arguments: None,
                        },
                    ],
                },
            }),
        ],
    }
    "###);
}

#[test]
fn test_type_empty_bounds() {
    #[rustfmt::skip]
    let tokens = quote! {
        trait Foo {
            type Bar: ;
        }
    };

    snapshot!(tokens as ItemTrait, @r###"
    ItemTrait {
        vis: Inherited,
        ident: "Foo",
        generics: Generics,
        items: [
            TraitItem::Type {
                ident: "Bar",
                generics: Generics,
                colon_token: Some,
            },
        ],
    }
    "###);
}

#[test]
fn test_impl_visibility() {
    let tokens = quote! {
        pub default unsafe impl union {}
    };

    snapshot!(tokens as Item, @"Verbatim(`pub default unsafe impl union { }`)");
}

#[test]
fn test_impl_type_parameter_defaults() {
    #[cfg(any())]
    impl<T = ()> () {}
    let tokens = quote! {
        impl<T = ()> () {}
    };
    snapshot!(tokens as Item, @r###"
    Item::Impl {
        generics: Generics {
            lt_token: Some,
            params: [
                Type(TypeParam {
                    ident: "T",
                    eq_token: Some,
                    default: Some(Type::Tuple),
                }),
            ],
            gt_token: Some,
        },
        self_ty: Type::Tuple,
    }"###);
}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! Generating numbers between two others.

// this is surprisingly complicated to be both generic & correct

use core::prelude::*;
use core::num::Bounded;

use Rng;
use distributions::{Sample, IndependentSample};

/// Sample values uniformly between two bounds.
///
/// This gives a uniform distribution (assuming the RNG used to sample
/// it is itself uniform & the `SampleRange` implementation for the
/// given type is correct), even for edge cases like `low = 0u8`,
/// `high = 170u8`, for which a naive modulo operation would return
/// numbers less than 85 with double the probability to those greater
/// than 85.
///
/// Types should attempt to sample in `[low, high)`, i.e., not
/// including `high`, but this may be very difficult. All the
/// primitive integer types satisfy this property, and the float types
/// normally satisfy it, but rounding may mean `high` can occur.
///
/// # Example
///
/// ```rust
/// use std::rand::distributions::{IndependentSample, Range};
///
/// fn main() {
///     let between = Range::new(10u, 10000u);
///     let mut rng = std::rand::task_rng();
///     let mut sum = 0;
///     for _ in range(0u, 1000) {
///         sum += between.ind_sample(&mut rng);
///     }
///     println!("{}", sum);
/// }
/// ```
pub struct Range<X> {
    low: X,
    range: X,
    accept_zone: X
}

impl<X: SampleRange + PartialOrd> Range<X> {
    /// Create a new `Range` instance that samples uniformly from
    /// `[low, high)`. Fails if `low >= high`.
    pub fn new(low: X, high: X) -> Range<X> {
        assert!(low < high, "Range::new called with `low >= high`");
        SampleRange::construct_range(low, high)
    }
}

impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
    #[inline]
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
}
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
        SampleRange::sample_range(self, rng)
    }
}

/// The helper trait for types that have a sensible way to sample
/// uniformly between two values. This should not be used directly,
/// and is only to facilitate `Range`.
pub trait SampleRange {
    /// Construct the `Range` object that `sample_range`
    /// requires. This should not ever be called directly, only via
    /// `Range::new`, which will check that `low < high`, so this
    /// function doesn't have to repeat the check.
    fn construct_range(low: Self, high: Self) -> Range<Self>;

    /// Sample a value from the given `Range` with the given `Rng` as
    /// a source of randomness.
    fn sample_range<R: Rng>(r: &Range<Self>, rng: &mut R) -> Self;
}

macro_rules! integer_impl {
    ($ty:ty, $unsigned:ty) => {
        impl SampleRange for $ty {
            // we play free and fast with unsigned vs signed here
            // (when $ty is signed), but that's fine, since the
            // contract of this macro is for $ty and $unsigned to be
            // "bit-equal", so casting between them is a no-op & a
            // bijection.

            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                let range = high as $unsigned - low as $unsigned;
                let unsigned_max: $unsigned = Bounded::max_value();

                // this is the largest number that fits into $unsigned
                // that `range` divides evenly, so, if we've sampled
                // `n` uniformly from this region, then `n % range` is
                // uniform in [0, range)
                let zone = unsigned_max - unsigned_max % range;

                Range {
                    low: low,
                    range: range as $ty,
                    accept_zone: zone as $ty
                }
            }
            #[inline]
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                loop {
                    // rejection sample
                    let v = rng.gen::<$unsigned>();
                    // until we find something that fits into the
                    // region which r.range evenly divides (this will
                    // be uniformly distributed)
                    if v < r.accept_zone as $unsigned {
                        // and return it, with some adjustments
                        return r.low + (v % r.range as $unsigned) as $ty;
                    }
                }
            }
        }
    }
}

integer_impl! { i8, u8 }
integer_impl! { i16, u16 }
integer_impl! { i32, u32 }
integer_impl! { i64, u64 }
integer_impl! { int, uint }
integer_impl! { u8, u8 }
integer_impl! { u16, u16 }
integer_impl! { u32, u32 }
integer_impl! { u64, u64 }
integer_impl! { uint, uint }

macro_rules! float_impl {
    ($ty:ty) => {
        impl SampleRange for $ty {
            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                Range {
                    low: low,
                    range: high - low,
                    accept_zone: 0.0 // unused
                }
            }
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                r.low + r.range * rng.gen()
            }
        }
    }
}

float_impl! { f32 }
float_impl! { f64 }

#[cfg(test)]
mod tests {
    use std::prelude::*;
    use distributions::{Sample, IndependentSample};
    use super::Range;
    use std::num::Bounded;

    #[should_fail]
    #[test]
    fn test_range_bad_limits_equal() {
        Range::new(10i, 10i);
    }
    #[should_fail]
    #[test]
    fn test_range_bad_limits_flipped() {
        Range::new(10i, 5i);
    }

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng();
        macro_rules! t (
            ($($ty:ty),*) => {{
                $(
                   let v: &[($ty, $ty)] = [(0, 10),
                                           (10, 127),
                                           (Bounded::min_value(), Bounded::max_value())];
                   for &(low, high) in v.iter() {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in range(0u, 1000) {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        );
        t!(i8, i16, i32, i64, int,
           u8, u16, u32, u64, uint)
    }

    #[test]
    fn test_floats() {
        let mut rng = ::test::rng();
        macro_rules! t (
            ($($ty:ty),*) => {{
                $(
                   let v: &[($ty, $ty)] = [(0.0, 100.0),
                                           (-1e35, -1e25),
                                           (1e-35, 1e-25),
                                           (-1e35, 1e35)];
                   for &(low, high) in v.iter() {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in range(0u, 1000) {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        );

        t!(f32, f64)
    }

}
<commit_msg>Deprecate Bounded trait<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

//! Generating numbers between two others.

// this is surprisingly complicated to be both generic & correct

use core::prelude::*;

use Rng;
use distributions::{Sample, IndependentSample};

/// Sample values uniformly between two bounds.
///
/// This gives a uniform distribution (assuming the RNG used to sample
/// it is itself uniform & the `SampleRange` implementation for the
/// given type is correct), even for edge cases like `low = 0u8`,
/// `high = 170u8`, for which a naive modulo operation would return
/// numbers less than 85 with double the probability to those greater
/// than 85.
///
/// Types should attempt to sample in `[low, high)`, i.e., not
/// including `high`, but this may be very difficult. All the
/// primitive integer types satisfy this property, and the float types
/// normally satisfy it, but rounding may mean `high` can occur.
///
/// # Example
///
/// ```rust
/// use std::rand::distributions::{IndependentSample, Range};
///
/// fn main() {
///     let between = Range::new(10u, 10000u);
///     let mut rng = std::rand::task_rng();
///     let mut sum = 0;
///     for _ in range(0u, 1000) {
///         sum += between.ind_sample(&mut rng);
///     }
///     println!("{}", sum);
/// }
/// ```
pub struct Range<X> {
    low: X,
    range: X,
    accept_zone: X
}

impl<X: SampleRange + PartialOrd> Range<X> {
    /// Create a new `Range` instance that samples uniformly from
    /// `[low, high)`. Fails if `low >= high`.
    pub fn new(low: X, high: X) -> Range<X> {
        assert!(low < high, "Range::new called with `low >= high`");
        SampleRange::construct_range(low, high)
    }
}

impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
    #[inline]
    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
}
impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
        SampleRange::sample_range(self, rng)
    }
}

/// The helper trait for types that have a sensible way to sample
/// uniformly between two values. This should not be used directly,
/// and is only to facilitate `Range`.
pub trait SampleRange {
    /// Construct the `Range` object that `sample_range`
    /// requires. This should not ever be called directly, only via
    /// `Range::new`, which will check that `low < high`, so this
    /// function doesn't have to repeat the check.
    fn construct_range(low: Self, high: Self) -> Range<Self>;

    /// Sample a value from the given `Range` with the given `Rng` as
    /// a source of randomness.
    fn sample_range<R: Rng>(r: &Range<Self>, rng: &mut R) -> Self;
}

macro_rules! integer_impl {
    ($ty:ty, $unsigned:ty) => {
        impl SampleRange for $ty {
            // we play free and fast with unsigned vs signed here
            // (when $ty is signed), but that's fine, since the
            // contract of this macro is for $ty and $unsigned to be
            // "bit-equal", so casting between them is a no-op & a
            // bijection.

            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                let range = high as $unsigned - low as $unsigned;
                let unsigned_max: $unsigned = Int::max_value();

                // this is the largest number that fits into $unsigned
                // that `range` divides evenly, so, if we've sampled
                // `n` uniformly from this region, then `n % range` is
                // uniform in [0, range)
                let zone = unsigned_max - unsigned_max % range;

                Range {
                    low: low,
                    range: range as $ty,
                    accept_zone: zone as $ty
                }
            }
            #[inline]
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                loop {
                    // rejection sample
                    let v = rng.gen::<$unsigned>();
                    // until we find something that fits into the
                    // region which r.range evenly divides (this will
                    // be uniformly distributed)
                    if v < r.accept_zone as $unsigned {
                        // and return it, with some adjustments
                        return r.low + (v % r.range as $unsigned) as $ty;
                    }
                }
            }
        }
    }
}

integer_impl! { i8, u8 }
integer_impl! { i16, u16 }
integer_impl! { i32, u32 }
integer_impl! { i64, u64 }
integer_impl! { int, uint }
integer_impl! { u8, u8 }
integer_impl! { u16, u16 }
integer_impl! { u32, u32 }
integer_impl! { u64, u64 }
integer_impl! { uint, uint }

macro_rules! float_impl {
    ($ty:ty) => {
        impl SampleRange for $ty {
            fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
                Range {
                    low: low,
                    range: high - low,
                    accept_zone: 0.0 // unused
                }
            }
            fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
                r.low + r.range * rng.gen()
            }
        }
    }
}

float_impl! { f32 }
float_impl! { f64 }

#[cfg(test)]
mod tests {
    use std::prelude::*;
    use distributions::{Sample, IndependentSample};
    use super::Range;

    #[should_fail]
    #[test]
    fn test_range_bad_limits_equal() {
        Range::new(10i, 10i);
    }
    #[should_fail]
    #[test]
    fn test_range_bad_limits_flipped() {
        Range::new(10i, 5i);
    }

    #[test]
    fn test_integers() {
        let mut rng = ::test::rng();
        macro_rules! t (
            ($($ty:ty),*) => {{
                $(
                   let v: &[($ty, $ty)] = [(0, 10),
                                           (10, 127),
                                           (Int::min_value(), Int::max_value())];
                   for &(low, high) in v.iter() {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in range(0u, 1000) {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        );
        t!(i8, i16, i32, i64, int,
           u8, u16, u32, u64, uint)
    }

    #[test]
    fn test_floats() {
        let mut rng = ::test::rng();
        macro_rules! t (
            ($($ty:ty),*) => {{
                $(
                   let v: &[($ty, $ty)] = [(0.0, 100.0),
                                           (-1e35, -1e25),
                                           (1e-35, 1e-25),
                                           (-1e35, 1e35)];
                   for &(low, high) in v.iter() {
                        let mut sampler: Range<$ty> = Range::new(low, high);
                        for _ in range(0u, 1000) {
                            let v = sampler.sample(&mut rng);
                            assert!(low <= v && v < high);
                            let v = sampler.ind_sample(&mut rng);
                            assert!(low <= v && v < high);
                        }
                    }
                 )*
            }}
        );

        t!(f32, f64)
    }

}
<|endoftext|>


<commit_before>#[legacy_exports];
export FreeTypeNativeFont, with_test_native_font, create;

use font::{FontMetrics, FractionalPixel};

use au = gfx::geometry;
use util::*;
use vec_as_buf = vec::as_imm_buf;
use ptr::{addr_of, null};
use cast::reinterpret_cast;
use glyph::GlyphIndex;
use font::FontMetrics;
use azure::freetype;
use freetype::{ FT_Error, FT_Library, FT_Face, FT_Long, FT_ULong, FT_UInt, FT_GlyphSlot };
use freetype::bindgen::{
    FT_Init_FreeType,
    FT_Done_FreeType,
    FT_New_Memory_Face,
    FT_Done_Face,
    FT_Get_Char_Index,
    FT_Load_Glyph,
    FT_Set_Char_Size
};

fn float_to_fixed_ft(f: float) -> i32 {
    float_to_fixed(6, f)
}

fn fixed_to_float_ft(f: i32) -> float {
    fixed_to_float(6, f)
}

struct FreeTypeNativeFont {
    /// The font binary. This must stay valid for the lifetime of the font
    buf: @~[u8],
    face: FT_Face,

    drop {
        assert self.face.is_not_null();
        if !FT_Done_Face(self.face).succeeded() {
            fail ~"FT_Done_Face failed";
        }
    }
}

fn FreeTypeNativeFont(face: FT_Face, buf: @~[u8]) -> FreeTypeNativeFont {
    assert face.is_not_null();
    FreeTypeNativeFont { buf: buf, face: face }
}

impl FreeTypeNativeFont {

    fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
        assert self.face.is_not_null();
        let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
        return if idx != 0 as FT_UInt {
            Some(idx as GlyphIndex)
        } else {
            debug!("Invalid codepoint: %?", codepoint);
            None
        };
    }

    // FIXME: What unit is this returning? Let's have a custom type
    fn glyph_h_advance(glyph: GlyphIndex) -> Option<FractionalPixel> {
        assert self.face.is_not_null();
        let res =  FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
        if res.succeeded() {
            unsafe {
                let void_glyph = (*self.face).glyph;
                let slot: FT_GlyphSlot = reinterpret_cast(&void_glyph);
                assert slot.is_not_null();
                debug!("metrics: %?", (*slot).metrics);
                let advance = (*slot).metrics.horiAdvance;
                debug!("h_advance for %? is %?", glyph, advance);
                let advance = advance as i32;
                return Some(fixed_to_float_ft(advance) as FractionalPixel);
            }
        } else {
            debug!("Unable to load glyph %?. reason: %?", glyph, res);
            return None;
        }
    }

    fn get_metrics() -> FontMetrics {
        /* TODO: complete me (Issue #76) */
        return FontMetrics {
            underline_size:   au::from_pt(0.0),
            underline_offset: au::from_pt(0.0),
            leading:          au::from_pt(0.0),
            x_height:         au::from_pt(0.0),
            em_size:          au::from_pt(0.0),
            ascent:           au::from_pt(0.0),
            descent:          au::from_pt(0.0),
            max_advance:      au::from_pt(0.0)
        }
    }
}

pub fn create(lib: &FT_Library, buf: @~[u8]) -> Result<FreeTypeNativeFont, ()> {
    assert lib.is_not_null();
    let face: FT_Face = null();
    return vec_as_buf(*buf, |cbuf, _len| {
           if FT_New_Memory_Face(*lib, cbuf, (*buf).len() as FT_Long,
                                 0 as FT_Long, addr_of(&face)).succeeded() {
               // FIXME: These values are placeholders
               let res = FT_Set_Char_Size(face, 0, 20*64, 0, 72);
               if !res.succeeded() { fail ~"unable to set font char size" }
               Ok(FreeTypeNativeFont(face, buf))
           } else {
               Err(())
           }
    })
}

trait FTErrorMethods {
    fn succeeded() -> bool;
}

impl FT_Error : FTErrorMethods {
    fn succeeded() -> bool { self == 0 as FT_Error }
}

fn with_test_native_font(f: fn@(nf: &NativeFont)) {
    use font::test_font_bin;
    use unwrap_result = result::unwrap;

    with_lib(|lib| {
        let buf = @test_font_bin();
        let font = unwrap_result(create(lib, move buf));
        f(&font);
    })
}

fn with_lib(f: fn@((&FT_Library))) {
    let lib: FT_Library = null();
    assert FT_Init_FreeType(addr_of(&lib)).succeeded();
    f(&lib);
    FT_Done_FreeType(lib);
}

#[test]
fn create_should_return_err_if_buf_is_bogus() {
    with_lib(|lib| {
        let buf = @~[];
        assert create(lib, buf).is_err();
    })
}
<commit_msg>Add most font metrics for FreeType<commit_after>#[legacy_exports];
export FreeTypeNativeFont, with_test_native_font, create;

use font::{FontMetrics, FractionalPixel};

use gfx::geometry;
use gfx::geometry::au;
use util::*;
use vec_as_buf = vec::as_imm_buf;
use ptr::{addr_of, null};
use cast::reinterpret_cast;
use glyph::GlyphIndex;
use font::FontMetrics;
use azure::freetype;
use freetype::{ FT_Error, FT_Library, FT_Face, FT_Long, FT_ULong, FT_Size, FT_SizeRec,
               FT_UInt, FT_GlyphSlot, FT_Size_Metrics, FT_FaceRec };
use freetype::bindgen::{
    FT_Init_FreeType,
    FT_Done_FreeType,
    FT_New_Memory_Face,
    FT_Done_Face,
    FT_Get_Char_Index,
    FT_Load_Glyph,
    FT_Set_Char_Size
};

fn float_to_fixed_ft(f: float) -> i32 {
    float_to_fixed(6, f)
}

fn fixed_to_float_ft(f: i32) -> float {
    fixed_to_float(6, f)
}

struct FreeTypeNativeFont {
    /// The font binary. This must stay valid for the lifetime of the font
    buf: @~[u8],
    face: FT_Face,

    drop {
        assert self.face.is_not_null();
        if !FT_Done_Face(self.face).succeeded() {
            fail ~"FT_Done_Face failed";
        }
    }
}

fn FreeTypeNativeFont(face: FT_Face, buf: @~[u8]) -> FreeTypeNativeFont {
    assert face.is_not_null();
    FreeTypeNativeFont { buf: buf, face: face }
}

impl FreeTypeNativeFont {

    fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
        assert self.face.is_not_null();
        let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
        return if idx != 0 as FT_UInt {
            Some(idx as GlyphIndex)
        } else {
            debug!("Invalid codepoint: %?", codepoint);
            None
        };
    }

    // FIXME: What unit is this returning? Let's have a custom type
    fn glyph_h_advance(glyph: GlyphIndex) -> Option<FractionalPixel> {
        assert self.face.is_not_null();
        let res =  FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
        if res.succeeded() {
            unsafe {
                let void_glyph = (*self.face).glyph;
                let slot: FT_GlyphSlot = reinterpret_cast(&void_glyph);
                assert slot.is_not_null();
                debug!("metrics: %?", (*slot).metrics);
                let advance = (*slot).metrics.horiAdvance;
                debug!("h_advance for %? is %?", glyph, advance);
                let advance = advance as i32;
                return Some(fixed_to_float_ft(advance) as FractionalPixel);
            }
        } else {
            debug!("Unable to load glyph %?. reason: %?", glyph, res);
            return None;
        }
    }

    fn get_metrics() -> FontMetrics {
        /* TODO: complete me (Issue #76) */

        let face = self.get_face_rec();

        let underline_size = self.font_units_to_au(face.underline_thickness as float);
        let underline_offset = self.font_units_to_au(face.underline_position as float);
        let em_size = self.font_units_to_au(face.units_per_EM as float);
        let ascent = self.font_units_to_au(face.ascender as float);
        let descent = self.font_units_to_au(face.descender as float);
        let max_advance = self.font_units_to_au(face.max_advance_width as float);

        return FontMetrics {
            underline_size:   underline_size,
            underline_offset: underline_offset,
            leading:          geometry::from_pt(0.0), //FIXME
            x_height:         geometry::from_pt(0.0), //FIXME
            em_size:          em_size,
            ascent:           ascent,
            descent:          descent,
            max_advance:      max_advance
        }
    }

    priv fn get_face_rec() -> &self/FT_FaceRec unsafe {
        &(*self.face)
    }

    priv fn font_units_to_au(value: float) -> au {

        let face = self.get_face_rec();

        // face.size is a *c_void in the bindings, presumably to avoid
        // recursive structural types
        let size: &FT_SizeRec = unsafe { cast::transmute(&(*face.size)) };
        let metrics: &FT_Size_Metrics = unsafe { &((*size).metrics) };

        let em_size = face.units_per_EM as float;
        let x_scale = (metrics.x_ppem as float) / em_size as float;

        // If this isn't true then we're scaling one of the axes wrong
        assert metrics.x_ppem == metrics.y_ppem;

        return geometry::from_frac_px(value * x_scale);
    }
}

pub fn create(lib: &FT_Library, buf: @~[u8]) -> Result<FreeTypeNativeFont, ()> {
    assert lib.is_not_null();
    let face: FT_Face = null();
    return vec_as_buf(*buf, |cbuf, _len| {
           if FT_New_Memory_Face(*lib, cbuf, (*buf).len() as FT_Long,
                                 0 as FT_Long, addr_of(&face)).succeeded() {
               // FIXME: These values are placeholders
               let res = FT_Set_Char_Size(face, 0, 20*64, 0, 72);
               if !res.succeeded() { fail ~"unable to set font char size" }
               Ok(FreeTypeNativeFont(face, buf))
           } else {
               Err(())
           }
    })
}

trait FTErrorMethods {
    fn succeeded() -> bool;
}

impl FT_Error : FTErrorMethods {
    fn succeeded() -> bool { self == 0 as FT_Error }
}

fn with_test_native_font(f: fn@(nf: &NativeFont)) {
    use font::test_font_bin;
    use unwrap_result = result::unwrap;

    with_lib(|lib| {
        let buf = @test_font_bin();
        let font = unwrap_result(create(lib, move buf));
        f(&font);
    })
}

fn with_lib(f: fn@((&FT_Library))) {
    let lib: FT_Library = null();
    assert FT_Init_FreeType(addr_of(&lib)).succeeded();
    f(&lib);
    FT_Done_FreeType(lib);
}

#[test]
fn create_should_return_err_if_buf_is_bogus() {
    with_lib(|lib| {
        let buf = @~[];
        assert create(lib, buf).is_err();
    })
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid 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 core::fmt;
use util;

impl<T> fmt::Display for util::UuidLength<T>
where
    T: AsRef<[usize]> + fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            util::UuidLength::Exact(v) => write!(f, "{}", v),
            util::UuidLength::OneOf(v) => write!(f, "any one of {:?}", v),
            util::UuidLength::Range { max, min } => {
                write!(f, "{}..{}", min, max)
            }
        }
    }
}
<commit_msg>fix borrow checker error<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid 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 core::fmt;
use util;

impl<T> fmt::Display for util::UuidLength<T>
where
    T: AsRef<[usize]> + fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            util::UuidLength::Exact(v) => write!(f, "{}", v),
            util::UuidLength::OneOf(ref v) => write!(f, "any one of {:?}", v),
            util::UuidLength::Range { max, min } => {
                write!(f, "{}..{}", min, max)
            }
        }
    }
}
<|endoftext|>


<commit_before>
extern crate test;
extern crate interpolation;

use interpolation::Ease;

macro_rules! bench_ease {
    ($name: ident, $T: ident, $f: ident) => (
        #[bench]
        fn $name(bencher: &mut test::Bencher) {
            let values = std::iter::count(0.0, 0.1).take(11).collect::<Vec<$T>>();
            bencher.iter(|| {
                let x = values.iter().map(|&x| Ease::$f(x)).collect::<Vec<$T>>();
                test::black_box(x);
            })
        }
    )
}

bench_ease!(bench_quadratic_in_f32, f32, quadratic_in);
bench_ease!(bench_quadratic_in_f64, f64, quadratic_in);

bench_ease!(bench_quadratic_out_f32, f32, quadratic_out);
bench_ease!(bench_quadratic_out_f64, f64, quadratic_out);

bench_ease!(bench_quadratic_in_out_f32, f32, quadratic_in_out);
bench_ease!(bench_quadratic_in_out_f64, f64, quadratic_in_out);

bench_ease!(bench_cubic_in_f32, f32, cubic_in);
bench_ease!(bench_cubic_in_f64, f64, cubic_in);

bench_ease!(bench_cubic_out_f32, f32, cubic_out);
bench_ease!(bench_cubic_out_f64, f64, cubic_out);

bench_ease!(bench_cubic_in_out_f32, f32, cubic_in_out);
bench_ease!(bench_cubic_in_out_f64, f64, cubic_in_out);

bench_ease!(bench_quartic_in_f32, f32, quartic_in);
bench_ease!(bench_quartic_in_f64, f64, quartic_in);

bench_ease!(bench_quartic_out_f32, f32, quartic_out);
bench_ease!(bench_quartic_out_f64, f64, quartic_out);

bench_ease!(bench_quartic_in_out_f32, f32, quartic_in_out);
bench_ease!(bench_quartic_in_out_f64, f64, quartic_in_out);

bench_ease!(bench_quintic_in_f32, f32, quintic_in);
bench_ease!(bench_quintic_in_f64, f64, quintic_in);

bench_ease!(bench_quintic_out_f32, f32, quintic_out);
bench_ease!(bench_quintic_out_f64, f64, quintic_out);

bench_ease!(bench_quintic_in_out_f32, f32, quintic_in_out);
bench_ease!(bench_quintic_in_out_f64, f64, quintic_in_out);

bench_ease!(bench_sine_in_f32, f32, sine_in);
bench_ease!(bench_sine_in_f64, f64, sine_in);

bench_ease!(bench_sine_out_f32, f32, sine_out);
bench_ease!(bench_sine_out_f64, f64, sine_out);

bench_ease!(bench_sine_in_out_f32, f32, sine_in_out);
bench_ease!(bench_sine_in_out_f64, f64, sine_in_out);

bench_ease!(bench_circular_in_f32, f32, circular_in);
bench_ease!(bench_circular_in_f64, f64, circular_in);

bench_ease!(bench_circular_out_f32, f32, circular_out);
bench_ease!(bench_circular_out_f64, f64, circular_out);

bench_ease!(bench_circular_in_out_f32, f32, circular_in_out);
bench_ease!(bench_circular_in_out_f64, f64, circular_in_out);

bench_ease!(bench_exponential_in_f32, f32, exponential_in);
bench_ease!(bench_exponential_in_f64, f64, exponential_in);

bench_ease!(bench_exponential_out_f32, f32, exponential_out);
bench_ease!(bench_exponential_out_f64, f64, exponential_out);

bench_ease!(bench_exponential_in_out_f32, f32, exponential_in_out);
bench_ease!(bench_exponential_in_out_f64, f64, exponential_in_out);

bench_ease!(bench_elastic_in_f32, f32, elastic_in);
bench_ease!(bench_elastic_in_f64, f64, elastic_in);

bench_ease!(bench_elastic_out_f32, f32, elastic_out);
bench_ease!(bench_elastic_out_f64, f64, elastic_out);

bench_ease!(bench_elastic_in_out_f32, f32, elastic_in_out);
bench_ease!(bench_elastic_in_out_f64, f64, elastic_in_out);

bench_ease!(bench_back_in_f32, f32, back_in);
bench_ease!(bench_back_in_f64, f64, back_in);

bench_ease!(bench_back_out_f32, f32, back_out);
bench_ease!(bench_back_out_f64, f64, back_out);

bench_ease!(bench_back_in_out_f32, f32, back_in_out);
bench_ease!(bench_back_in_out_f64, f64, back_in_out);

bench_ease!(bench_bounce_in_f32, f32, bounce_in);
bench_ease!(bench_bounce_in_f64, f64, bounce_in);

bench_ease!(bench_bounce_out_f32, f32, bounce_out);
bench_ease!(bench_bounce_out_f64, f64, bounce_out);

bench_ease!(bench_bounce_in_out_f32, f32, bounce_in_out);
bench_ease!(bench_bounce_in_out_f64, f64, bounce_in_out);

<commit_msg>Removed 'collect' in benches.<commit_after>
extern crate test;
extern crate interpolation;

use interpolation::Ease;

macro_rules! bench_ease {
    ($name: ident, $T: ident, $f: ident) => (
        #[bench]
        fn $name(bencher: &mut test::Bencher) {
            let values = std::iter::count(0.0, 0.1).take(11).collect::<Vec<$T>>();
            bencher.iter(|| {
                for x in values.iter().map(|&x| Ease::$f(x)) {
                    test::black_box(x);
                }
            })
        }
    )
}

bench_ease!(bench_quadratic_in_f32, f32, quadratic_in);
bench_ease!(bench_quadratic_in_f64, f64, quadratic_in);

bench_ease!(bench_quadratic_out_f32, f32, quadratic_out);
bench_ease!(bench_quadratic_out_f64, f64, quadratic_out);

bench_ease!(bench_quadratic_in_out_f32, f32, quadratic_in_out);
bench_ease!(bench_quadratic_in_out_f64, f64, quadratic_in_out);

bench_ease!(bench_cubic_in_f32, f32, cubic_in);
bench_ease!(bench_cubic_in_f64, f64, cubic_in);

bench_ease!(bench_cubic_out_f32, f32, cubic_out);
bench_ease!(bench_cubic_out_f64, f64, cubic_out);

bench_ease!(bench_cubic_in_out_f32, f32, cubic_in_out);
bench_ease!(bench_cubic_in_out_f64, f64, cubic_in_out);

bench_ease!(bench_quartic_in_f32, f32, quartic_in);
bench_ease!(bench_quartic_in_f64, f64, quartic_in);

bench_ease!(bench_quartic_out_f32, f32, quartic_out);
bench_ease!(bench_quartic_out_f64, f64, quartic_out);

bench_ease!(bench_quartic_in_out_f32, f32, quartic_in_out);
bench_ease!(bench_quartic_in_out_f64, f64, quartic_in_out);

bench_ease!(bench_quintic_in_f32, f32, quintic_in);
bench_ease!(bench_quintic_in_f64, f64, quintic_in);

bench_ease!(bench_quintic_out_f32, f32, quintic_out);
bench_ease!(bench_quintic_out_f64, f64, quintic_out);

bench_ease!(bench_quintic_in_out_f32, f32, quintic_in_out);
bench_ease!(bench_quintic_in_out_f64, f64, quintic_in_out);

bench_ease!(bench_sine_in_f32, f32, sine_in);
bench_ease!(bench_sine_in_f64, f64, sine_in);

bench_ease!(bench_sine_out_f32, f32, sine_out);
bench_ease!(bench_sine_out_f64, f64, sine_out);

bench_ease!(bench_sine_in_out_f32, f32, sine_in_out);
bench_ease!(bench_sine_in_out_f64, f64, sine_in_out);

bench_ease!(bench_circular_in_f32, f32, circular_in);
bench_ease!(bench_circular_in_f64, f64, circular_in);

bench_ease!(bench_circular_out_f32, f32, circular_out);
bench_ease!(bench_circular_out_f64, f64, circular_out);

bench_ease!(bench_circular_in_out_f32, f32, circular_in_out);
bench_ease!(bench_circular_in_out_f64, f64, circular_in_out);

bench_ease!(bench_exponential_in_f32, f32, exponential_in);
bench_ease!(bench_exponential_in_f64, f64, exponential_in);

bench_ease!(bench_exponential_out_f32, f32, exponential_out);
bench_ease!(bench_exponential_out_f64, f64, exponential_out);

bench_ease!(bench_exponential_in_out_f32, f32, exponential_in_out);
bench_ease!(bench_exponential_in_out_f64, f64, exponential_in_out);

bench_ease!(bench_elastic_in_f32, f32, elastic_in);
bench_ease!(bench_elastic_in_f64, f64, elastic_in);

bench_ease!(bench_elastic_out_f32, f32, elastic_out);
bench_ease!(bench_elastic_out_f64, f64, elastic_out);

bench_ease!(bench_elastic_in_out_f32, f32, elastic_in_out);
bench_ease!(bench_elastic_in_out_f64, f64, elastic_in_out);

bench_ease!(bench_back_in_f32, f32, back_in);
bench_ease!(bench_back_in_f64, f64, back_in);

bench_ease!(bench_back_out_f32, f32, back_out);
bench_ease!(bench_back_out_f64, f64, back_out);

bench_ease!(bench_back_in_out_f32, f32, back_in_out);
bench_ease!(bench_back_in_out_f64, f64, back_in_out);

bench_ease!(bench_bounce_in_f32, f32, bounce_in);
bench_ease!(bench_bounce_in_f64, f64, bounce_in);

bench_ease!(bench_bounce_out_f32, f32, bounce_out);
bench_ease!(bench_bounce_out_f64, f64, bounce_out);

bench_ease!(bench_bounce_in_out_f32, f32, bounce_in_out);
bench_ease!(bench_bounce_in_out_f64, f64, bounce_in_out);

<|endoftext|>


<commit_before>#![cfg(feature = "encoding")]

#![feature(test)]
extern crate test;

#[macro_use]
extern crate lambda_calculus as lambda;

use test::Bencher;
use lambda::data::boolean::fls;
use lambda::data::list::*;
use lambda::data::numerals::church::*;
use lambda::combinators::C;
use lambda::*;

fn list1() -> Term { vec![1].into_church() }
fn list2() -> Term { vec![2, 3].into_church() }
fn list3() -> Term { vec![1, 2, 3].into_church() }
fn   gt1() -> Term { app!(C(), gt(), 1.into_church()) }

#[bench]
fn list_is_nil(b: &mut Bencher) {
    b.iter(|| { beta(app(is_nil(), list3()), HAP, 0) } );
}

#[bench]
fn list_head(b: &mut Bencher) {
    b.iter(|| { beta(app(head(), list3()), HAP, 0) } );
}

#[bench]
fn list_tail(b: &mut Bencher) {
    b.iter(|| { beta(app(tail(), list3()), HAP, 0) } );
}

#[bench]
fn list_list(b: &mut Bencher) {
    b.iter(|| { beta(app!(list(), 3.into_church(), 1.into_church(), 2.into_church(), 3.into_church()), HAP, 0) } );
}

#[bench]
fn list_reverse(b: &mut Bencher) {
    b.iter(|| { beta(app(reverse(), list3()), HAP, 0) } );
}

#[bench]
fn list_append(b: &mut Bencher) {
    b.iter(|| { beta(app!(append(), list1(), list2()), HAP, 0) } );
}

#[bench]
fn list_map(b: &mut Bencher) {
    b.iter(|| { beta(app!(map(), gt1(), list3()), HAP, 0) } );
}

#[bench]
fn list_foldl(b: &mut Bencher) {
    b.iter(|| { beta(app!(foldl(), add(), 0.into_church(), list3()), HAP, 0) } );
}

#[bench]
fn list_foldr(b: &mut Bencher) {
    b.iter(|| { beta(app!(foldr(), add(), 0.into_church(), list3()), HAP, 0) } );
}

#[bench]
fn list_filter(b: &mut Bencher) {
    b.iter(|| { beta(app!(filter(), gt1(), list3()), HAP, 0) } );
}

#[bench]
fn list_init(b: &mut Bencher) {
    b.iter(|| { beta(app(init(), list3()), HAP, 0) } );
}

#[bench]
fn list_last(b: &mut Bencher) {
    b.iter(|| { beta(app(last(), list3()), HAP, 0) } );
}

#[bench]
fn list_zip(b: &mut Bencher) {
    b.iter(|| { beta(app!(zip(), list3(), list3()), HAP, 0) } );
}

#[bench]
fn list_zip_with(b: &mut Bencher) {
    b.iter(|| { beta(app!(zip_with(), fls(), list3(), list3()), HAP, 0) } );
}

#[bench]
fn list_take_while(b: &mut Bencher) {
    b.iter(|| { beta(app!(take_while(), is_zero(), list3()), HAP, 0) } );
}
<commit_msg>temporarily comment out the list::list bench<commit_after>#![cfg(feature = "encoding")]

#![feature(test)]
extern crate test;

#[macro_use]
extern crate lambda_calculus as lambda;

use test::Bencher;
use lambda::data::boolean::fls;
use lambda::data::list::*;
use lambda::data::numerals::church::*;
use lambda::combinators::C;
use lambda::*;

fn list1() -> Term { vec![1].into_church() }
fn list2() -> Term { vec![2, 3].into_church() }
fn list3() -> Term { vec![1, 2, 3].into_church() }
fn   gt1() -> Term { app!(C(), gt(), 1.into_church()) }

#[bench]
fn list_is_nil(b: &mut Bencher) {
    b.iter(|| { beta(app(is_nil(), list3()), HAP, 0) } );
}

#[bench]
fn list_head(b: &mut Bencher) {
    b.iter(|| { beta(app(head(), list3()), HAP, 0) } );
}

#[bench]
fn list_tail(b: &mut Bencher) {
    b.iter(|| { beta(app(tail(), list3()), HAP, 0) } );
}
/*
#[bench]
fn list_list(b: &mut Bencher) {
    b.iter(|| { beta(app!(list(), 3.into_church(), 1.into_church(), 2.into_church(), 3.into_church()), HAP, 0) } );
}
*/
#[bench]
fn list_reverse(b: &mut Bencher) {
    b.iter(|| { beta(app(reverse(), list3()), HAP, 0) } );
}

#[bench]
fn list_append(b: &mut Bencher) {
    b.iter(|| { beta(app!(append(), list1(), list2()), HAP, 0) } );
}

#[bench]
fn list_map(b: &mut Bencher) {
    b.iter(|| { beta(app!(map(), gt1(), list3()), HAP, 0) } );
}

#[bench]
fn list_foldl(b: &mut Bencher) {
    b.iter(|| { beta(app!(foldl(), add(), 0.into_church(), list3()), HAP, 0) } );
}

#[bench]
fn list_foldr(b: &mut Bencher) {
    b.iter(|| { beta(app!(foldr(), add(), 0.into_church(), list3()), HAP, 0) } );
}

#[bench]
fn list_filter(b: &mut Bencher) {
    b.iter(|| { beta(app!(filter(), gt1(), list3()), HAP, 0) } );
}

#[bench]
fn list_init(b: &mut Bencher) {
    b.iter(|| { beta(app(init(), list3()), HAP, 0) } );
}

#[bench]
fn list_last(b: &mut Bencher) {
    b.iter(|| { beta(app(last(), list3()), HAP, 0) } );
}

#[bench]
fn list_zip(b: &mut Bencher) {
    b.iter(|| { beta(app!(zip(), list3(), list3()), HAP, 0) } );
}

#[bench]
fn list_zip_with(b: &mut Bencher) {
    b.iter(|| { beta(app!(zip_with(), fls(), list3(), list3()), HAP, 0) } );
}

#[bench]
fn list_take_while(b: &mut Bencher) {
    b.iter(|| { beta(app!(take_while(), is_zero(), list3()), HAP, 0) } );
}
<|endoftext|>


<commit_before>use cairo;
use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};

use crate::drawing_ctx::DrawingCtx;
use crate::error::NodeError;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::surface_utils::shared_surface::SharedImageSurface;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::input::Input;
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible blending modes.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum Mode {
    Normal,
    Multiply,
    Screen,
    Darken,
    Lighten,
    Overlay,
    ColorDodge,
    ColorBurn,
    HardLight,
    SoftLight,
    Difference,
    Exclusion,
    HslHue,
    HslSaturation,
    HslColor,
    HslLuminosity,
}

/// The `feBlend` filter primitive.
pub struct FeBlend {
    base: PrimitiveWithInput,
    in2: Option<Input>,
    mode: Mode,
}

impl Default for FeBlend {
    /// Constructs a new `Blend` with empty properties.
    #[inline]
    fn default() -> FeBlend {
        FeBlend {
            base: PrimitiveWithInput::new::<Self>(),
            in2: None,
            mode: Mode::Normal,
        }
    }
}

impl NodeTrait for FeBlend {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!(svg "in2") => {
                    self.in2 = Some(Input::parse(attr, value)?);
                }
                expanded_name!(svg "mode") => self.mode = Mode::parse(attr, value)?,
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeBlend {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let input_2 = ctx.get_input(draw_ctx, self.in2.as_ref())?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .add_input(&input_2)
            .into_irect(draw_ctx);

        // If we're combining two alpha-only surfaces, the result is alpha-only. Otherwise the
        // result is whatever the non-alpha-only type we're working on (which can be either sRGB or
        // linear sRGB depending on color-interpolation-filters).
        let surface_type = if input.surface().is_alpha_only() {
            input_2.surface().surface_type()
        } else {
            if !input_2.surface().is_alpha_only() {
                // All surface types should match (this is enforced by get_input()).
                assert_eq!(
                    input_2.surface().surface_type(),
                    input.surface().surface_type()
                );
            }

            input.surface().surface_type()
        };

        let output_surface = input_2.surface().copy_surface(bounds)?;
        {
            let cr = cairo::Context::new(&output_surface);
            let r = cairo::Rectangle::from(bounds);
            cr.rectangle(r.x, r.y, r.width, r.height);
            cr.clip();

            input.surface().set_as_source_surface(&cr, 0f64, 0f64);
            cr.set_operator(self.mode.into());
            cr.paint();
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, surface_type)?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Mode {
    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
        match s {
            "normal" => Ok(Mode::Normal),
            "multiply" => Ok(Mode::Multiply),
            "screen" => Ok(Mode::Screen),
            "darken" => Ok(Mode::Darken),
            "lighten" => Ok(Mode::Lighten),
            "overlay" => Ok(Mode::Overlay),
            "color-dodge" => Ok(Mode::ColorDodge),
            "color-burn" => Ok(Mode::ColorBurn),
            "hard-light" => Ok(Mode::HardLight),
            "soft-light" => Ok(Mode::SoftLight),
            "difference" => Ok(Mode::Difference),
            "exclusion" => Ok(Mode::Exclusion),
            "hue" => Ok(Mode::HslHue),
            "saturation" => Ok(Mode::HslSaturation),
            "color" => Ok(Mode::HslColor),
            "luminosity" => Ok(Mode::HslLuminosity),
            _ => Err(NodeError::parse_error(attr, "invalid value")),
        }
    }
}

impl From<Mode> for cairo::Operator {
    #[inline]
    fn from(x: Mode) -> Self {
        match x {
            Mode::Normal => cairo::Operator::Over,
            Mode::Multiply => cairo::Operator::Multiply,
            Mode::Screen => cairo::Operator::Screen,
            Mode::Darken => cairo::Operator::Darken,
            Mode::Lighten => cairo::Operator::Lighten,
            Mode::Overlay => cairo::Operator::Overlay,
            Mode::ColorDodge => cairo::Operator::ColorDodge,
            Mode::ColorBurn => cairo::Operator::ColorBurn,
            Mode::HardLight => cairo::Operator::HardLight,
            Mode::SoftLight => cairo::Operator::SoftLight,
            Mode::Difference => cairo::Operator::Difference,
            Mode::Exclusion => cairo::Operator::Exclusion,
            Mode::HslHue => cairo::Operator::HslHue,
            Mode::HslSaturation => cairo::Operator::HslSaturation,
            Mode::HslColor => cairo::Operator::HslColor,
            Mode::HslLuminosity => cairo::Operator::HslLuminosity,
        }
    }
}
<commit_msg>blend.rs: Don't create a NodeError directly<commit_after>use cairo;
use markup5ever::{expanded_name, local_name, namespace_url, ns, QualName};

use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{NodeResult, NodeTrait, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::surface_utils::shared_surface::SharedImageSurface;

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::input::Input;
use super::{FilterEffect, FilterError, PrimitiveWithInput};

/// Enumeration of the possible blending modes.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum Mode {
    Normal,
    Multiply,
    Screen,
    Darken,
    Lighten,
    Overlay,
    ColorDodge,
    ColorBurn,
    HardLight,
    SoftLight,
    Difference,
    Exclusion,
    HslHue,
    HslSaturation,
    HslColor,
    HslLuminosity,
}

/// The `feBlend` filter primitive.
pub struct FeBlend {
    base: PrimitiveWithInput,
    in2: Option<Input>,
    mode: Mode,
}

impl Default for FeBlend {
    /// Constructs a new `Blend` with empty properties.
    #[inline]
    fn default() -> FeBlend {
        FeBlend {
            base: PrimitiveWithInput::new::<Self>(),
            in2: None,
            mode: Mode::Normal,
        }
    }
}

impl NodeTrait for FeBlend {
    impl_node_as_filter_effect!();

    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)?;

        for (attr, value) in pbag.iter() {
            match attr.expanded() {
                expanded_name!(svg "in2") => {
                    self.in2 = Some(Input::parse(attr, value)?);
                }
                expanded_name!(svg "mode") => self.mode = Mode::parse(attr, value)?,
                _ => (),
            }
        }

        Ok(())
    }
}

impl FilterEffect for FeBlend {
    fn render(
        &self,
        _node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        let input = self.base.get_input(ctx, draw_ctx)?;
        let input_2 = ctx.get_input(draw_ctx, self.in2.as_ref())?;
        let bounds = self
            .base
            .get_bounds(ctx)
            .add_input(&input)
            .add_input(&input_2)
            .into_irect(draw_ctx);

        // If we're combining two alpha-only surfaces, the result is alpha-only. Otherwise the
        // result is whatever the non-alpha-only type we're working on (which can be either sRGB or
        // linear sRGB depending on color-interpolation-filters).
        let surface_type = if input.surface().is_alpha_only() {
            input_2.surface().surface_type()
        } else {
            if !input_2.surface().is_alpha_only() {
                // All surface types should match (this is enforced by get_input()).
                assert_eq!(
                    input_2.surface().surface_type(),
                    input.surface().surface_type()
                );
            }

            input.surface().surface_type()
        };

        let output_surface = input_2.surface().copy_surface(bounds)?;
        {
            let cr = cairo::Context::new(&output_surface);
            let r = cairo::Rectangle::from(bounds);
            cr.rectangle(r.x, r.y, r.width, r.height);
            cr.clip();

            input.surface().set_as_source_surface(&cr, 0f64, 0f64);
            cr.set_operator(self.mode.into());
            cr.paint();
        }

        Ok(FilterResult {
            name: self.base.result.clone(),
            output: FilterOutput {
                surface: SharedImageSurface::new(output_surface, surface_type)?,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}

impl Mode {
    fn parse(attr: QualName, s: &str) -> Result<Self, NodeError> {
        match s {
            "normal" => Ok(Mode::Normal),
            "multiply" => Ok(Mode::Multiply),
            "screen" => Ok(Mode::Screen),
            "darken" => Ok(Mode::Darken),
            "lighten" => Ok(Mode::Lighten),
            "overlay" => Ok(Mode::Overlay),
            "color-dodge" => Ok(Mode::ColorDodge),
            "color-burn" => Ok(Mode::ColorBurn),
            "hard-light" => Ok(Mode::HardLight),
            "soft-light" => Ok(Mode::SoftLight),
            "difference" => Ok(Mode::Difference),
            "exclusion" => Ok(Mode::Exclusion),
            "hue" => Ok(Mode::HslHue),
            "saturation" => Ok(Mode::HslSaturation),
            "color" => Ok(Mode::HslColor),
            "luminosity" => Ok(Mode::HslLuminosity),
            _ => Err(ValueErrorKind::parse_error("invalid value")).attribute(attr),
        }
    }
}

impl From<Mode> for cairo::Operator {
    #[inline]
    fn from(x: Mode) -> Self {
        match x {
            Mode::Normal => cairo::Operator::Over,
            Mode::Multiply => cairo::Operator::Multiply,
            Mode::Screen => cairo::Operator::Screen,
            Mode::Darken => cairo::Operator::Darken,
            Mode::Lighten => cairo::Operator::Lighten,
            Mode::Overlay => cairo::Operator::Overlay,
            Mode::ColorDodge => cairo::Operator::ColorDodge,
            Mode::ColorBurn => cairo::Operator::ColorBurn,
            Mode::HardLight => cairo::Operator::HardLight,
            Mode::SoftLight => cairo::Operator::SoftLight,
            Mode::Difference => cairo::Operator::Difference,
            Mode::Exclusion => cairo::Operator::Exclusion,
            Mode::HslHue => cairo::Operator::HslHue,
            Mode::HslSaturation => cairo::Operator::HslSaturation,
            Mode::HslColor => cairo::Operator::HslColor,
            Mode::HslLuminosity => cairo::Operator::HslLuminosity,
        }
    }
}
<|endoftext|>