<commit_before>// Copyright (c) 2015-2016 Ivo Wetzel

// 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.
extern crate clock_ticks;

use std::cmp;
use std::thread;
use std::time::Duration;
use std::io::{Error, ErrorKind};
use std::net::{SocketAddr, ToSocketAddrs};
use traits::socket::Socket;
use shared::stats::{StatsCollector, Stats};
use shared::udp_socket::UdpSocket;
use super::{Config, Connection, Handler, MessageKind};

/// Implementation of a single-server client with handler based event dispatch.
///
/// There are two ways of creating and connection a client instance:
///
/// 1. Blocking mode to be used in it dedicated thread, with asynchronous
/// `Handler` callbacks, available via the methods **without** the `sync`
/// postfix.
///
/// 2. Non-Blocking mode, with synchronous `Handler` callbacks, available via
/// the methods **with** the `sync` postfix.
#[derive(Debug)]
pub struct Client {
    closed: bool,
    running: bool,
    config: Config,
    peer_address: Option<SocketAddr>,
    local_address: Option<SocketAddr>,
    statistics: StatsCollector
}

impl Client {

    /// Creates a new client with the given configuration.
    pub fn new(config: Config) -> Client {
        Client {
            closed: false,
            running: false,
            config: config,
            peer_address: None,
            local_address: None,
            statistics: StatsCollector::new(config)
        }
    }

    /// Returns the address of the server the client is currently connected to.
    pub fn peer_addr(&self) -> Result<SocketAddr, Error> {
        self.peer_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, ""))
    }

    /// Returns the local address that the client is sending from.
    pub fn local_addr(&self) -> Result<SocketAddr, Error> {
        self.local_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, ""))
    }

    /// Returns statistics (i.e. bandwidth usage) for the last second.
    pub fn stats(&mut self) -> Stats {
        self.statistics.average()
    }

    /// Overrides the client's existing configuration.
    pub fn set_config<S: Socket>(&mut self, config: Config, state: &mut ClientState<S>) {
        self.config = config;
        self.statistics.set_config(config);
        state.set_config(config);
    }

    // Asynchronous, blocking API ---------------------------------------------

    /// Establishes a connection with the server at the specified address by
    /// creating a local socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method starts the tick loop, blocking the calling thread.
    pub fn connect<A: ToSocketAddrs>(
        &mut self, handler: &mut Handler<Client>, addr: A

    ) -> Result<(), Error> {

        let socket = try!(UdpSocket::new(
            "0.0.0.0:0",
            self.config.packet_max_size
        ));

        self.connect_from_socket(handler, addr, socket)

    }

    /// Establishes a connection with the server at the specified address by
    /// using the specified socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method starts the tick loop, blocking the calling thread.
    pub fn connect_from_socket<S: Socket, A: ToSocketAddrs>(
        &mut self, handler: &mut Handler<Client>, addr: A, socket: S

    ) -> Result<(), Error> {

        let mut state = try!(
            self.connect_from_socket_sync(handler, addr, socket)
        );

        while self.running {

            // Get current time to correct tick delay in order to achieve
            // a more stable tick rate
            let begin = clock_ticks::precise_time_ns();
            let tick_delay = 1000000000 / self.config.send_rate;

            self.receive_sync(handler, &mut state, tick_delay / 1000000);
            self.tick_sync(handler, &mut state);
            self.send_sync(handler, &mut state);

            // Calculate spend time in current loop iteration and limit ticks
            // accordingly.

            // TODO: In case we spent more time than the tick_delay, make the
            // next tick faster in order to compensate.
            thread::sleep(
                Duration::new(0, tick_delay - cmp::min(
                    (clock_ticks::precise_time_ns() - begin) as u32,
                    tick_delay
                ))
            );

        }

        self.close_sync(handler, &mut state)

    }

    /// Asynchronously closes the connection to the server.
    ///
    /// This exits the tick loop, resets the connection and shuts down the
    /// underlying socket the client was sending and receiving from.
    pub fn close(&mut self) -> Result<(), Error>{
        if self.running {
            self.running = false;
            Ok(())

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    // Non-Blocking, Synchronous API ------------------------------------------

    /// Establishes a connection with the server at the specified address by
    /// creating a local socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method returns a `ClientState` instance for this client, which can
    /// be used with other synchronous `Client` methods.
    pub fn connect_sync<A: ToSocketAddrs>(
        &mut self, handler: &mut Handler<Client>, addr: A

    ) -> Result<ClientState<UdpSocket>, Error> {

        let socket = try!(UdpSocket::new(
            "0.0.0.0:0",
            self.config.packet_max_size
        ));

        self.connect_from_socket_sync(handler, addr, socket)

    }

    /// Establishes a connection with the server at the specified address by
    /// using the specified socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method returns a `ClientState` instance for this client, which can
    /// be used with other synchronous `Client` methods.
    pub fn connect_from_socket_sync<A: ToSocketAddrs, S: Socket>(
        &mut self, handler: &mut Handler<Client>, addr: A, socket: S

    ) -> Result<ClientState<S>, Error> {

        let peer_addr = try!(addr.to_socket_addrs()).nth(0).unwrap();
        let local_addr = try!(socket.local_addr());

        self.peer_address = Some(peer_addr);
        self.local_address = Some(local_addr);
        self.statistics.reset();
        self.running = true;
        self.closed = false;

        let connection = Connection::new(
            self.config,
            local_addr,
            peer_addr,
            handler.rate_limiter(&self.config)
        );

        handler.connect(self);

        Ok(ClientState::new(socket, connection, peer_addr))

    }

    /// Receives all currently buffered incoming packet from the underlying
    /// connection.
    pub fn receive_sync<S: Socket>(
        &mut self,
        handler: &mut Handler<Client>, state: &mut ClientState<S>,
        tick_delay: u32
    ) {

        // Receive all incoming UDP packets from the specified remote
        // address feeding them into out connection object for parsing
        if !self.closed {
            let mut bytes_received = 0;
            while let Ok((addr, packet)) = state.socket.try_recv() {
                if addr == state.peer_address {
                    bytes_received += packet.len();
                    state.connection.receive_packet(
                        packet, tick_delay, self, handler
                    );
                }
            }
            self.statistics.set_bytes_received(bytes_received as u32);
        }

    }

    /// Performs exactly on tick of the underlying connection.
    pub fn tick_sync<S: Socket>(
        &mut self, handler: &mut Handler<Client>, state: &mut ClientState<S>
    ) {
        if !self.closed {
            handler.tick_connection(self, &mut state.connection);
        }
    }

    /// Sends exactly on outgoing packet from the underlying connection.
    pub fn send_sync<S: Socket>(
        &mut self, handler: &mut Handler<Client>, state: &mut ClientState<S>
    ) {
        if !self.closed {
            let bytes_sent = state.connection.send_packet(
                &mut state.socket, &state.peer_address, self, handler
            );
            self.statistics.set_bytes_sent(bytes_sent);
            self.statistics.tick();
            state.stats = self.statistics.average();
        }
    }

    /// Closes the connection to the server.
    ///
    /// This resets the connection and shuts down the underlying socket the
    /// client was sending and receiving from.
    pub fn close_sync<S: Socket>(
        &mut self, handler: &mut Handler<Client>, state: &mut ClientState<S>

    ) -> Result<(), Error> {

        if self.closed {
            Err(Error::new(ErrorKind::NotConnected, ""))

        } else {

            self.closed = true;

            handler.close(self);
            state.connection.reset();
            state.socket.shutdown();

            self.peer_address = None;
            self.local_address = None;

            Ok(())

        }

    }

}

/// A structure used for synchronous calls on a `Client` instance.
#[derive(Debug)]
pub struct ClientState<S: Socket> {
    socket: S,
    connection: Connection,
    peer_address: SocketAddr,
    stats: Stats
}

impl <S: Socket>ClientState< S> {

    // We need to encapsulate the above objects because they cannot be
    // owned by the client itself without running into issues with multiple
    // bindings of Self when trying to both call a method on it's
    // connection and pass it to that method.
    fn new(
        socket: S,
        connection: Connection,
        peer_addr: SocketAddr

    ) -> ClientState<S> {
        ClientState {
            socket: socket,
            connection: connection,
            peer_address: peer_addr,
            stats: Stats {
                bytes_sent: 0,
                bytes_received: 0
            }
        }
    }

    /// Returns the average roundtrip time for this client's underlying
    /// connection.
    pub fn rtt(&self) -> u32 {
        self.connection.rtt()
    }

    /// Returns the percent of packets that were sent and never acknowledged
    /// over the total number of packets that have been send across this
    /// client's underlying connection.
    pub fn packet_loss(&self) -> f32 {
        self.connection.packet_loss()
    }

    /// Returns statistics (i.e. bandwidth usage) for the last second, of this
    /// client'sunderlying connection.
    pub fn stats(&self) -> Stats {
        self.stats
    }

    /// Returns the socket address for the local end of this client's
    /// underlying connection.
    pub fn local_addr(&self) -> SocketAddr {
        self.connection.local_addr()
    }

    /// Returns the socket address for the remote end of this client's
    /// underlying connection.
    pub fn peer_addr(&self) -> SocketAddr {
        self.connection.peer_addr()
    }

    /// Overrides the configuration of this client's underlying connection.
    pub fn set_config(&mut self, config: Config) {
        self.connection.set_config(config);
    }

    /// Sends a message of the specified `kind` along with its `payload` over
    /// this client's underlying connection.
    pub fn send(&mut self, kind: MessageKind, payload: Vec<u8>) {
        self.connection.send(kind, payload);
    }

    /// Resets this client's underlying connection state.
    pub fn reset(&mut self) {
        self.connection.reset();
    }

}

<commit_msg>Add config() method to Client.<commit_after>// Copyright (c) 2015-2016 Ivo Wetzel

// 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.
extern crate clock_ticks;

use std::cmp;
use std::thread;
use std::time::Duration;
use std::io::{Error, ErrorKind};
use std::net::{SocketAddr, ToSocketAddrs};
use traits::socket::Socket;
use shared::stats::{StatsCollector, Stats};
use shared::udp_socket::UdpSocket;
use super::{Config, Connection, Handler, MessageKind};

/// Implementation of a single-server client with handler based event dispatch.
///
/// There are two ways of creating and connection a client instance:
///
/// 1. Blocking mode to be used in it dedicated thread, with asynchronous
/// `Handler` callbacks, available via the methods **without** the `sync`
/// postfix.
///
/// 2. Non-Blocking mode, with synchronous `Handler` callbacks, available via
/// the methods **with** the `sync` postfix.
#[derive(Debug)]
pub struct Client {
    closed: bool,
    running: bool,
    config: Config,
    peer_address: Option<SocketAddr>,
    local_address: Option<SocketAddr>,
    statistics: StatsCollector
}

impl Client {

    /// Creates a new client with the given configuration.
    pub fn new(config: Config) -> Client {
        Client {
            closed: false,
            running: false,
            config: config,
            peer_address: None,
            local_address: None,
            statistics: StatsCollector::new(config)
        }
    }

    /// Returns the address of the server the client is currently connected to.
    pub fn peer_addr(&self) -> Result<SocketAddr, Error> {
        self.peer_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, ""))
    }

    /// Returns the local address that the client is sending from.
    pub fn local_addr(&self) -> Result<SocketAddr, Error> {
        self.local_address.ok_or_else(|| Error::new(ErrorKind::AddrNotAvailable, ""))
    }

    /// Returns statistics (i.e. bandwidth usage) for the last second.
    pub fn stats(&mut self) -> Stats {
        self.statistics.average()
    }

    /// Returns a copy of the client's current configuration.
    pub fn config(&self) -> Config {
        self.config
    }

    /// Overrides the client's existing configuration.
    pub fn set_config<S: Socket>(&mut self, config: Config, state: &mut ClientState<S>) {
        self.config = config;
        self.statistics.set_config(config);
        state.set_config(config);
    }

    // Asynchronous, blocking API ---------------------------------------------

    /// Establishes a connection with the server at the specified address by
    /// creating a local socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method starts the tick loop, blocking the calling thread.
    pub fn connect<A: ToSocketAddrs>(
        &mut self, handler: &mut Handler<Client>, addr: A

    ) -> Result<(), Error> {

        let socket = try!(UdpSocket::new(
            "0.0.0.0:0",
            self.config.packet_max_size
        ));

        self.connect_from_socket(handler, addr, socket)

    }

    /// Establishes a connection with the server at the specified address by
    /// using the specified socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method starts the tick loop, blocking the calling thread.
    pub fn connect_from_socket<S: Socket, A: ToSocketAddrs>(
        &mut self, handler: &mut Handler<Client>, addr: A, socket: S

    ) -> Result<(), Error> {

        let mut state = try!(
            self.connect_from_socket_sync(handler, addr, socket)
        );

        while self.running {

            // Get current time to correct tick delay in order to achieve
            // a more stable tick rate
            let begin = clock_ticks::precise_time_ns();
            let tick_delay = 1000000000 / self.config.send_rate;

            self.receive_sync(handler, &mut state, tick_delay / 1000000);
            self.tick_sync(handler, &mut state);
            self.send_sync(handler, &mut state);

            // Calculate spend time in current loop iteration and limit ticks
            // accordingly.

            // TODO: In case we spent more time than the tick_delay, make the
            // next tick faster in order to compensate.
            thread::sleep(
                Duration::new(0, tick_delay - cmp::min(
                    (clock_ticks::precise_time_ns() - begin) as u32,
                    tick_delay
                ))
            );

        }

        self.close_sync(handler, &mut state)

    }

    /// Asynchronously closes the connection to the server.
    ///
    /// This exits the tick loop, resets the connection and shuts down the
    /// underlying socket the client was sending and receiving from.
    pub fn close(&mut self) -> Result<(), Error>{
        if self.running {
            self.running = false;
            Ok(())

        } else {
            Err(Error::new(ErrorKind::NotConnected, ""))
        }
    }

    // Non-Blocking, Synchronous API ------------------------------------------

    /// Establishes a connection with the server at the specified address by
    /// creating a local socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method returns a `ClientState` instance for this client, which can
    /// be used with other synchronous `Client` methods.
    pub fn connect_sync<A: ToSocketAddrs>(
        &mut self, handler: &mut Handler<Client>, addr: A

    ) -> Result<ClientState<UdpSocket>, Error> {

        let socket = try!(UdpSocket::new(
            "0.0.0.0:0",
            self.config.packet_max_size
        ));

        self.connect_from_socket_sync(handler, addr, socket)

    }

    /// Establishes a connection with the server at the specified address by
    /// using the specified socket for message sending.
    ///
    /// The server must use a compatible connection / packet configuration.
    ///
    /// The `handler` is a struct that implements the `Handler` trait in order
    /// to handle events from the client and its connection.
    ///
    /// This method returns a `ClientState` instance for this client, which can
    /// be used with other synchronous `Client` methods.
    pub fn connect_from_socket_sync<A: ToSocketAddrs, S: Socket>(
        &mut self, handler: &mut Handler<Client>, addr: A, socket: S

    ) -> Result<ClientState<S>, Error> {

        let peer_addr = try!(addr.to_socket_addrs()).nth(0).unwrap();
        let local_addr = try!(socket.local_addr());

        self.peer_address = Some(peer_addr);
        self.local_address = Some(local_addr);
        self.statistics.reset();
        self.running = true;
        self.closed = false;

        let connection = Connection::new(
            self.config,
            local_addr,
            peer_addr,
            handler.rate_limiter(&self.config)
        );

        handler.connect(self);

        Ok(ClientState::new(socket, connection, peer_addr))

    }

    /// Receives all currently buffered incoming packet from the underlying
    /// connection.
    pub fn receive_sync<S: Socket>(
        &mut self,
        handler: &mut Handler<Client>, state: &mut ClientState<S>,
        tick_delay: u32
    ) {

        // Receive all incoming UDP packets from the specified remote
        // address feeding them into out connection object for parsing
        if !self.closed {
            let mut bytes_received = 0;
            while let Ok((addr, packet)) = state.socket.try_recv() {
                if addr == state.peer_address {
                    bytes_received += packet.len();
                    state.connection.receive_packet(
                        packet, tick_delay, self, handler
                    );
                }
            }
            self.statistics.set_bytes_received(bytes_received as u32);
        }

    }

    /// Performs exactly on tick of the underlying connection.
    pub fn tick_sync<S: Socket>(
        &mut self, handler: &mut Handler<Client>, state: &mut ClientState<S>
    ) {
        if !self.closed {
            handler.tick_connection(self, &mut state.connection);
        }
    }

    /// Sends exactly on outgoing packet from the underlying connection.
    pub fn send_sync<S: Socket>(
        &mut self, handler: &mut Handler<Client>, state: &mut ClientState<S>
    ) {
        if !self.closed {
            let bytes_sent = state.connection.send_packet(
                &mut state.socket, &state.peer_address, self, handler
            );
            self.statistics.set_bytes_sent(bytes_sent);
            self.statistics.tick();
            state.stats = self.statistics.average();
        }
    }

    /// Closes the connection to the server.
    ///
    /// This resets the connection and shuts down the underlying socket the
    /// client was sending and receiving from.
    pub fn close_sync<S: Socket>(
        &mut self, handler: &mut Handler<Client>, state: &mut ClientState<S>

    ) -> Result<(), Error> {

        if self.closed {
            Err(Error::new(ErrorKind::NotConnected, ""))

        } else {

            self.closed = true;

            handler.close(self);
            state.connection.reset();
            state.socket.shutdown();

            self.peer_address = None;
            self.local_address = None;

            Ok(())

        }

    }

}

/// A structure used for synchronous calls on a `Client` instance.
#[derive(Debug)]
pub struct ClientState<S: Socket> {
    socket: S,
    connection: Connection,
    peer_address: SocketAddr,
    stats: Stats
}

impl <S: Socket>ClientState<S> {

    // We need to encapsulate the above objects because they cannot be
    // owned by the client itself without running into issues with multiple
    // bindings of Self when trying to both call a method on it's
    // connection and pass it to that method.
    fn new(
        socket: S,
        connection: Connection,
        peer_addr: SocketAddr

    ) -> ClientState<S> {
        ClientState {
            socket: socket,
            connection: connection,
            peer_address: peer_addr,
            stats: Stats {
                bytes_sent: 0,
                bytes_received: 0
            }
        }
    }

    /// Returns the average roundtrip time for this client's underlying
    /// connection.
    pub fn rtt(&self) -> u32 {
        self.connection.rtt()
    }

    /// Returns the percent of packets that were sent and never acknowledged
    /// over the total number of packets that have been send across this
    /// client's underlying connection.
    pub fn packet_loss(&self) -> f32 {
        self.connection.packet_loss()
    }

    /// Returns statistics (i.e. bandwidth usage) for the last second, of this
    /// client's underlying connection.
    pub fn stats(&self) -> Stats {
        self.stats
    }

    /// Returns the socket address for the local end of this client's
    /// underlying connection.
    pub fn local_addr(&self) -> SocketAddr {
        self.connection.local_addr()
    }

    /// Returns the socket address for the remote end of this client's
    /// underlying connection.
    pub fn peer_addr(&self) -> SocketAddr {
        self.connection.peer_addr()
    }

    /// Overrides the configuration of this client's underlying connection.
    pub fn set_config(&mut self, config: Config) {
        self.connection.set_config(config);
    }

    /// Sends a message of the specified `kind` along with its `payload` over
    /// this client's underlying connection.
    pub fn send(&mut self, kind: MessageKind, payload: Vec<u8>) {
        self.connection.send(kind, payload);
    }

    /// Resets this client's underlying connection state.
    pub fn reset(&mut self) {
        self.connection.reset();
    }

}

<|endoftext|>


<commit_before>/// Define a type that supports parsing and printing a given identifier as if it
/// were a keyword.
///
/// # Usage
///
/// As a convention, it is recommended that this macro be invoked within a
/// module called `kw` or `keyword` and that the resulting parser be invoked
/// with a `kw::` or `keyword::` prefix.
///
/// ```
/// mod kw {
///     syn::custom_keyword!(whatever);
/// }
/// ```
///
/// The generated syntax tree node supports the following operations just like
/// any built-in keyword token.
///
/// - [Peeking] — `input.peek(kw::whatever)`
///
/// - [Parsing] — `input.parse::<kw::whatever>()?`
///
/// - [Printing] — `quote!( ... #whatever_token ... )`
///
/// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)`
///
/// - Field access to its span — `let sp = whatever_token.span`
///
/// [Peeking]: crate::parse::ParseBuffer::peek
/// [Parsing]: crate::parse::ParseBuffer::parse
/// [Printing]: quote::ToTokens
/// [`Span`]: proc_macro2::Span
///
/// # Example
///
/// This example parses input that looks like `bool = true` or `str = "value"`.
/// The key must be either the identifier `bool` or the identifier `str`. If
/// `bool`, the value may be either `true` or `false`. If `str`, the value may
/// be any string literal.
///
/// The symbols `bool` and `str` are not reserved keywords in Rust so these are
/// not considered keywords in the `syn::token` module. Like any other
/// identifier that is not a keyword, these can be declared as custom keywords
/// by crates that need to use them as such.
///
/// ```
/// use syn::{LitBool, LitStr, Result, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// mod kw {
///     syn::custom_keyword!(bool);
///     syn::custom_keyword!(str);
/// }
///
/// enum Argument {
///     Bool {
///         bool_token: kw::bool,
///         eq_token: Token![=],
///         value: LitBool,
///     },
///     Str {
///         str_token: kw::str,
///         eq_token: Token![=],
///         value: LitStr,
///     },
/// }
///
/// impl Parse for Argument {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let lookahead = input.lookahead1();
///         if lookahead.peek(kw::bool) {
///             Ok(Argument::Bool {
///                 bool_token: input.parse::<kw::bool>()?,
///                 eq_token: input.parse()?,
///                 value: input.parse()?,
///             })
///         } else if lookahead.peek(kw::str) {
///             Ok(Argument::Str {
///                 str_token: input.parse::<kw::str>()?,
///                 eq_token: input.parse()?,
///                 value: input.parse()?,
///             })
///         } else {
///             Err(lookahead.error())
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! custom_keyword {
    ($ident:ident) => {
        #[allow(non_camel_case_types)]
        pub struct $ident {
            pub span: $crate::__private::Span,
        }

        #[doc(hidden)]
        #[allow(dead_code, non_snake_case)]
        pub fn $ident<__S: $crate::__private::IntoSpans<[$crate::__private::Span; 1]>>(
            span: __S,
        ) -> $ident {
            $ident {
                span: $crate::__private::IntoSpans::into_spans(span)[0],
            }
        }

        impl $crate::__private::Default for $ident {
            fn default() -> Self {
                $ident {
                    span: $crate::__private::Span::call_site(),
                }
            }
        }

        $crate::impl_parse_for_custom_keyword!($ident);
        $crate::impl_to_tokens_for_custom_keyword!($ident);
        $crate::impl_clone_for_custom_keyword!($ident);
        $crate::impl_extra_traits_for_custom_keyword!($ident);
    };
}

// Not public API.
#[cfg(feature = "parsing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_keyword {
    ($ident:ident) => {
        // For peek.
        impl $crate::token::CustomToken for $ident {
            fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
                if let Some((ident, _rest)) = cursor.ident() {
                    ident == stringify!($ident)
                } else {
                    false
                }
            }

            fn display() -> &'static $crate::__private::str {
                concat!("`", stringify!($ident), "`")
            }
        }

        impl $crate::parse::Parse for $ident {
            fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
                input.step(|cursor| {
                    if let $crate::__private::Some((ident, rest)) = cursor.ident() {
                        if ident == stringify!($ident) {
                            return $crate::__private::Ok(($ident { span: ident.span() }, rest));
                        }
                    }
                    $crate::__private::Err(cursor.error(concat!(
                        "expected `",
                        stringify!($ident),
                        "`"
                    )))
                })
            }
        }
    };
}

// Not public API.
#[cfg(not(feature = "parsing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_keyword {
    ($ident:ident) => {};
}

// Not public API.
#[cfg(feature = "printing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_keyword {
    ($ident:ident) => {
        impl $crate::__private::ToTokens for $ident {
            fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
                let ident = $crate::Ident::new(stringify!($ident), self.span);
                $crate::__private::TokenStreamExt::append(tokens, ident);
            }
        }
    };
}

// Not public API.
#[cfg(not(feature = "printing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_keyword {
    ($ident:ident) => {};
}

// Not public API.
#[cfg(feature = "clone-impls")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_keyword {
    ($ident:ident) => {
        impl $crate::__private::Copy for $ident {}

        #[allow(clippy::expl_impl_clone_on_copy)]
        impl $crate::__private::Clone for $ident {
            fn clone(&self) -> Self {
                *self
            }
        }
    };
}

// Not public API.
#[cfg(not(feature = "clone-impls"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_keyword {
    ($ident:ident) => {};
}

// Not public API.
#[cfg(feature = "extra-traits")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_keyword {
    ($ident:ident) => {
        impl $crate::__private::Debug for $ident {
            fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
                $crate::__private::Formatter::write_str(
                    f,
                    concat!("Keyword [", stringify!($ident), "]"),
                )
            }
        }

        impl $crate::__private::Eq for $ident {}

        impl $crate::__private::PartialEq for $ident {
            fn eq(&self, _other: &Self) -> $crate::__private::bool {
                true
            }
        }

        impl $crate::__private::Hash for $ident {
            fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
        }
    };
}

// Not public API.
#[cfg(not(feature = "extra-traits"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_keyword {
    ($ident:ident) => {};
}
<commit_msg>Use Some from $crate<commit_after>/// Define a type that supports parsing and printing a given identifier as if it
/// were a keyword.
///
/// # Usage
///
/// As a convention, it is recommended that this macro be invoked within a
/// module called `kw` or `keyword` and that the resulting parser be invoked
/// with a `kw::` or `keyword::` prefix.
///
/// ```
/// mod kw {
///     syn::custom_keyword!(whatever);
/// }
/// ```
///
/// The generated syntax tree node supports the following operations just like
/// any built-in keyword token.
///
/// - [Peeking] — `input.peek(kw::whatever)`
///
/// - [Parsing] — `input.parse::<kw::whatever>()?`
///
/// - [Printing] — `quote!( ... #whatever_token ... )`
///
/// - Construction from a [`Span`] — `let whatever_token = kw::whatever(sp)`
///
/// - Field access to its span — `let sp = whatever_token.span`
///
/// [Peeking]: crate::parse::ParseBuffer::peek
/// [Parsing]: crate::parse::ParseBuffer::parse
/// [Printing]: quote::ToTokens
/// [`Span`]: proc_macro2::Span
///
/// # Example
///
/// This example parses input that looks like `bool = true` or `str = "value"`.
/// The key must be either the identifier `bool` or the identifier `str`. If
/// `bool`, the value may be either `true` or `false`. If `str`, the value may
/// be any string literal.
///
/// The symbols `bool` and `str` are not reserved keywords in Rust so these are
/// not considered keywords in the `syn::token` module. Like any other
/// identifier that is not a keyword, these can be declared as custom keywords
/// by crates that need to use them as such.
///
/// ```
/// use syn::{LitBool, LitStr, Result, Token};
/// use syn::parse::{Parse, ParseStream};
///
/// mod kw {
///     syn::custom_keyword!(bool);
///     syn::custom_keyword!(str);
/// }
///
/// enum Argument {
///     Bool {
///         bool_token: kw::bool,
///         eq_token: Token![=],
///         value: LitBool,
///     },
///     Str {
///         str_token: kw::str,
///         eq_token: Token![=],
///         value: LitStr,
///     },
/// }
///
/// impl Parse for Argument {
///     fn parse(input: ParseStream) -> Result<Self> {
///         let lookahead = input.lookahead1();
///         if lookahead.peek(kw::bool) {
///             Ok(Argument::Bool {
///                 bool_token: input.parse::<kw::bool>()?,
///                 eq_token: input.parse()?,
///                 value: input.parse()?,
///             })
///         } else if lookahead.peek(kw::str) {
///             Ok(Argument::Str {
///                 str_token: input.parse::<kw::str>()?,
///                 eq_token: input.parse()?,
///                 value: input.parse()?,
///             })
///         } else {
///             Err(lookahead.error())
///         }
///     }
/// }
/// ```
#[macro_export]
macro_rules! custom_keyword {
    ($ident:ident) => {
        #[allow(non_camel_case_types)]
        pub struct $ident {
            pub span: $crate::__private::Span,
        }

        #[doc(hidden)]
        #[allow(dead_code, non_snake_case)]
        pub fn $ident<__S: $crate::__private::IntoSpans<[$crate::__private::Span; 1]>>(
            span: __S,
        ) -> $ident {
            $ident {
                span: $crate::__private::IntoSpans::into_spans(span)[0],
            }
        }

        impl $crate::__private::Default for $ident {
            fn default() -> Self {
                $ident {
                    span: $crate::__private::Span::call_site(),
                }
            }
        }

        $crate::impl_parse_for_custom_keyword!($ident);
        $crate::impl_to_tokens_for_custom_keyword!($ident);
        $crate::impl_clone_for_custom_keyword!($ident);
        $crate::impl_extra_traits_for_custom_keyword!($ident);
    };
}

// Not public API.
#[cfg(feature = "parsing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_keyword {
    ($ident:ident) => {
        // For peek.
        impl $crate::token::CustomToken for $ident {
            fn peek(cursor: $crate::buffer::Cursor) -> $crate::__private::bool {
                if let $crate::__private::Some((ident, _rest)) = cursor.ident() {
                    ident == stringify!($ident)
                } else {
                    false
                }
            }

            fn display() -> &'static $crate::__private::str {
                concat!("`", stringify!($ident), "`")
            }
        }

        impl $crate::parse::Parse for $ident {
            fn parse(input: $crate::parse::ParseStream) -> $crate::parse::Result<$ident> {
                input.step(|cursor| {
                    if let $crate::__private::Some((ident, rest)) = cursor.ident() {
                        if ident == stringify!($ident) {
                            return $crate::__private::Ok(($ident { span: ident.span() }, rest));
                        }
                    }
                    $crate::__private::Err(cursor.error(concat!(
                        "expected `",
                        stringify!($ident),
                        "`"
                    )))
                })
            }
        }
    };
}

// Not public API.
#[cfg(not(feature = "parsing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_parse_for_custom_keyword {
    ($ident:ident) => {};
}

// Not public API.
#[cfg(feature = "printing")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_keyword {
    ($ident:ident) => {
        impl $crate::__private::ToTokens for $ident {
            fn to_tokens(&self, tokens: &mut $crate::__private::TokenStream2) {
                let ident = $crate::Ident::new(stringify!($ident), self.span);
                $crate::__private::TokenStreamExt::append(tokens, ident);
            }
        }
    };
}

// Not public API.
#[cfg(not(feature = "printing"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_to_tokens_for_custom_keyword {
    ($ident:ident) => {};
}

// Not public API.
#[cfg(feature = "clone-impls")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_keyword {
    ($ident:ident) => {
        impl $crate::__private::Copy for $ident {}

        #[allow(clippy::expl_impl_clone_on_copy)]
        impl $crate::__private::Clone for $ident {
            fn clone(&self) -> Self {
                *self
            }
        }
    };
}

// Not public API.
#[cfg(not(feature = "clone-impls"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_clone_for_custom_keyword {
    ($ident:ident) => {};
}

// Not public API.
#[cfg(feature = "extra-traits")]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_keyword {
    ($ident:ident) => {
        impl $crate::__private::Debug for $ident {
            fn fmt(&self, f: &mut $crate::__private::Formatter) -> $crate::__private::fmt::Result {
                $crate::__private::Formatter::write_str(
                    f,
                    concat!("Keyword [", stringify!($ident), "]"),
                )
            }
        }

        impl $crate::__private::Eq for $ident {}

        impl $crate::__private::PartialEq for $ident {
            fn eq(&self, _other: &Self) -> $crate::__private::bool {
                true
            }
        }

        impl $crate::__private::Hash for $ident {
            fn hash<__H: $crate::__private::Hasher>(&self, _state: &mut __H) {}
        }
    };
}

// Not public API.
#[cfg(not(feature = "extra-traits"))]
#[doc(hidden)]
#[macro_export]
macro_rules! impl_extra_traits_for_custom_keyword {
    ($ident:ident) => {};
}
<|endoftext|>


<commit_before>extern crate regex;
use self::regex::Regex;
use super::*;

#[test]
fn parse_args_help_works() {
    assert_eq!(parse_args(vec!["-h".to_string()]), Ok(ShowHelp));
    assert_eq!(parse_args(vec!["--help".to_string()]), Ok(ShowHelp));
}

#[test]
fn parse_args_version_works() {
    assert_eq!(parse_args(vec!["-v".to_string()]), Ok(ShowVersion));
    assert_eq!(parse_args(vec!["--version".to_string()]), Ok(ShowVersion));
}

#[test]
fn parse_args_uses_default_string() {
    assert_eq!(parse_args(vec![]), Ok(RepeatString(DEFAULT_STRING.to_string())));
}

#[test]
fn parse_args_uses_arguments() {
    assert_eq!(parse_args(vec!["str".to_string()]),
               Ok(RepeatString("str".to_string())));
}

#[test]
fn parse_args_concatenates_arguments() {
    assert_eq!(parse_args(vec!["str".to_string(), "dup".to_string()]),
               Ok(RepeatString("str dup".to_string())));
}

#[test]
fn parse_args_allows_escaped_flags() {
    assert_eq!(parse_args(vec!["--".to_string(), "-h".to_string()]),
               Ok(RepeatString("-h".to_string())));
}

#[test]
fn parse_args_raises_error_on_illegal_argument() {
    assert!(parse_args(vec!["-g".to_string()]).is_err());
    match parse_args(vec!["--global".to_string()]) {
        Err(InvalidOption(_)) => assert!(true),
        _ => assert!(false)
    }
}

/*
#[test]
fn repeat_buffer_uses_given_word() {
    let buf = repeat_buffer("word");

    // make sure buf only contains the word followed by a newline
    let re = Regex::new(r"^(word\n)+$").unwrap();
    assert!(re.is_match(&buf));
}

#[test]
fn version_text_returns_version() {
    let re = Regex::new(r"^.* version \d+(\.\d+)*.*$").unwrap();
    assert!(re.is_match(&version_text()));
}
*/
<commit_msg>rewrites tests to use the refactoring<commit_after>extern crate regex;
use self::regex::Regex;
use super::*;

#[test]
fn parse_args_help_works() {
    assert_eq!(parse_args(vec!["-h".to_string()]), Ok(ShowHelp));
    assert_eq!(parse_args(vec!["--help".to_string()]), Ok(ShowHelp));
}

#[test]
fn parse_args_version_works() {
    assert_eq!(parse_args(vec!["-v".to_string()]), Ok(ShowVersion));
    assert_eq!(parse_args(vec!["--version".to_string()]), Ok(ShowVersion));
}

#[test]
fn parse_args_uses_default_string() {
    assert_eq!(parse_args(vec![]), Ok(RepeatString(DEFAULT_STRING.to_string())));
}

#[test]
fn parse_args_uses_arguments() {
    assert_eq!(parse_args(vec!["str".to_string()]),
               Ok(RepeatString("str".to_string())));
}

#[test]
fn parse_args_concatenates_arguments() {
    assert_eq!(parse_args(vec!["str".to_string(), "dup".to_string()]),
               Ok(RepeatString("str dup".to_string())));
}

#[test]
fn parse_args_allows_escaped_flags() {
    assert_eq!(parse_args(vec!["--".to_string(), "-h".to_string()]),
               Ok(RepeatString("-h".to_string())));
}

#[test]
fn parse_args_raises_error_on_illegal_argument() {
    assert!(parse_args(vec!["-g".to_string()]).is_err());
    match parse_args(vec!["--global".to_string()]) {
        Err(InvalidOption(_)) => assert!(true),
        _ => assert!(false)
    }
}

#[test]
fn string_newline_terminate_works() {
    assert_eq!("word".to_string().newline_terminate(), "word\n");
    assert_eq!("myname".to_string().newline_terminate(), "myname\n");
}

#[test]
fn string_fill_works() {
    let max = 1500;
    let buf = "myword\n".to_string().fill(max);

    // make sure string isn't too long
    assert!(buf.len() <= max);

    // make sure buf only contains the word followed by a newline
    let re = Regex::new(r"^(myword\n)+$").unwrap();
    assert!(re.is_match(&buf));
}

#[test]
fn version_text_returns_version() {
    let re = Regex::new(r"^.* version \d+(\.\d+)*.*$").unwrap();
    assert!(re.is_match(&version_text()));
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](http://kentonv.github.io/capnproto/) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![feature(alloc, io, core, unsafe_destructor)]
#![allow(raw_pointer_derive)]

#![crate_name="capnp"]
#![crate_type = "lib"]

// reexports
pub use common::{MessageSize, Word};
pub use message::{MessageBuilder, BuilderOptions, MessageReader, ReaderOptions};
pub use message::MallocMessageBuilder;
pub use serialize::OwnedSpaceMessageReader;

pub mod any_pointer;
pub mod capability;
mod common;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod private;
pub mod io;
pub mod list;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;
<commit_msg>mod list does not exist anymore<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Runtime Library
//!
//! [Cap'n Proto](http://kentonv.github.io/capnproto/) is an extremely efficient protocol for
//! sharing data and capabilities.
//!
//! The Rust implementation is split into three separate crates.
//!
//! Code generation is handled by [capnpc-rust](https://github.com/dwrensha/capnpc-rust).
//!
//! The present crate is the runtime library required by that generated code. It is hosted on Github
//! [here](https://github.com/dwrensha/capnproto-rust).
//!
//! [capnp-rpc-rust](https://github.com/dwrensha/capnp-rpc-rust) is an implementation of a
//! distributed object-capability layer.

#![feature(alloc, io, core, unsafe_destructor)]
#![allow(raw_pointer_derive)]

#![crate_name="capnp"]
#![crate_type = "lib"]

// reexports
pub use common::{MessageSize, Word};
pub use message::{MessageBuilder, BuilderOptions, MessageReader, ReaderOptions};
pub use message::MallocMessageBuilder;
pub use serialize::OwnedSpaceMessageReader;

pub mod any_pointer;
pub mod capability;
mod common;
pub mod data;
pub mod data_list;
pub mod enum_list;
pub mod private;
pub mod io;
pub mod list_list;
pub mod message;
pub mod primitive_list;
pub mod serialize;
pub mod serialize_packed;
pub mod struct_list;
pub mod text;
pub mod text_list;
pub mod traits;
<|endoftext|>


<commit_before>use std::cmp::Ordering::{self, Less, Equal, Greater};
use std::num::Float;
use std::num::Int;
use std::num::ToPrimitive;
use std::num::FromPrimitive;

/// Clamp a value between a given min and max.
pub fn clamp<T: Float + PartialOrd>(n: T, min: T, max: T) -> T {
    if n < min { min } else if n > max { max } else { n }
}

/// Clamp a f32 between 0f32 and 1f32.
pub fn clampf32(f: f32) -> f32 {
    if f < 0f32 { 0f32 } else if f > 1f32 { 1f32 } else { f }
}

/// Compare two f64s and return an Ordering.
pub fn compare_f64s(a: f64, b: f64) -> Ordering {
    if a > b { Greater }
    else if a < b { Less }
    else { Equal }
}

/// Get value percentage between max and min.
pub fn percentage<T: Float + Copy + FromPrimitive + ToPrimitive>
    (value: T, min: T, max: T) -> f32 {
    let v = value.to_f32().unwrap();
    let mn = min.to_f32().unwrap();
    let mx = max.to_f32().unwrap();
    (v - mn) / (mx - mn)
}

/// Adjust the value to the given percentage.
pub fn value_from_perc<T: Float + Copy + FromPrimitive + ToPrimitive>
    (perc: f32, min: T, max: T) -> T {
    min + FromPrimitive::from_f32((max - min).to_f32().unwrap() * perc).unwrap()
}

/// Map a value from a given range to a new given range.
pub fn map_range<X: Float + Copy + FromPrimitive + ToPrimitive,
                 Y: Float + Copy + FromPrimitive + ToPrimitive>
(val: X, in_min: X, in_max: X, out_min: Y, out_max: Y) -> Y {
    let (val_f, in_min_f, in_max_f, out_min_f, out_max_f) = (
        val.to_f64().unwrap(),
        in_min.to_f64().unwrap(),
        in_max.to_f64().unwrap(),
        out_min.to_f64().unwrap(),
        out_max.to_f64().unwrap(),
    );
    FromPrimitive::from_f64(
        (val_f - in_min_f) / (in_max_f - in_min_f) * (out_max_f - out_min_f) + out_min_f
    ).unwrap()
}

/// Get a suitable string from the value, its max and the pixel range.
pub fn val_to_string<T: ToString + ToPrimitive>
(val: T, max: T, val_rng: T, pixel_range: usize) -> String {
    let mut s = val.to_string();
    let decimal = s.as_slice().chars().position(|ch| ch == '.');
    match decimal {
        None => s,
        Some(idx) => {
            // Find the minimum string length by determing
            // what power of ten both the max and range are.
            let val_rng_f = val_rng.to_f64().unwrap();
            let max_f = max.to_f64().unwrap();
            let mut n: f64 = 0.0;
            let mut pow_ten = 0.0;
            while pow_ten < val_rng_f || pow_ten < max_f {
                pow_ten = (10.0).powf(n);
                n += 1.0
            }
            let min_string_len = n as usize + 1;

            // Find out how many pixels there are to actually use
            // and judge a reasonable precision from this.
            let mut n: usize = 1;
            while 10.pow(n) < pixel_range { n += 1 }
            let precision = n;

            // Truncate the length to the pixel precision as
            // long as this doesn't cause it to be smaller
            // than the necessary decimal place.
            let mut truncate_len = min_string_len + (precision - 1);
            if idx + precision < truncate_len { truncate_len = idx + precision }
            if s.len() > truncate_len { s.truncate(truncate_len) }
            s
        }
    }
}

<commit_msg>Update to latest rust<commit_after>use std::cmp::Ordering::{self, Less, Equal, Greater};
use std::num::Float;
use std::num::Int;
use std::num::ToPrimitive;
use std::num::FromPrimitive;

/// Clamp a value between a given min and max.
pub fn clamp<T: Float + PartialOrd>(n: T, min: T, max: T) -> T {
    if n < min { min } else if n > max { max } else { n }
}

/// Clamp a f32 between 0f32 and 1f32.
pub fn clampf32(f: f32) -> f32 {
    if f < 0f32 { 0f32 } else if f > 1f32 { 1f32 } else { f }
}

/// Compare two f64s and return an Ordering.
pub fn compare_f64s(a: f64, b: f64) -> Ordering {
    if a > b { Greater }
    else if a < b { Less }
    else { Equal }
}

/// Get value percentage between max and min.
pub fn percentage<T: Float + Copy + FromPrimitive + ToPrimitive>
    (value: T, min: T, max: T) -> f32 {
    let v = value.to_f32().unwrap();
    let mn = min.to_f32().unwrap();
    let mx = max.to_f32().unwrap();
    (v - mn) / (mx - mn)
}

/// Adjust the value to the given percentage.
pub fn value_from_perc<T: Float + Copy + FromPrimitive + ToPrimitive>
    (perc: f32, min: T, max: T) -> T {
    min + FromPrimitive::from_f32((max - min).to_f32().unwrap() * perc).unwrap()
}

/// Map a value from a given range to a new given range.
pub fn map_range<X: Float + Copy + FromPrimitive + ToPrimitive,
                 Y: Float + Copy + FromPrimitive + ToPrimitive>
(val: X, in_min: X, in_max: X, out_min: Y, out_max: Y) -> Y {
    let (val_f, in_min_f, in_max_f, out_min_f, out_max_f) = (
        val.to_f64().unwrap(),
        in_min.to_f64().unwrap(),
        in_max.to_f64().unwrap(),
        out_min.to_f64().unwrap(),
        out_max.to_f64().unwrap(),
    );
    FromPrimitive::from_f64(
        (val_f - in_min_f) / (in_max_f - in_min_f) * (out_max_f - out_min_f) + out_min_f
    ).unwrap()
}

/// Get a suitable string from the value, its max and the pixel range.
pub fn val_to_string<T: ToString + ToPrimitive>
(val: T, max: T, val_rng: T, pixel_range: usize) -> String {
    let mut s = val.to_string();
    let decimal = s.as_slice().chars().position(|ch| ch == '.');
    match decimal {
        None => s,
        Some(idx) => {
            // Find the minimum string length by determing
            // what power of ten both the max and range are.
            let val_rng_f = val_rng.to_f64().unwrap();
            let max_f = max.to_f64().unwrap();
            let mut n: f64 = 0.0;
            let mut pow_ten = 0.0;
            while pow_ten < val_rng_f || pow_ten < max_f {
                pow_ten = (10.0).powf(n);
                n += 1.0
            }
            let min_string_len = n as usize + 1;

            // Find out how many pixels there are to actually use
            // and judge a reasonable precision from this.
            let mut n = 1;
            while 10.pow(n) < pixel_range { n += 1 }
            let precision = n as usize;

            // Truncate the length to the pixel precision as
            // long as this doesn't cause it to be smaller
            // than the necessary decimal place.
            let mut truncate_len = min_string_len + (precision - 1);
            if idx + precision < truncate_len { truncate_len = idx + precision }
            if s.len() > truncate_len { s.truncate(truncate_len) }
            s
        }
    }
}

<|endoftext|>


<commit_before>use alloc::collections::VecDeque;
use alloc::vec::Vec;
use core::fmt::Write;
use core::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
use log::{Level, Metadata, Record};
use spin::Mutex;

/// Disable logging directly to the built-in vga buffer.
/// This MUST NOT BE done before memory map has been initialized,
/// or it causes page faults. (Requires allocation)
static DISABLE_DIRECT_VGA: AtomicBool = AtomicBool::new(false);

pub fn disable_direct_vga() {
    DISABLE_DIRECT_VGA.store(true, Ordering::Release);
}

/********************************* PORT E9 ***********************************/

struct PortE9;

static PORT: Mutex<cpuio::UnsafePort<u8>> = Mutex::new(unsafe { cpuio::UnsafePort::new(0xe9) });

/// Allow formatting
impl ::core::fmt::Write for PortE9 {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        let mut port = PORT.lock();
        unsafe {
            for byte in s.bytes() {
                assert!(byte != 0);
                if byte == b'\n' {
                    port.write(b'\r');
                    port.write(b'\n');
                } else if 0x20 <= byte && byte <= 0x7e {
                    port.write(byte);
                } else {
                    port.write(b'?');
                    bochs_magic_bp!();
                    loop {
                        unsafe {
                            asm!("cli; hlt");
                        }
                    }
                }
            }
        }
        Ok(()) // Success. Always.
    }
}

static mut PORT_E9: PortE9 = PortE9;

macro_rules! e9_print {
    ($fmt:expr, $($arg:tt)*) => (
        unsafe {
            PORT_E9.write_fmt(format_args!(concat!($fmt, "\n"), $($arg)*)).unwrap()
        }
    );
}

/******************************* UART SERIAL *********************************/

static UART_LOCK: AtomicBool = AtomicBool::new(false);

struct Uart;

/// Allow formatting
impl ::core::fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        use crate::driver::uart::{has_com1, write_com1};
        if has_com1() {
            // Acquire lock
            while UART_LOCK
                .compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::SeqCst)
                .is_err()
            {
                spin_loop_hint();
            }

            for byte in s.bytes() {
                assert!(byte != 0);
                if byte == b'\n' {
                    write_com1(b'\r');
                    write_com1(b'\n');
                } else if 0x20 <= byte && byte <= 0x7e {
                    write_com1(byte);
                } else {
                    write_com1(b'?');
                    bochs_magic_bp!();
                    loop {
                        unsafe {
                            asm!("cli; hlt");
                        }
                    }
                }
            }

            // Release lock
            UART_LOCK.store(false, Ordering::SeqCst);
        }
        Ok(()) // Success. Always.
    }
}

static mut UART: Uart = Uart;

macro_rules! uart_print {
    ($fmt:expr, $($arg:tt)*) => (
        unsafe {
            UART.write_fmt(format_args!(concat!($fmt, "\n"), $($arg)*)).unwrap()
        }
    );
}

/**************************** BUFFER + SYSCALL *******************************/

lazy_static::lazy_static! {
    /// Write ahead log for kernel log messages
    static ref WRITE_AHEAD_LOG: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
}

pub fn syscall_read(buffer: &mut [u8]) -> usize {
    let mut wal = WRITE_AHEAD_LOG.try_lock().unwrap();
    let count = wal.len().min(buffer.len());
    for (i, b) in wal.drain(..count).enumerate() {
        buffer[i] = b;
    }
    count
}

/***************************** LOGGER ITSELF ********************************/

struct SystemLogger;

// pub const LEVEL_SCREEN: log::Level = log::Level::Info;
pub const LEVEL_SCREEN: log::Level = log::Level::Debug;
pub const LEVEL_PORTE9: log::Level = log::Level::Trace;
// pub const LEVEL_PORTE9: log::Level = log::Level::Debug;

impl log::Log for SystemLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= LEVEL_SCREEN || metadata.level() <= LEVEL_PORTE9
    }

    fn log(&self, record: &Record) {
        let level = record.metadata().level();
        if level <= LEVEL_PORTE9 {
            e9_print!(
                "{:30} [{}] {:5} {}",
                record.target(),
                crate::smp::current_processor_id(),
                record.level(),
                record.args()
            );

            uart_print!(
                "{:30} [{}] {:5} {}",
                record.target(),
                crate::smp::current_processor_id(),
                record.level(),
                record.args()
            );
        }
        if level <= LEVEL_SCREEN {
            if crate::memory::can_allocate() {
                let message = format!(
                    "{:5} {} - {}\n",
                    record.level(),
                    record.target(),
                    record.args()
                );
                let mut wal = WRITE_AHEAD_LOG.lock();
                wal.extend(message.bytes());
            }

            if !DISABLE_DIRECT_VGA.load(Ordering::Acquire) {
                rprintln!(
                    "{:5} {} - {}",
                    record.level(),
                    record.target(),
                    record.args()
                );
            }
        }
    }

    fn flush(&self) {}
}

static LOGGER: SystemLogger = SystemLogger;

pub fn enable() {
    log::set_logger(&LOGGER).unwrap();
    log::set_max_level(log::LevelFilter::Trace);
}
<commit_msg>Replace deprecaded spin_loop_hint with hint::spin_loop<commit_after>use alloc::collections::VecDeque;
use alloc::vec::Vec;
use core::fmt::Write;
use core::sync::atomic::{AtomicBool, Ordering};
use core::hint;
use log::{Level, Metadata, Record};
use spin::Mutex;

/// Disable logging directly to the built-in vga buffer.
/// This MUST NOT BE done before memory map has been initialized,
/// or it causes page faults. (Requires allocation)
static DISABLE_DIRECT_VGA: AtomicBool = AtomicBool::new(false);

pub fn disable_direct_vga() {
    DISABLE_DIRECT_VGA.store(true, Ordering::Release);
}

/********************************* PORT E9 ***********************************/

struct PortE9;

static PORT: Mutex<cpuio::UnsafePort<u8>> = Mutex::new(unsafe { cpuio::UnsafePort::new(0xe9) });

/// Allow formatting
impl ::core::fmt::Write for PortE9 {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        let mut port = PORT.lock();
        unsafe {
            for byte in s.bytes() {
                assert!(byte != 0);
                if byte == b'\n' {
                    port.write(b'\r');
                    port.write(b'\n');
                } else if 0x20 <= byte && byte <= 0x7e {
                    port.write(byte);
                } else {
                    port.write(b'?');
                    bochs_magic_bp!();
                    loop {
                        unsafe {
                            asm!("cli; hlt");
                        }
                    }
                }
            }
        }
        Ok(()) // Success. Always.
    }
}

static mut PORT_E9: PortE9 = PortE9;

macro_rules! e9_print {
    ($fmt:expr, $($arg:tt)*) => (
        unsafe {
            PORT_E9.write_fmt(format_args!(concat!($fmt, "\n"), $($arg)*)).unwrap()
        }
    );
}

/******************************* UART SERIAL *********************************/

static UART_LOCK: AtomicBool = AtomicBool::new(false);

struct Uart;

/// Allow formatting
impl ::core::fmt::Write for Uart {
    fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
        use crate::driver::uart::{has_com1, write_com1};
        if has_com1() {
            // Acquire lock
            while UART_LOCK
                .compare_exchange_weak(false, true, Ordering::SeqCst, Ordering::SeqCst)
                .is_err()
            {
                hint::spin_loop();
            }

            for byte in s.bytes() {
                assert!(byte != 0);
                if byte == b'\n' {
                    write_com1(b'\r');
                    write_com1(b'\n');
                } else if 0x20 <= byte && byte <= 0x7e {
                    write_com1(byte);
                } else {
                    write_com1(b'?');
                    bochs_magic_bp!();
                    loop {
                        unsafe {
                            asm!("cli; hlt");
                        }
                    }
                }
            }

            // Release lock
            UART_LOCK.store(false, Ordering::SeqCst);
        }
        Ok(()) // Success. Always.
    }
}

static mut UART: Uart = Uart;

macro_rules! uart_print {
    ($fmt:expr, $($arg:tt)*) => (
        unsafe {
            UART.write_fmt(format_args!(concat!($fmt, "\n"), $($arg)*)).unwrap()
        }
    );
}

/**************************** BUFFER + SYSCALL *******************************/

lazy_static::lazy_static! {
    /// Write ahead log for kernel log messages
    static ref WRITE_AHEAD_LOG: Mutex<VecDeque<u8>> = Mutex::new(VecDeque::new());
}

pub fn syscall_read(buffer: &mut [u8]) -> usize {
    let mut wal = WRITE_AHEAD_LOG.try_lock().unwrap();
    let count = wal.len().min(buffer.len());
    for (i, b) in wal.drain(..count).enumerate() {
        buffer[i] = b;
    }
    count
}

/***************************** LOGGER ITSELF ********************************/

struct SystemLogger;

// pub const LEVEL_SCREEN: log::Level = log::Level::Info;
pub const LEVEL_SCREEN: log::Level = log::Level::Debug;
pub const LEVEL_PORTE9: log::Level = log::Level::Trace;
// pub const LEVEL_PORTE9: log::Level = log::Level::Debug;

impl log::Log for SystemLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= LEVEL_SCREEN || metadata.level() <= LEVEL_PORTE9
    }

    fn log(&self, record: &Record) {
        let level = record.metadata().level();
        if level <= LEVEL_PORTE9 {
            e9_print!(
                "{:30} [{}] {:5} {}",
                record.target(),
                crate::smp::current_processor_id(),
                record.level(),
                record.args()
            );

            uart_print!(
                "{:30} [{}] {:5} {}",
                record.target(),
                crate::smp::current_processor_id(),
                record.level(),
                record.args()
            );
        }
        if level <= LEVEL_SCREEN {
            if crate::memory::can_allocate() {
                let message = format!(
                    "{:5} {} - {}\n",
                    record.level(),
                    record.target(),
                    record.args()
                );
                let mut wal = WRITE_AHEAD_LOG.lock();
                wal.extend(message.bytes());
            }

            if !DISABLE_DIRECT_VGA.load(Ordering::Acquire) {
                rprintln!(
                    "{:5} {} - {}",
                    record.level(),
                    record.target(),
                    record.args()
                );
            }
        }
    }

    fn flush(&self) {}
}

static LOGGER: SystemLogger = SystemLogger;

pub fn enable() {
    log::set_logger(&LOGGER).unwrap();
    log::set_max_level(log::LevelFilter::Trace);
}
<|endoftext|>


<commit_before>use std::{
    env,
    path::{Path, PathBuf},
};

pub static BACKUP_CONTROL_VALUES: &[&str] = &[
    "simple", "never", "numbered", "t", "existing", "nil", "none", "off",
];

pub static BACKUP_CONTROL_LONG_HELP: &str = "The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX. Here are the version control values:

none, off
    never make backups (even if --backup is given)

numbered, t
    make numbered backups

existing, nil
    numbered if numbered backups exist, simple otherwise

simple, never
    always make simple backups";

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum BackupMode {
    NoBackup,
    SimpleBackup,
    NumberedBackup,
    ExistingBackup,
}

pub fn determine_backup_suffix(supplied_suffix: Option<&str>) -> String {
    if let Some(suffix) = supplied_suffix {
        String::from(suffix)
    } else {
        env::var("SIMPLE_BACKUP_SUFFIX").unwrap_or_else(|_| "~".to_owned())
    }
}

pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>) -> BackupMode {
    if backup_opt_exists {
        match backup_opt.map(String::from) {
            // default is existing, see:
            // https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
            None => BackupMode::ExistingBackup,
            Some(mode) => match &mode[..] {
                "simple" | "never" => BackupMode::SimpleBackup,
                "numbered" | "t" => BackupMode::NumberedBackup,
                "existing" | "nil" => BackupMode::ExistingBackup,
                "none" | "off" => BackupMode::NoBackup,
                _ => panic!(), // cannot happen as it is managed by clap
            },
        }
    } else {
        BackupMode::NoBackup
    }
}

pub fn get_backup_path(
    backup_mode: BackupMode,
    backup_path: &Path,
    suffix: &str,
) -> Option<PathBuf> {
    match backup_mode {
        BackupMode::NoBackup => None,
        BackupMode::SimpleBackup => Some(simple_backup_path(backup_path, suffix)),
        BackupMode::NumberedBackup => Some(numbered_backup_path(backup_path)),
        BackupMode::ExistingBackup => Some(existing_backup_path(backup_path, suffix)),
    }
}

pub fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let mut p = path.to_string_lossy().into_owned();
    p.push_str(suffix);
    PathBuf::from(p)
}

pub fn numbered_backup_path(path: &Path) -> PathBuf {
    for i in 1_u64.. {
        let path_str = &format!("{}.~{}~", path.to_string_lossy(), i);
        let path = Path::new(path_str);
        if !path.exists() {
            return path.to_path_buf();
        }
    }
    panic!("cannot create backup")
}

pub fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let test_path_str = &format!("{}.~1~", path.to_string_lossy());
    let test_path = Path::new(test_path_str);
    if test_path.exists() {
        numbered_backup_path(path)
    } else {
        simple_backup_path(path, suffix)
    }
}
<commit_msg>backup_control: Add todo for gnu compliant behavior<commit_after>use std::{
    env,
    path::{Path, PathBuf},
};

pub static BACKUP_CONTROL_VALUES: &[&str] = &[
    "simple", "never", "numbered", "t", "existing", "nil", "none", "off",
];

pub static BACKUP_CONTROL_LONG_HELP: &str = "The backup suffix is '~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX. Here are the version control values:

none, off
    never make backups (even if --backup is given)

numbered, t
    make numbered backups

existing, nil
    numbered if numbered backups exist, simple otherwise

simple, never
    always make simple backups";

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum BackupMode {
    NoBackup,
    SimpleBackup,
    NumberedBackup,
    ExistingBackup,
}

pub fn determine_backup_suffix(supplied_suffix: Option<&str>) -> String {
    if let Some(suffix) = supplied_suffix {
        String::from(suffix)
    } else {
        env::var("SIMPLE_BACKUP_SUFFIX").unwrap_or_else(|_| "~".to_owned())
    }
}

/// # TODO
///
/// This function currently deviates slightly from how the [manual][1] describes
/// that it should work. In particular, the current implementation:
///
/// 1. Doesn't strictly respect the order in which to determine the backup type,
///    which is (in order of precedence)
///     1. Take a valid value to the '--backup' option
///     2. Take the value of the `VERSION_CONTROL` env var
///     3. default to 'existing'
/// 2. Doesn't accept abbreviations to the 'backup_option' parameter
///
/// [1]: https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
pub fn determine_backup_mode(backup_opt_exists: bool, backup_opt: Option<&str>) -> BackupMode {
    if backup_opt_exists {
        match backup_opt.map(String::from) {
            // default is existing, see:
            // https://www.gnu.org/software/coreutils/manual/html_node/Backup-options.html
            None => BackupMode::ExistingBackup,
            Some(mode) => match &mode[..] {
                "simple" | "never" => BackupMode::SimpleBackup,
                "numbered" | "t" => BackupMode::NumberedBackup,
                "existing" | "nil" => BackupMode::ExistingBackup,
                "none" | "off" => BackupMode::NoBackup,
                _ => panic!(), // cannot happen as it is managed by clap
            },
        }
    } else {
        BackupMode::NoBackup
    }
}

pub fn get_backup_path(
    backup_mode: BackupMode,
    backup_path: &Path,
    suffix: &str,
) -> Option<PathBuf> {
    match backup_mode {
        BackupMode::NoBackup => None,
        BackupMode::SimpleBackup => Some(simple_backup_path(backup_path, suffix)),
        BackupMode::NumberedBackup => Some(numbered_backup_path(backup_path)),
        BackupMode::ExistingBackup => Some(existing_backup_path(backup_path, suffix)),
    }
}

pub fn simple_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let mut p = path.to_string_lossy().into_owned();
    p.push_str(suffix);
    PathBuf::from(p)
}

pub fn numbered_backup_path(path: &Path) -> PathBuf {
    for i in 1_u64.. {
        let path_str = &format!("{}.~{}~", path.to_string_lossy(), i);
        let path = Path::new(path_str);
        if !path.exists() {
            return path.to_path_buf();
        }
    }
    panic!("cannot create backup")
}

pub fn existing_backup_path(path: &Path, suffix: &str) -> PathBuf {
    let test_path_str = &format!("{}.~1~", path.to_string_lossy());
    let test_path = Path::new(test_path_str);
    if test_path.exists() {
        numbered_backup_path(path)
    } else {
        simple_backup_path(path, suffix)
    }
}
<|endoftext|>