<commit_before>use clientbound::ClientboundPacket;
use serverbound::ServerboundPacket;
use connection::Connection;
use {ClientState, PROTOCOL_VERSION, mojang, serverbound};
use json::AuthenticationResponse;

use std::{io, thread, time};

/// Represents a single client connection to a Server.
pub struct Client {
    conn: Connection<ClientboundPacket, ServerboundPacket>,
    auto_handle: bool,
    hide_handled: bool,
}
impl Client {
    /// Attempt open the tcp connection to the given host and port, and
    /// nothing more. If you use this you must then send all subsequent
    /// packets manually to authenticate and so on.
    pub fn connect_tcp(host: &str, port: u16) -> io::Result<Self> {
        Ok(Client {
               conn: Connection::connect_tcp(host, port)?,
               auto_handle: false,
               hide_handled: false,
           })
    }

    /// Attempt to connect to the server at the given host and port,
    /// completing the usual steps for an unauthenticated login.
    ///
    /// In most cases this is what you will want for offline/local servers
    /// and singleplayer. This will establish an unencrypted connection
    /// to the server.
    ///
    /// The username is the Minecraft username, and not the Mojang username,
    /// (i.e. NOT the email address for migrated accounts.)
    ///
    /// This will set auto_handle and hide_handled to true.
    ///
    /// This will return Ok(Client) on receival of a PlayerAbilities packet,
    /// but note that the PlayerAbilities packet and all packets received before
    /// it will not be available for consumers. If you need any of those
    /// packets, you will want to do the authentication manually.
    ///
    /// This function will time out after 30 seconds (theoretical absolute worst
    /// case 60 seconds.)
    pub fn connect_unauthenticated(host: &str,
                                   port: u16,
                                   username: &str)
                                   -> io::Result<Self> {

        let timeout = time::Instant::now();
        let mut client = Client::connect_tcp(host, port)?;
        client.set_auto_handle(true);
        client.set_hide_handled(true);
        let handshake = serverbound::Handshake::new(PROTOCOL_VERSION,
                                                    host.to_string(),
                                                    port,
                                                    2);
        let loginstart = serverbound::LoginStart::new(username.to_string());
        client.send(handshake)?;
        client.set_clientstate(ClientState::Login);
        client.send(loginstart)?;

        /* Now we wait for the PlayerAbilities packet from the server */
        'wait: loop {
            if timeout.elapsed() > time::Duration::new(30, 0) {
                return io_error!("Timed out waiting for LoginSuccess/EncryptionRequest");
            }
            client.update_inbuf()?;
            match client.read_packet()? {
                Some(ClientboundPacket::LoginDisconnect(ref p)) => {
                    return io_error!("Got LoginDisconnect, reason: {}",
                                     p.get_raw_chat());
                },
                Some(ClientboundPacket::PlayerAbilities(..)) => break 'wait,
                Some(ClientboundPacket::EncryptionRequest(..)) => {
                    return io_error!("connect_unauthenticated got EncryptionRequest");
                },
                Some(_) => (),
                None => thread::sleep(time::Duration::from_millis(10)),
            }
        }

        Ok(client)
    }

    /// Authenticate with Mojang, and then connect to the server at the
    /// given host and port. In most cases this is what you will want to use
    /// to connect to online servers.
    ///
    /// This will establish an encrypted connection to the server.
    ///
    /// Requires that you've already authenticated with Mojang, e.g. by calling
    /// yggdrasil::authenticate
    ///
    /// This will set auto_handle and hide_handled to true.
    ///
    /// This will return Ok(Client) on receival of a PlayerAbilities packet,
    /// but note that the PlayerAbilities packet and all packets received before
    /// it will not be available for consumers. If you need any of those
    /// packets, you will want to do the authentication manually.
    ///
    /// This function will time out after 30 seconds (theoretical absolute worst
    /// case 60 seconds.)
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// use ozelot::{mojang, Client};
    /// let auth = mojang::Authenticate::new("my_email@example.com".to_string(),
    ///                                      "my_password".to_string())
    ///     .perform().unwrap();
    /// let mut client = Client::connect_authenticated("minecraft.example.com",
    /// 25565,
    /// &auth).unwrap();
    /// ```
    pub fn connect_authenticated(host: &str,
                                 port: u16,
                                 auth: &AuthenticationResponse)
                                 -> io::Result<Self> {

        let timeout = time::Instant::now();
        let mut client = Client::connect_tcp(host, port)?;
        client.set_auto_handle(true);
        client.set_hide_handled(true);
        let handshake = serverbound::Handshake::new(PROTOCOL_VERSION,
                                                    host.to_string(),
                                                    port,
                                                    2);
        let loginstart =
            serverbound::LoginStart::new(auth.selectedProfile.name.clone());
        client.send(handshake)?;
        client.set_clientstate(ClientState::Login);
        client.send(loginstart)?;

        /* Here we wait for a LoginSuccess/EncryptionRequest packet */
        'wait: loop {
            if timeout.elapsed() > time::Duration::new(30, 0) {
                return io_error!("Timed out waiting for LoginSuccess/EncryptionRequest");
            }
            client.update_inbuf()?;
            match client.read_packet()? {
                Some(ClientboundPacket::LoginDisconnect(ref p)) => {
                    return io_error!("Got LoginDisconnect, reason: {}",
                                     p.get_raw_chat());
                },
                Some(ClientboundPacket::LoginSuccess(..)) => return io_error!("Logged in unauthenticated"),
                Some(ClientboundPacket::EncryptionRequest(ref p)) => {
                    let shared_secret = mojang::create_shared_secret();

                    mojang::SessionJoin::new(auth.accessToken.clone(),
                                             auth.selectedProfile.id.clone(),
                                             p.get_server_id(),
                                             &shared_secret,
                                             p.get_public_key()).perform()?;

                    let encryptionresponse
                            = serverbound::EncryptionResponse::new_unencrypted(
                                &p.get_public_key(),
                                &shared_secret,
                                &p.get_verify_token())?;
                    client.send(encryptionresponse)?;
                    client.enable_encryption(&shared_secret);

                    break 'wait;
                },
                Some(_) => (),
                None => thread::sleep(time::Duration::from_millis(10)),
            }
        }

        /* Now we wait for the PlayerAbilities packet from the server */
        'wait2: loop {
            if timeout.elapsed() > time::Duration::new(30, 0) {
                return io_error!("Timed out waiting for PlayerAbilities packet");
            }
            client.update_inbuf()?;
            match client.read_packet()? {
                Some(ClientboundPacket::LoginDisconnect(ref p)) => {
                    return io_error!("Got LoginDisconnect, reason: {}",
                                     p.get_raw_chat());
                },
                Some(ClientboundPacket::PlayerAbilities(..)) => break 'wait2,
                Some(_) => (),
                None => thread::sleep(time::Duration::from_millis(10)),
            }
        }

        Ok(client)
    }

    /// Try to read some packets from the server.
    ///
    /// This function may in rare circumstances block for up to 30 seconds,
    /// specifically the timeout for reading the TcpStream is 30 seconds,
    /// so if the tcp connection is lost, it will block until the timeout.
    /// During normal back and forth with a server it should return as fast as
    /// possible.
    pub fn read(&mut self) -> io::Result<Vec<ClientboundPacket>> {
        self.update_inbuf()?;

        let mut ret = Vec::new();
        loop {
            let packet = self.read_packet()?;
            /* push = whether to push the packet to ret */
            let mut push = match &packet {
                &Some(ClientboundPacket::LoginSuccess(_)) => false,
                &Some(ClientboundPacket::SetCompression(_)) => false,
                &Some(ClientboundPacket::KeepAlive(_)) => false,
                &Some(_) => true,
                &None => break,
            };
            if self.hide_handled == false || self.auto_handle == false {
                push = true;
            }

            if push {
                ret.push(packet
                         .expect("unreachable packet = None in client.read()"));
            }
        }

        Ok(ret)
    }

    /// Send the given packet to the server that we're connected to.
    pub fn send(&mut self, packet: ServerboundPacket) -> io::Result<()> {
        self.conn.send(packet)
    }

    /// Whether to automatically handle: KeepAlive, LoginSuccess and
    /// SetCompression packets. Most clients won't need to manually deal with
    /// these.
    pub fn set_auto_handle(&mut self, new: bool) {
        self.auto_handle = new;
    }

    /// Whether or not to hide packets that have been handled by ozelot from the
    /// consumer of the library.
    ///
    /// E.g. KeepAlives that are automatically handled if auto_handle = true.
    pub fn set_hide_handled(&mut self, new: bool) {
        self.hide_handled = new;
    }

    /// Attempt to close this connection, disconnecting from the server.
    ///
    /// All future sends and reads to this connection will fail.
    pub fn close(&mut self) -> io::Result<()> {
        self.conn.close()
    }

    /// Change the client state of this connection
    pub fn set_clientstate(&mut self, new_state: ClientState) {
        self.conn.set_clientstate(new_state)
    }

    /// Enable encryption with the given key.
    ///
    /// It is an error to enable encryption if encryption has already been
    /// enabled.
    pub fn enable_encryption(&mut self, key: &[u8; 16]) {
        self.conn.enable_encryption(key)
    }

    /// Enable compression.
    ///
    /// It is generally an error to enable compression if compression has
    /// already been enabled.
    pub fn enable_compression(&mut self, threshold: usize) {
        self.conn.enable_compression(threshold)
    }

    /// Read from the TcpStream and update the incoming buffer.
    ///
    /// This is the only way to actually read from the TcpStream. Unless you
    /// know for sure you need to call this, then you do not need to call this.
    /// I.e. if you're just using client.read(), then you do not need to call
    /// this function.
    pub fn update_inbuf(&mut self) -> io::Result<()> {
        self.conn.update_inbuf()
    }

    /// Read a single packet from the internal buffer.
    ///
    /// This is only really useful if you want finegrained control over the
    /// processing of packets, or if you want to manually authenticate with
    /// the server. In most cases, you'll want to just call client.read().
    ///
    /// You MUST be sure that client.update_inbuf() has been called before this,
    /// this function will not attempt to read from the TcpStream, only from the
    /// internal buffer.
    pub fn read_packet(&mut self) -> io::Result<Option<ClientboundPacket>> {
        let packet = self.conn.read_packet()?;

        if self.auto_handle {
            match &packet {
                &Some(ClientboundPacket::LoginSuccess(..)) => {
                    self.set_clientstate(ClientState::Play);
                },
                &Some(ClientboundPacket::SetCompression(ref p)) => {
                    self.enable_compression(*p.get_threshold() as usize);
                },
                &Some(ClientboundPacket::KeepAlive(ref p)) => {
                    let keepalive = serverbound::KeepAlive::new(*p.get_id());
                    self.send(keepalive)?;
                },
                _ => (),
            }
        }

        Ok(packet)
    }
}
<commit_msg>docs: Update Client doc about nonblocking functions<commit_after>use clientbound::ClientboundPacket;
use serverbound::ServerboundPacket;
use connection::Connection;
use {ClientState, PROTOCOL_VERSION, mojang, serverbound};
use json::AuthenticationResponse;

use std::{io, thread, time};

/// Represents a single client connection to a Server.
pub struct Client {
    conn: Connection<ClientboundPacket, ServerboundPacket>,
    auto_handle: bool,
    hide_handled: bool,
}
impl Client {
    /// Attempt open the tcp connection to the given host and port, and
    /// nothing more. If you use this you must then send all subsequent
    /// packets manually to authenticate and so on.
    pub fn connect_tcp(host: &str, port: u16) -> io::Result<Self> {
        Ok(Client {
               conn: Connection::connect_tcp(host, port)?,
               auto_handle: false,
               hide_handled: false,
           })
    }

    /// Attempt to connect to the server at the given host and port,
    /// completing the usual steps for an unauthenticated login.
    ///
    /// In most cases this is what you will want for offline/local servers
    /// and singleplayer. This will establish an unencrypted connection
    /// to the server.
    ///
    /// The username is the Minecraft username, and not the Mojang username,
    /// (i.e. NOT the email address for migrated accounts.)
    ///
    /// This will set auto_handle and hide_handled to true.
    ///
    /// This will return Ok(Client) on receival of a PlayerAbilities packet,
    /// but note that the PlayerAbilities packet and all packets received before
    /// it will not be available for consumers. If you need any of those
    /// packets, you will want to do the authentication manually.
    ///
    /// This function will time out after 30 seconds (theoretical absolute worst
    /// case 60 seconds.)
    pub fn connect_unauthenticated(host: &str,
                                   port: u16,
                                   username: &str)
                                   -> io::Result<Self> {

        let timeout = time::Instant::now();
        let mut client = Client::connect_tcp(host, port)?;
        client.set_auto_handle(true);
        client.set_hide_handled(true);
        let handshake = serverbound::Handshake::new(PROTOCOL_VERSION,
                                                    host.to_string(),
                                                    port,
                                                    2);
        let loginstart = serverbound::LoginStart::new(username.to_string());
        client.send(handshake)?;
        client.set_clientstate(ClientState::Login);
        client.send(loginstart)?;

        /* Now we wait for the PlayerAbilities packet from the server */
        'wait: loop {
            if timeout.elapsed() > time::Duration::new(30, 0) {
                return io_error!("Timed out waiting for LoginSuccess/EncryptionRequest");
            }
            client.update_inbuf()?;
            match client.read_packet()? {
                Some(ClientboundPacket::LoginDisconnect(ref p)) => {
                    return io_error!("Got LoginDisconnect, reason: {}",
                                     p.get_raw_chat());
                },
                Some(ClientboundPacket::PlayerAbilities(..)) => break 'wait,
                Some(ClientboundPacket::EncryptionRequest(..)) => {
                    return io_error!("connect_unauthenticated got EncryptionRequest");
                },
                Some(_) => (),
                None => thread::sleep(time::Duration::from_millis(10)),
            }
        }

        Ok(client)
    }

    /// Authenticate with Mojang, and then connect to the server at the
    /// given host and port. In most cases this is what you will want to use
    /// to connect to online servers.
    ///
    /// This will establish an encrypted connection to the server.
    ///
    /// Requires that you've already authenticated with Mojang, e.g. by calling
    /// yggdrasil::authenticate
    ///
    /// This will set auto_handle and hide_handled to true.
    ///
    /// This will return Ok(Client) on receival of a PlayerAbilities packet,
    /// but note that the PlayerAbilities packet and all packets received before
    /// it will not be available for consumers. If you need any of those
    /// packets, you will want to do the authentication manually.
    ///
    /// This function will time out after 30 seconds (theoretical absolute worst
    /// case 60 seconds.)
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// use ozelot::{mojang, Client};
    /// let auth = mojang::Authenticate::new("my_email@example.com".to_string(),
    ///                                      "my_password".to_string())
    ///     .perform().unwrap();
    /// let mut client = Client::connect_authenticated("minecraft.example.com",
    /// 25565,
    /// &auth).unwrap();
    /// ```
    pub fn connect_authenticated(host: &str,
                                 port: u16,
                                 auth: &AuthenticationResponse)
                                 -> io::Result<Self> {

        let timeout = time::Instant::now();
        let mut client = Client::connect_tcp(host, port)?;
        client.set_auto_handle(true);
        client.set_hide_handled(true);
        let handshake = serverbound::Handshake::new(PROTOCOL_VERSION,
                                                    host.to_string(),
                                                    port,
                                                    2);
        let loginstart =
            serverbound::LoginStart::new(auth.selectedProfile.name.clone());
        client.send(handshake)?;
        client.set_clientstate(ClientState::Login);
        client.send(loginstart)?;

        /* Here we wait for a LoginSuccess/EncryptionRequest packet */
        'wait: loop {
            if timeout.elapsed() > time::Duration::new(30, 0) {
                return io_error!("Timed out waiting for LoginSuccess/EncryptionRequest");
            }
            client.update_inbuf()?;
            match client.read_packet()? {
                Some(ClientboundPacket::LoginDisconnect(ref p)) => {
                    return io_error!("Got LoginDisconnect, reason: {}",
                                     p.get_raw_chat());
                },
                Some(ClientboundPacket::LoginSuccess(..)) => {
                    return io_error!("Logged in unauthenticated")
                },
                Some(ClientboundPacket::EncryptionRequest(ref p)) => {
                    let shared_secret = mojang::create_shared_secret();

                    mojang::SessionJoin::new(auth.accessToken.clone(),
                                             auth.selectedProfile.id.clone(),
                                             p.get_server_id(),
                                             &shared_secret,
                                             p.get_public_key()).perform()?;

                    let encryptionresponse
                            = serverbound::EncryptionResponse::new_unencrypted(
                                &p.get_public_key(),
                                &shared_secret,
                                &p.get_verify_token())?;
                    client.send(encryptionresponse)?;
                    client.enable_encryption(&shared_secret);

                    break 'wait;
                },
                Some(_) => (),
                None => thread::sleep(time::Duration::from_millis(10)),
            }
        }

        /* Now we wait for the PlayerAbilities packet from the server */
        'wait2: loop {
            if timeout.elapsed() > time::Duration::new(30, 0) {
                return io_error!("Timed out waiting for PlayerAbilities packet");
            }
            client.update_inbuf()?;
            match client.read_packet()? {
                Some(ClientboundPacket::LoginDisconnect(ref p)) => {
                    return io_error!("Got LoginDisconnect, reason: {}",
                                     p.get_raw_chat());
                },
                Some(ClientboundPacket::PlayerAbilities(..)) => break 'wait2,
                Some(_) => (),
                None => thread::sleep(time::Duration::from_millis(10)),
            }
        }

        Ok(client)
    }

    /// Try to read some packets from the server.
    ///
    /// This function is nonblocking.
    pub fn read(&mut self) -> io::Result<Vec<ClientboundPacket>> {
        self.update_inbuf()?;

        let mut ret = Vec::new();
        loop {
            let packet = self.read_packet()?;
            /* push = whether to push the packet to ret */
            let mut push = match &packet {
                &Some(ClientboundPacket::LoginSuccess(_)) => false,
                &Some(ClientboundPacket::SetCompression(_)) => false,
                &Some(ClientboundPacket::KeepAlive(_)) => false,
                &Some(_) => true,
                &None => break,
            };
            if self.hide_handled == false || self.auto_handle == false {
                push = true;
            }

            if push {
                ret.push(packet
                         .expect("unreachable packet = None in client.read()"));
            }
        }

        Ok(ret)
    }

    /// Send the given packet to the server that we're connected to.
    ///
    /// This function may block.
    pub fn send(&mut self, packet: ServerboundPacket) -> io::Result<()> {
        self.conn.send(packet)
    }

    /// Whether to automatically handle: KeepAlive, LoginSuccess and
    /// SetCompression packets. Most clients won't need to manually deal with
    /// these.
    pub fn set_auto_handle(&mut self, new: bool) {
        self.auto_handle = new;
    }

    /// Whether or not to hide packets that have been handled by ozelot from the
    /// consumer of the library.
    ///
    /// E.g. KeepAlives that are automatically handled if auto_handle = true.
    pub fn set_hide_handled(&mut self, new: bool) {
        self.hide_handled = new;
    }

    /// Attempt to close this connection, disconnecting from the server.
    ///
    /// All future sends and reads to this connection will fail.
    pub fn close(&mut self) -> io::Result<()> {
        self.conn.close()
    }

    /// Change the client state of this connection
    pub fn set_clientstate(&mut self, new_state: ClientState) {
        self.conn.set_clientstate(new_state)
    }

    /// Enable encryption with the given key.
    ///
    /// It is an error to enable encryption if encryption has already been
    /// enabled.
    pub fn enable_encryption(&mut self, key: &[u8; 16]) {
        self.conn.enable_encryption(key)
    }

    /// Enable compression.
    ///
    /// It is generally an error to enable compression if compression has
    /// already been enabled.
    pub fn enable_compression(&mut self, threshold: usize) {
        self.conn.enable_compression(threshold)
    }

    /// Read from the TcpStream and update the incoming buffer.
    ///
    /// This is the only way to actually read from the TcpStream. Unless you
    /// know for sure you need to call this, then you do not need to call this.
    /// I.e. if you're just using client.read(), then you do not need to call
    /// this function.
    ///
    /// This function is nonblocking.
    pub fn update_inbuf(&mut self) -> io::Result<()> {
        self.conn.update_inbuf()
    }

    /// Read a single packet from the internal buffer.
    ///
    /// This is only really useful if you want finegrained control over the
    /// processing of packets, or if you want to manually authenticate with
    /// the server. In most cases, you'll want to just call client.read().
    ///
    /// You MUST be sure that client.update_inbuf() has been called before this,
    /// this function will not attempt to read from the TcpStream, only from the
    /// internal buffer.
    pub fn read_packet(&mut self) -> io::Result<Option<ClientboundPacket>> {
        let packet = self.conn.read_packet()?;

        if self.auto_handle {
            match &packet {
                &Some(ClientboundPacket::LoginSuccess(..)) => {
                    self.set_clientstate(ClientState::Play);
                },
                &Some(ClientboundPacket::SetCompression(ref p)) => {
                    self.enable_compression(*p.get_threshold() as usize);
                },
                &Some(ClientboundPacket::KeepAlive(ref p)) => {
                    let keepalive = serverbound::KeepAlive::new(*p.get_id());
                    self.send(keepalive)?;
                },
                _ => (),
            }
        }

        Ok(packet)
    }
}
<|endoftext|>


<commit_before>//! Contains common types and functions used throughout the library.

use std::fmt;

/// Represents a position inside some textual document.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct TextPosition {
    /// Row, counting from 0
    pub row: u64,
    /// Column, counting from 0
    pub column: u64,
}

impl TextPosition {
    /// Creates a new position initialized to the beginning of the document
    #[inline]
    pub fn new() -> TextPosition {
        TextPosition { row: 0, column: 0 }
    }

    /// Advances the position in a line
    #[inline]
    pub fn advance(&mut self, count: u8) {
        self.column += count as u64;
    }

    /// Advances the position in a line to the next tab position
    #[inline]
    pub fn advance_to_tab(&mut self, width: u8) {
        let width = width as u64;
        self.column += width - self.column % width
    }

    /// Advances the position to the beginning of the next line
    #[inline]
    pub fn new_line(&mut self) {
        self.column = 0;
        self.row += 1;
    }
}

impl fmt::Debug for TextPosition {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.row + 1, self.column + 1)
    }
}

impl fmt::Display for TextPosition {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.row + 1, self.column + 1)
    }
}

/// Get the position in the document corresponding to the object
///
/// This trait is implemented by parsers, lexers and errors.
pub trait Position {
    /// Returns the current position or a position corresponding to the object.
    fn position(&self) -> TextPosition;
}

impl Position for TextPosition {
    #[inline]
    fn position(&self) -> TextPosition {
        *self
    }
}

/// XML version enumeration.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum XmlVersion {
    /// XML version 1.0.
    Version10,

    /// XML version 1.1.
    Version11
}

impl fmt::Display for XmlVersion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            XmlVersion::Version10 => write!(f, "1.0"),
            XmlVersion::Version11 => write!(f, "1.1")
        }
    }
}

impl fmt::Debug for XmlVersion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

/// Checks whether the given character is a white space character (`S`)
/// as is defined by XML 1.1 specification, [section 2.3][1].
///
/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
pub fn is_whitespace_char(c: char) -> bool {
    match c {
        '\x20' | '\x09' | '\x0d' | '\x0a' => true,
        _ => false
    }
}

/// Checks whether the given string is compound only by white space
/// characters (`S`) using the previous is_whitespace_char to check
/// all characters of this string
pub fn is_whitespace_str(s: &str) -> bool {
    s.chars().all(is_whitespace_char)
}

/// Checks whether the given character is a name start character (`NameStartChar`)
/// as is defined by XML 1.1 specification, [section 2.3][1].
///
/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
pub fn is_name_start_char(c: char) -> bool {
    match c {
        ':' | 'A'...'Z' | '_' | 'a'...'z' |
        '\u{C0}'...'\u{D6}' | '\u{D8}'...'\u{F6}' | '\u{F8}'...'\u{2FF}' |
        '\u{370}'...'\u{37D}' | '\u{37F}'...'\u{1FFF}' |
        '\u{200C}'...'\u{200D}' | '\u{2070}'...'\u{218F}' |
        '\u{2C00}'...'\u{2FEF}' | '\u{3001}'...'\u{D7FF}' |
        '\u{F900}'...'\u{FDCF}' | '\u{FDF0}'...'\u{FFFD}' |
        '\u{10000}'...'\u{EFFFF}' => true,
        _ => false
    }
}

/// Checks whether the given character is a name character (`NameChar`)
/// as is defined by XML 1.1 specification, [section 2.3][1].
///
/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
pub fn is_name_char(c: char) -> bool {
    match c {
        _ if is_name_start_char(c) => true,
        '-' | '.' | '0'...'9' | '\u{B7}' |
        '\u{300}'...'\u{3F6}' | '\u{203F}'...'\u{2040}' => true,
        _ => false
    }
}
<commit_msg>Fix is_name_char transcription error.<commit_after>//! Contains common types and functions used throughout the library.

use std::fmt;

/// Represents a position inside some textual document.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct TextPosition {
    /// Row, counting from 0
    pub row: u64,
    /// Column, counting from 0
    pub column: u64,
}

impl TextPosition {
    /// Creates a new position initialized to the beginning of the document
    #[inline]
    pub fn new() -> TextPosition {
        TextPosition { row: 0, column: 0 }
    }

    /// Advances the position in a line
    #[inline]
    pub fn advance(&mut self, count: u8) {
        self.column += count as u64;
    }

    /// Advances the position in a line to the next tab position
    #[inline]
    pub fn advance_to_tab(&mut self, width: u8) {
        let width = width as u64;
        self.column += width - self.column % width
    }

    /// Advances the position to the beginning of the next line
    #[inline]
    pub fn new_line(&mut self) {
        self.column = 0;
        self.row += 1;
    }
}

impl fmt::Debug for TextPosition {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.row + 1, self.column + 1)
    }
}

impl fmt::Display for TextPosition {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}:{}", self.row + 1, self.column + 1)
    }
}

/// Get the position in the document corresponding to the object
///
/// This trait is implemented by parsers, lexers and errors.
pub trait Position {
    /// Returns the current position or a position corresponding to the object.
    fn position(&self) -> TextPosition;
}

impl Position for TextPosition {
    #[inline]
    fn position(&self) -> TextPosition {
        *self
    }
}

/// XML version enumeration.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum XmlVersion {
    /// XML version 1.0.
    Version10,

    /// XML version 1.1.
    Version11
}

impl fmt::Display for XmlVersion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            XmlVersion::Version10 => write!(f, "1.0"),
            XmlVersion::Version11 => write!(f, "1.1")
        }
    }
}

impl fmt::Debug for XmlVersion {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self, f)
    }
}

/// Checks whether the given character is a white space character (`S`)
/// as is defined by XML 1.1 specification, [section 2.3][1].
///
/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
pub fn is_whitespace_char(c: char) -> bool {
    match c {
        '\x20' | '\x09' | '\x0d' | '\x0a' => true,
        _ => false
    }
}

/// Checks whether the given string is compound only by white space
/// characters (`S`) using the previous is_whitespace_char to check
/// all characters of this string
pub fn is_whitespace_str(s: &str) -> bool {
    s.chars().all(is_whitespace_char)
}

/// Checks whether the given character is a name start character (`NameStartChar`)
/// as is defined by XML 1.1 specification, [section 2.3][1].
///
/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
pub fn is_name_start_char(c: char) -> bool {
    match c {
        ':' | 'A'...'Z' | '_' | 'a'...'z' |
        '\u{C0}'...'\u{D6}' | '\u{D8}'...'\u{F6}' | '\u{F8}'...'\u{2FF}' |
        '\u{370}'...'\u{37D}' | '\u{37F}'...'\u{1FFF}' |
        '\u{200C}'...'\u{200D}' | '\u{2070}'...'\u{218F}' |
        '\u{2C00}'...'\u{2FEF}' | '\u{3001}'...'\u{D7FF}' |
        '\u{F900}'...'\u{FDCF}' | '\u{FDF0}'...'\u{FFFD}' |
        '\u{10000}'...'\u{EFFFF}' => true,
        _ => false
    }
}

/// Checks whether the given character is a name character (`NameChar`)
/// as is defined by XML 1.1 specification, [section 2.3][1].
///
/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
pub fn is_name_char(c: char) -> bool {
    match c {
        _ if is_name_start_char(c) => true,
        '-' | '.' | '0'...'9' | '\u{B7}' |
        '\u{300}'...'\u{36F}' | '\u{203F}'...'\u{2040}' => true,
        _ => false
    }
}
<|endoftext|>


<commit_before>const ASN1_CONSTRUCTED_FLAG: isize = 0x20;

pub enum ASN1Tag {
    Bool = 0x1,
    Integer = 0x2,
    BitString = 0x3,
    OctetString = 0x4,
    ObjectIdentifier = 0x6,
    PrintableString = 0x13,
    UTCTime = 0x17,
    Sequence = (0x10 | ASN1_CONSTRUCTED_FLAG),
}
<commit_msg>make the types be what I want<commit_after>const ASN1_CONSTRUCTED_FLAG: u8 = 0x20;

#[repr(u8)]
pub enum ASN1Tag {
    Bool = 0x1,
    Integer = 0x2,
    BitString = 0x3,
    OctetString = 0x4,
    ObjectIdentifier = 0x6,
    PrintableString = 0x13,
    UTCTime = 0x17,
    Sequence = (0x10 | ASN1_CONSTRUCTED_FLAG),
}
<|endoftext|>


<commit_before>use num_traits::{FromPrimitive, Signed};

/// Generic floating point number, implemented for f32 and f64
pub trait FFTnum: Copy + FromPrimitive + Signed + Sync + Send + 'static {}

impl FFTnum for f32 {}
impl FFTnum for f64 {}

#[inline(always)]
pub fn verify_length<T>(input: &[T], output: &[T], expected: usize) {
	assert_eq!(input.len(), expected, "Input is the wrong length. Expected {}, got {}", expected, input.len());
	assert_eq!(output.len(), expected, "Output is the wrong length. Expected {}, got {}", expected, output.len());
}

#[inline(always)]
pub fn verify_length_divisible<T>(input: &[T], output: &[T], expected: usize) {
	assert_eq!(input.len() % expected, 0, "Input is the wrong length. Expected multiple of {}, got {}", expected, input.len());
	assert_eq!(input.len(), output.len(), "Input and output must have the same length. Expected {}, got {}", input.len(), output.len());
}
<commit_msg>Fftnum blanket impl (#12)<commit_after>use num_traits::{FromPrimitive, Signed};

/// Generic floating point number
pub trait FFTnum: Copy + FromPrimitive + Signed + Sync + Send + 'static {}

// Blanket impl for any type that implements the required traits.
// Notably, this includes f32 and f64, but also allows flexibility for library authors of custom numeric types.
impl<T> FFTnum for T where T: Copy + FromPrimitive + Signed + Sync + Send + 'static {}

#[inline(always)]
pub fn verify_length<T>(input: &[T], output: &[T], expected: usize) {
	assert_eq!(input.len(), expected, "Input is the wrong length. Expected {}, got {}", expected, input.len());
	assert_eq!(output.len(), expected, "Output is the wrong length. Expected {}, got {}", expected, output.len());
}

#[inline(always)]
pub fn verify_length_divisible<T>(input: &[T], output: &[T], expected: usize) {
	assert_eq!(input.len() % expected, 0, "Input is the wrong length. Expected multiple of {}, got {}", expected, input.len());
	assert_eq!(input.len(), output.len(), "Input and output must have the same length. Expected {}, got {}", input.len(), output.len());
}
<|endoftext|>


<commit_before>use std::{io::Write, time::Duration};

use kcp::Kcp;

/// Kcp Delay Config
#[derive(Debug, Clone, Copy)]
pub struct KcpNoDelayConfig {
    /// Enable nodelay
    pub nodelay: bool,
    /// Internal update interval (ms)
    pub interval: i32,
    /// ACK number to enable fast resend
    pub resend: i32,
    /// Disable congetion control
    pub nc: bool,
}

impl Default for KcpNoDelayConfig {
    fn default() -> KcpNoDelayConfig {
        KcpNoDelayConfig {
            nodelay: false,
            interval: 100,
            resend: 0,
            nc: false,
        }
    }
}

impl KcpNoDelayConfig {
    /// Get a fastest configuration
    ///
    /// 1. Enable NoDelay
    /// 2. Set ticking interval to be 10ms
    /// 3. Set fast resend to be 2
    /// 4. Disable congestion control
    pub fn fastest() -> KcpNoDelayConfig {
        KcpNoDelayConfig {
            nodelay: true,
            interval: 10,
            resend: 2,
            nc: true,
        }
    }
}

/// Kcp Config
#[derive(Debug, Clone, Copy)]
pub struct KcpConfig {
    /// Max Transmission Unit
    pub mtu: Option<usize>,
    /// Internal update interval
    pub interval: Option<u32>,
    /// nodelay
    pub nodelay: Option<KcpNoDelayConfig>,
    /// Send window size
    pub wnd_size: Option<(u16, u16)>,
    /// Minimal resend timeout
    pub rx_minrto: Option<u32>,
    /// Session expire duration, default is 90 seconds
    pub session_expire: Duration,
    /// Flush KCP state immediately after write
    pub flush_write: bool,
    /// Flush ACKs immediately after input
    pub flush_acks_input: bool,
    /// Stream mode
    pub stream: bool,
}

impl Default for KcpConfig {
    fn default() -> KcpConfig {
        KcpConfig {
            mtu: None,
            interval: None,
            nodelay: None,
            wnd_size: None,
            rx_minrto: None,
            session_expire: Duration::from_secs(90),
            flush_write: true,
            flush_acks_input: true,
            stream: true,
        }
    }
}

impl KcpConfig {
    /// Applies config onto `Kcp`
    #[doc(hidden)]
    pub fn apply_config<W: Write>(&self, k: &mut Kcp<W>) {
        if let Some(mtu) = self.mtu {
            k.set_mtu(mtu).expect("Invalid MTU");
        }

        if let Some(interval) = self.interval {
            k.set_interval(interval);
        }

        if let Some(ref nodelay) = self.nodelay {
            k.set_nodelay(nodelay.nodelay, nodelay.interval, nodelay.resend, nodelay.nc);
        } else {
            // Normal Mode recommend by KCP upstream
            // https://github.com/skywind3000/kcp#%E5%8D%8F%E8%AE%AE%E9%85%8D%E7%BD%AE
            k.set_nodelay(false, 40, 0, false);
        }

        if let Some(rm) = self.rx_minrto {
            k.set_rx_minrto(rm);
        }

        if let Some(ws) = self.wnd_size {
            k.set_wndsize(ws.0, ws.1);
        }
    }
}
<commit_msg>set default nodelay to normal mode and remove interval config<commit_after>use std::{io::Write, time::Duration};

use kcp::Kcp;

/// Kcp Delay Config
#[derive(Debug, Clone, Copy)]
pub struct KcpNoDelayConfig {
    /// Enable nodelay
    pub nodelay: bool,
    /// Internal update interval (ms)
    pub interval: i32,
    /// ACK number to enable fast resend
    pub resend: i32,
    /// Disable congetion control
    pub nc: bool,
}

impl Default for KcpNoDelayConfig {
    fn default() -> KcpNoDelayConfig {
        KcpNoDelayConfig {
            nodelay: false,
            interval: 100,
            resend: 0,
            nc: false,
        }
    }
}

impl KcpNoDelayConfig {
    /// Get a fastest configuration
    ///
    /// 1. Enable NoDelay
    /// 2. Set ticking interval to be 10ms
    /// 3. Set fast resend to be 2
    /// 4. Disable congestion control
    pub fn fastest() -> KcpNoDelayConfig {
        KcpNoDelayConfig {
            nodelay: true,
            interval: 10,
            resend: 2,
            nc: true,
        }
    }

    /// Get a normal configuration
    ///
    /// 1. Disable NoDelay
    /// 2. Set ticking interval to be 40ms
    /// 3. Disable fast resend
    /// 4. Enable congestion control
    pub fn normal() -> KcpNoDelayConfig {
        KcpNoDelayConfig {
            nodelay: false,
            interval: 40,
            resend: 0,
            nc: false,
        }
    }
}

/// Kcp Config
#[derive(Debug, Clone, Copy)]
pub struct KcpConfig {
    /// Max Transmission Unit
    pub mtu: Option<usize>,
    /// nodelay
    pub nodelay: KcpNoDelayConfig,
    /// Send window size
    pub wnd_size: Option<(u16, u16)>,
    /// Minimal resend timeout
    pub rx_minrto: Option<u32>,
    /// Session expire duration, default is 90 seconds
    pub session_expire: Duration,
    /// Flush KCP state immediately after write
    pub flush_write: bool,
    /// Flush ACKs immediately after input
    pub flush_acks_input: bool,
    /// Stream mode
    pub stream: bool,
}

impl Default for KcpConfig {
    fn default() -> KcpConfig {
        KcpConfig {
            mtu: None,
            nodelay: KcpNoDelayConfig::normal(),
            wnd_size: None,
            rx_minrto: None,
            session_expire: Duration::from_secs(90),
            flush_write: true,
            flush_acks_input: true,
            stream: true,
        }
    }
}

impl KcpConfig {
    /// Applies config onto `Kcp`
    #[doc(hidden)]
    pub fn apply_config<W: Write>(&self, k: &mut Kcp<W>) {
        if let Some(mtu) = self.mtu {
            k.set_mtu(mtu).expect("Invalid MTU");
        }

        k.set_nodelay(
            self.nodelay.nodelay,
            self.nodelay.interval,
            self.nodelay.resend,
            self.nodelay.nc,
        );

        if let Some(rm) = self.rx_minrto {
            k.set_rx_minrto(rm);
        }

        if let Some(ws) = self.wnd_size {
            k.set_wndsize(ws.0, ws.1);
        }
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::str::FromStr;
use std::error::Error as StdError;
use std::io::Error as IoError;
use std::fmt::{self, Display, Formatter};
use docopt::Docopt;
use docopt::Error as DocoptError;
use toml;

use gobjects;
use version::Version;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkMode {
    Normal,     //generate widgets etc.
    Sys,        //generate -sys with ffi
}

impl Default for WorkMode {
    fn default() -> WorkMode { WorkMode::Normal }
}

impl FromStr for WorkMode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(WorkMode::Normal),
            "sys" => Ok(WorkMode::Sys),
            _ => Err("Wrong work mode".into())
        }
    }
}

#[derive(Debug)]
pub enum Error {
    CommandLine(DocoptError),
    Io(IoError, String),
    Toml(String, String),
    Options(String, String),
}

impl StdError for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            CommandLine(ref e) => e.description(),
            Io(ref e, _) => e.description(),
            Toml(ref s, _) => s,
            Options(ref s, _) => s,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            CommandLine(ref err) => err.fmt(f),
            Io(ref err, ref filename) => {
                try!(write!(f, "Failed to read config \"{}\": ", filename));
                err.fmt(f)
            }
            Toml(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename, err)
            }
            Options(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename, err)
            }
        }
    }
}

impl<'a> From<DocoptError> for Error {
    fn from(e: DocoptError) -> Error {
        Error::CommandLine(e)
    }
}

impl<'a> From<(IoError, &'a str)> for Error {
    fn from(e: (IoError, &'a str)) -> Error {
        Error::Io(e.0, e.1.into())
    }
}

impl<'a, 'b> From<(&'a str, &'b str)> for Error {
    fn from(e: (&'a str, &'b str)) -> Error {
        Error::Options(e.0.into(), e.1.into())
    }
}

impl<'a> From<(String, &'a str)> for Error {
    fn from(e: (String, &'a str)) -> Error {
        Error::Options(e.0, e.1.into())
    }
}

trait LookupStr {
    fn lookup_str<'a>(&'a self, option: &'a str, err: &str, config_file: &str) -> Result<&'a str, Error>;
}

impl LookupStr for toml::Value {
    fn lookup_str<'a>(&'a self, option: &'a str, err: &str, config_file: &str) -> Result<&'a str, Error> {
        let value = try!(self.lookup(option).ok_or((err, config_file)));
        Ok(value.as_str().unwrap())
    }
}

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help          Show this message.
    -c CONFIG           Config file path (default: Gir.toml)
    -d GIRSPATH         Directory for girs
    -m MODE             Work mode: normal or sys
    -o PATH             Target path
    -b, --make_backup   Make backup before generating
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: String,
    pub library_name: String,
    pub library_version: String,
    pub target_path: String,
    pub external_libraries: Vec<String>,
    pub objects: gobjects::GObjects,
    pub min_cfg_version: Version,
    pub make_backup: bool,
}

impl Config {
    pub fn new() -> Result<Config, Error> {
        let args = try!(Docopt::new(USAGE)
            .and_then(|dopt| dopt.parse()));

        let config_file = match args.get_str("-c") {
            "" => "Gir.toml",
            a => a,
        };

        //TODO: add check file existence when stable std::fs::PathExt
        let toml = try!(read_toml(config_file));

        let work_mode_str = match args.get_str("-m") {
            "" => try!(toml.lookup_str("options.work_mode", "No options.work_mode in config", config_file)),
            a => a,
        };
        let work_mode = WorkMode::from_str(work_mode_str)
            .unwrap_or_else(|e| panic!(e));

        let girs_dir = match args.get_str("-d") {
            "" => try!(toml.lookup_str("options.girs_dir", "No options.girs_dir in config", config_file)),
            a => a
        };

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
            ("", "") => (
                try!(toml.lookup_str("options.library", "No options.library in config", config_file)),
                try!(toml.lookup_str("options.version", "No options.version in config", config_file))
            ),
            ("", _) | (_, "") => try!(Err(("Library and version can not be specified separately", config_file))),
            (a, b) => (a, b)
        };

        let target_path = match args.get_str("-o") {
            "" => try!(toml.lookup_str("options.target_path", "No target path specified", config_file)),
            a => a
        };

        let mut objects = toml.lookup("object").map(|t| gobjects::parse_toml(t))
            .unwrap_or_else(|| Default::default());
        gobjects::parse_status_shorthands(&mut objects, &toml);

        let external_libraries = toml.lookup("options.external_libraries")
            .map(|a| a.as_slice().unwrap().iter()
                .filter_map(|v|
                    if let &toml::Value::String(ref s) = v { Some(s.clone()) } else { None } )
                .collect())
            .unwrap_or_else(|| Vec::new());

        let min_cfg_version = try!(toml.lookup("options.min_cfg_version")
           .map_or_else(|| Ok(Default::default()), |t| t.as_str().unwrap().parse())
           .map_err(|e: String| (e, config_file)));

        let make_backup = args.get_bool("-b");

        Ok(Config {
            work_mode: work_mode,
            girs_dir: girs_dir.into(),
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path.into(),
            external_libraries: external_libraries,
            objects: objects,
            min_cfg_version: min_cfg_version,
            make_backup: make_backup,
        })
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }
}

fn read_toml(filename: &str) -> Result<toml::Value, Error> {
    let mut input = String::new();
    try!(File::open(filename)
         .and_then(|mut f| f.read_to_string(&mut input))
         .map_err(|e| (e, filename)));

    let mut parser = toml::Parser::new(&input);
    match parser.parse() {
        Some(toml) => Ok(toml::Value::Table(toml)),
        None => {
            let err = &parser.errors[parser.errors.len() - 1];
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            let s = format!("{}:{}-{}:{} error: {}", loline, locol, hiline, hicol, err.desc);
            Err(Error::Toml(s, filename.to_owned()))
        }
    }
}
<commit_msg>Make Result from tomls as_xxx<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::str::FromStr;
use std::error::Error as StdError;
use std::io::Error as IoError;
use std::fmt::{self, Display, Formatter};
use docopt::Docopt;
use docopt::Error as DocoptError;
use toml;

use gobjects;
use version::Version;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WorkMode {
    Normal,     //generate widgets etc.
    Sys,        //generate -sys with ffi
}

impl Default for WorkMode {
    fn default() -> WorkMode { WorkMode::Normal }
}

impl FromStr for WorkMode {
    type Err = String;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "normal" => Ok(WorkMode::Normal),
            "sys" => Ok(WorkMode::Sys),
            _ => Err("Wrong work mode".into())
        }
    }
}

#[derive(Debug)]
pub enum Error {
    CommandLine(DocoptError),
    Io(IoError, String),
    Toml(String, String),
    Options(String, String),
}

impl StdError for Error {
    fn description(&self) -> &str {
        use self::Error::*;
        match *self {
            CommandLine(ref e) => e.description(),
            Io(ref e, _) => e.description(),
            Toml(ref s, _) => s,
            Options(ref s, _) => s,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            CommandLine(ref err) => err.fmt(f),
            Io(ref err, ref filename) => {
                try!(write!(f, "Failed to read config \"{}\": ", filename));
                err.fmt(f)
            }
            Toml(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename, err)
            }
            Options(ref err, ref filename) => {
                write!(f, "\"{}\": {}", filename, err)
            }
        }
    }
}

impl<'a> From<DocoptError> for Error {
    fn from(e: DocoptError) -> Error {
        Error::CommandLine(e)
    }
}

impl<'a> From<(IoError, &'a str)> for Error {
    fn from(e: (IoError, &'a str)) -> Error {
        Error::Io(e.0, e.1.into())
    }
}

impl<'a> From<(&'a str, &'a str)> for Error {
    fn from(e: (&'a str, &'a str)) -> Error {
        Error::Options(e.0.into(), e.1.into())
    }
}

impl<'a> From<(String, &'a str)> for Error {
    fn from(e: (String, &'a str)) -> Error {
        Error::Options(e.0, e.1.into())
    }
}

trait TomlHelper where Self: Sized {
    fn lookup_str<'a>(&'a self, option: &'a str, err: &str, config_file: &str) -> Result<&'a str, Error>;
    fn as_result_str<'a>(&'a self, option: &'a str, config_file: &str) -> Result<&'a str, Error>;
    fn as_result_slice<'a>(&'a self, option: &'a str, config_file: &str) -> Result<&'a [Self], Error>;
}

impl TomlHelper for toml::Value {
    fn lookup_str<'a>(&'a self, option: &'a str, err: &str, config_file: &str) -> Result<&'a str, Error> {
        let value = try!(self.lookup(option).ok_or((err, config_file)));
        value.as_result_str(option, config_file)
    }
    fn as_result_str<'a>(&'a self, option: &'a str, config_file: &str) -> Result<&'a str, Error> {
        self.as_str()
            .ok_or(Error::Options(format!("Invalid `{}` value, expected a string, found {}",
                                          option, self.type_str()),
                                  config_file.into()))
    }
    fn as_result_slice<'a>(&'a self, option: &'a str, config_file: &str) -> Result<&'a [Self], Error> {
        self.as_slice()
            .ok_or(Error::Options(format!("Invalid `{}` value, expected a array, found {}",
                                          option, self.type_str()),
                                  config_file.into()))
    }
}

static USAGE: &'static str = "
Usage: gir [options] [<library> <version>]
       gir --help

Options:
    -h, --help          Show this message.
    -c CONFIG           Config file path (default: Gir.toml)
    -d GIRSPATH         Directory for girs
    -m MODE             Work mode: normal or sys
    -o PATH             Target path
    -b, --make_backup   Make backup before generating
";

#[derive(Debug)]
pub struct Config {
    pub work_mode: WorkMode,
    pub girs_dir: String,
    pub library_name: String,
    pub library_version: String,
    pub target_path: String,
    pub external_libraries: Vec<String>,
    pub objects: gobjects::GObjects,
    pub min_cfg_version: Version,
    pub make_backup: bool,
}

impl Config {
    pub fn new() -> Result<Config, Error> {
        let args = try!(Docopt::new(USAGE)
            .and_then(|dopt| dopt.parse()));

        let config_file = match args.get_str("-c") {
            "" => "Gir.toml",
            a => a,
        };

        //TODO: add check file existence when stable std::fs::PathExt
        let toml = try!(read_toml(config_file));

        let work_mode_str = match args.get_str("-m") {
            "" => try!(toml.lookup_str("options.work_mode", "No options.work_mode in config", config_file)),
            a => a,
        };
        let work_mode = WorkMode::from_str(work_mode_str)
            .unwrap_or_else(|e| panic!(e));

        let girs_dir = match args.get_str("-d") {
            "" => try!(toml.lookup_str("options.girs_dir", "No options.girs_dir in config", config_file)),
            a => a
        };

        let (library_name, library_version) =
            match (args.get_str("<library>"), args.get_str("<version>")) {
            ("", "") => (
                try!(toml.lookup_str("options.library", "No options.library in config", config_file)),
                try!(toml.lookup_str("options.version", "No options.version in config", config_file))
            ),
            ("", _) | (_, "") => try!(Err(("Library and version can not be specified separately", config_file))),
            (a, b) => (a, b)
        };

        let target_path = match args.get_str("-o") {
            "" => try!(toml.lookup_str("options.target_path", "No target path specified", config_file)),
            a => a
        };

        let mut objects = toml.lookup("object").map(|t| gobjects::parse_toml(t))
            .unwrap_or_else(|| Default::default());
        gobjects::parse_status_shorthands(&mut objects, &toml);

        let external_libraries = match toml.lookup("options.external_libraries") {
            Some(a) => {
                try!(a.as_result_slice("options.external_libraries", &config_file))
                    .iter().filter_map(|v| v.as_str().map(String::from))
                    .collect()
            }
            None => Vec::new(),
        };

        let min_cfg_version = match toml.lookup("options.min_cfg_version") {
            Some(v) => try!(try!(v.as_result_str("options.min_cfg_version", config_file))
                            .parse().map_err(|e: String| (e, config_file))),
            None => Default::default(),
        };

        let make_backup = args.get_bool("-b");

        Ok(Config {
            work_mode: work_mode,
            girs_dir: girs_dir.into(),
            library_name: library_name.into(),
            library_version: library_version.into(),
            target_path: target_path.into(),
            external_libraries: external_libraries,
            objects: objects,
            min_cfg_version: min_cfg_version,
            make_backup: make_backup,
        })
    }

    pub fn library_full_name(&self) -> String {
        format!("{}-{}", self.library_name, self.library_version)
    }
}

fn read_toml(filename: &str) -> Result<toml::Value, Error> {
    let mut input = String::new();
    try!(File::open(filename)
         .and_then(|mut f| f.read_to_string(&mut input))
         .map_err(|e| (e, filename)));

    let mut parser = toml::Parser::new(&input);
    match parser.parse() {
        Some(toml) => Ok(toml::Value::Table(toml)),
        None => {
            let err = &parser.errors[parser.errors.len() - 1];
            let (loline, locol) = parser.to_linecol(err.lo);
            let (hiline, hicol) = parser.to_linecol(err.hi);
            let s = format!("{}:{}-{}:{} error: {}", loline, locol, hiline, hicol, err.desc);
            Err(Error::Toml(s, filename.to_owned()))
        }
    }
}
<|endoftext|>


<commit_before>/// Symbols (dibits) per second.
pub const SYMBOL_RATE: usize = 4800;
/// Baseband samples per second
pub const SAMPLE_RATE: usize = 48000;
/// Baseband samples per symbol.
pub const SYMBOL_PERIOD: usize = SAMPLE_RATE / SYMBOL_RATE;
/// Number of symbols in the frame sync sequence.
pub const SYNC_SYMBOLS: usize = 24;
/// Number of dibits in a coded NID word.
pub const NID_DIBITS: usize = 32;
/// Number of dibits that are input to the 1/2 or 3/4-rate trellis coder.
pub const CODING_DIBITS: usize = 98;
/// Number of dibits in an uncoded TSBK packet.
pub const TSBK_DIBITS: usize = 48;
/// Number of bytes in an uncoded TSBK packet.
pub const TSBK_BYTES: usize = TSBK_DIBITS / 4;
/// Number of dibits in a coded frame.
pub const FRAME_DIBITS: usize = 72;
/// Number of hexbits in a coded header packet.
pub const HEADER_HEXBITS: usize = 36;
/// Number of bytes in an uncoded header packet.
pub const HEADER_BYTES: usize = 15;
/// Number of hexbits in a coded voice extra packet.
pub const EXTRA_HEXBITS: usize = 24;
/// Number of bytes in a link control word.
pub const LINK_CONTROL_BYTES: usize = 9;
/// Number of bytes in a crypto control word.
pub const CRYPTO_CONTROL_BYTES: usize = 12;
/// Number of dibits in an LC/CC piece. An LC/CC word is spread over 6 equal-sized pieces
/// in each frame group, for a total of 120 dibits.
pub const EXTRA_PIECE_DIBITS: usize = 20;
/// Number of dibits in each coded word that makes up a voice extra component.
pub const EXTRA_WORD_DIBITS: usize = 5;
/// Number of dibits in the voice data fragment.
pub const DATA_FRAG_DIBITS: usize = 8;
/// Number of dibits in each coded word that makes up the voice header packet.
pub const HEADER_WORD_DIBITS: usize = 9;
/// Number of dibits in each coded word that makes up the voice LC terminator packet.
pub const LC_TERM_WORD_DIBITS: usize = 12;

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

    #[test]
    fn validate_params() {
        // Don't support non-integer period.
        assert!(SAMPLE_RATE % SYMBOL_RATE == 0);
    }
}
<commit_msg>Clarify const comments<commit_after>/// Symbols (dibits) per second.
pub const SYMBOL_RATE: usize = 4800;
/// Baseband samples per second
pub const SAMPLE_RATE: usize = 48000;
/// Baseband samples per symbol.
pub const SYMBOL_PERIOD: usize = SAMPLE_RATE / SYMBOL_RATE;
/// Number of symbols in the frame sync sequence.
pub const SYNC_SYMBOLS: usize = 24;
/// Number of dibits in a coded NID word.
pub const NID_DIBITS: usize = 32;
/// Number of dibits that are input to the 1/2 or 3/4-rate trellis coder.
pub const CODING_DIBITS: usize = 98;
/// Number of dibits in an uncoded TSBK packet.
pub const TSBK_DIBITS: usize = 48;
/// Number of bytes in an uncoded TSBK packet.
pub const TSBK_BYTES: usize = TSBK_DIBITS / 4;
/// Number of dibits in a coded voice frame.
pub const FRAME_DIBITS: usize = 72;
/// Number of hexbits in a coded voice header packet.
pub const HEADER_HEXBITS: usize = 36;
/// Number of bytes in an uncoded voice header packet.
pub const HEADER_BYTES: usize = 15;
/// Number of hexbits in a coded voice extra packet.
pub const EXTRA_HEXBITS: usize = 24;
/// Number of bytes in a link control word.
pub const LINK_CONTROL_BYTES: usize = 9;
/// Number of bytes in a crypto control word.
pub const CRYPTO_CONTROL_BYTES: usize = 12;
/// Number of dibits in an LC/CC piece. An LC/CC word is spread over 6 equal-sized pieces
/// in each frame group, for a total of 120 dibits.
pub const EXTRA_PIECE_DIBITS: usize = 20;
/// Number of dibits in each coded word that makes up a voice extra component.
pub const EXTRA_WORD_DIBITS: usize = 5;
/// Number of dibits in the voice data fragment.
pub const DATA_FRAG_DIBITS: usize = 8;
/// Number of dibits in each coded word that makes up the voice header packet.
pub const HEADER_WORD_DIBITS: usize = 9;
/// Number of dibits in each coded word that makes up the voice LC terminator packet.
pub const LC_TERM_WORD_DIBITS: usize = 12;

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

    #[test]
    fn validate_params() {
        // Don't support non-integer period.
        assert!(SAMPLE_RATE % SYMBOL_RATE == 0);
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use chrono::{DateTime, Local, NaiveDateTime, TimeZone};
use chrono_humanize::HumanTime;
use json::JsonValue;

// #[derive(Debug, Default)]
// pub struct Error {
//     pub detail: String,
// }
//
// #[derive(Debug)]
// pub struct CrateLinks {
//     pub owners: Option<String>,
//     pub reverse_dependencies: String,
//     pub version_downloads: String,
//     pub versions: Option<String>,
// }
//
// pub struct Crate {
//     pub created_at: String,
//     pub description: Option<String>,
//     pub documentation: Option<String>,
//     pub downloads: i32,
//     pub homepage: Option<String>,
//     pub id: String,
//     pub keywords: Option<Vec<String>>,
//     pub license: Option<String>,
//     pub links: CrateLinks,
//     pub max_version: String,
//     pub name: String,
//     pub repository: Option<String>,
//     pub updated_at: String,
//     pub versions: Option<Vec<u64>>,
// }
//
// #[derive(Debug)]
// pub struct Keyword {
//     pub crates_cnt: u64,
//     pub created_at: String,
//     pub id: String,
//     pub keyword: String,
// }
//
// #[derive(Debug)]
// pub struct VersionLinks {
//     pub authors: String,
//     pub dependencies: String,
//     pub version_downloads: String,
// }
//
// #[derive(Debug)]
// pub struct Version {
//     pub krate: String,
//     pub created_at: String,
//     pub dl_path: String,
//     pub downloads: i32,
//     pub features: HashMap<String, Vec<String>>,
//     pub id: i32,
//     pub links: VersionLinks,
//     pub num: String,
//     pub updated_at: String,
//     pub yanked: bool,
// }
//
// pub struct Reply {
//     pub errors: Error,
//     pub krate: Crate,
//     pub keywords: Vec<Keyword>,
//     pub versions: Vec<Version>,
// }

struct TimeStamp(Option<DateTime<Local>>);

impl<'a> From<&'a JsonValue> for TimeStamp {
    fn from(jv: &JsonValue) -> Self {
        let parse_naive = |s: &str| s.parse::<NaiveDateTime>();
        let naive_to_local = |n: NaiveDateTime| Local.from_utc_datetime(&n);
        let parse_local = |s: &str| s.parse::<DateTime<Local>>();
        let parse = |s: &str| parse_local(s).or_else(|_| parse_naive(s).map(naive_to_local)).ok();
        TimeStamp(jv.as_str().and_then(parse))
    }
}

impl fmt::Display for TimeStamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ts) = self.0 {
            if f.alternate() {
                f.pad(&format!("{}", HumanTime::from(ts)))
            } else {
                f.pad(&format!("{}", ts.naive_local()))
            }
        } else {
            f.pad("")
        }
    }
}

pub struct Crate {
    krate: JsonValue,
    versions: JsonValue,
    keywords: JsonValue,
}

const FIELDS: [&'static str; 5] =
    ["description", "documentation", "homepage", "repository", "license"];

impl Crate {
    pub fn new(json: &JsonValue) -> Self {
        let mut krate = json["crate"].clone();
        // Fix up fields that may be absent

        for field in &FIELDS {
            if krate[*field].is_null() {
                krate[*field] = "".into();
            }
        }

        Crate {
            krate: krate,
            versions: json["versions"].clone(),
            keywords: json["keywords"].clone(),
        }
    }

    pub fn print_repository(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Repository:", self.krate["repository"])
        } else {
            format!("{}", self.krate["repository"])
        }
        // if let JsonValue::String(ref repository) = self.krate["repository"] {
        //     if verbose {
        //         format!("{:<16}{}", "Repository:", repository)
        //     } else {
        //         repository.clone()
        //     }
        // }
    }

    pub fn print_documentation(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Documentation:", self.krate["documentation"])
        } else {
            format!("{}", self.krate["documentation"])
        }
        // if let JsonValue::String(ref documentation) = self.krate["documentation"] {
        //     if verbose {
        //         format!("{:<16}{}", "Documentation:", documentation)
        //     } else {
        //         documentation.clone()
        //     }
        // }
    }

    pub fn print_downloads(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Downloads:", self.krate["downloads"])
        } else {
            format!("{}", self.krate["downloads"])
        }
        // if let JsonValue::Number(downloads) = self.krate["downloads"] {
        //     if verbose {
        //         format!("{:<16}{}", "Downloads:", downloads)
        //     } else {
        //         format!("{}", downloads)
        //     }
        // }
    }

    pub fn print_homepage(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Homepage:", self.krate["homepage"])
        } else {
            format!("{}", self.krate["homepage"])
        }
        // if let JsonValue::String(ref homepage) = self.krate["homepage"] {
        //     let fmt = if verbose {
        //         format!("{:<16}{}", "Homepage:", homepage)
        //     } else {
        //         homepage.clone()
        //     };
        //     println!("{}", fmt);
        // }
    }

    fn print_version(v: &JsonValue, verbose: bool) -> String {
        let created_at = TimeStamp::from(&v["created_at"]);
        let mut output = format!("{:<11}{:<#16}{:<11}", v["num"], created_at, v["downloads"]);

        if v["yanked"].as_bool() == Some(true) {
            output = output + "\t\t(yanked)";
        }

        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    fn print_version_header(verbose: bool) -> String {
        let output = format!("{:<11}{:<#16}{:<11}\n", "VERSION", "RELEASED", "DOWNLOADS");
        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    pub fn print_last_versions(&self, limit: usize, verbose: bool) -> String {
        let mut output = Crate::print_version_header(verbose);
        for version in self.versions.members().take(limit) {
            output = output + &Crate::print_version(version, verbose);
        }
        let length = self.versions.len();
        if limit < length {
            output = output + &format!("\n... use -VV to show all {} versions\n", length);
        }
        output
    }

    pub fn print_keywords(&self, verbose: bool) -> String {
        if verbose {
            format!("{:#}", self.keywords)
        } else {
            format!("{}", self.keywords)
        }
    }
}

impl fmt::Display for Crate {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let created_at = TimeStamp::from(&self.krate["created_at"]);
        let updated_at = TimeStamp::from(&self.krate["updated_at"]);

        let keywords = self.krate["keywords"]
            .members()
            .filter_map(|jv| jv.as_str())
            .collect::<Vec<_>>();

        if f.alternate() {
            write!(f,
                   "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                   format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                   format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                   format_args!("{:<16}{}", "Description:", self.krate["description"]),
                   format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                   format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                   format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                   format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                   format_args!("{:<16}{}", "License:", self.krate["license"]),
                   format_args!("{:<16}{:?}", "Keywords:", keywords),
                   format_args!("{:<16}{}  ({:#})", "Created at:", created_at, created_at),
                   format_args!("{:<16}{}  ({:#})", "Updated at:", updated_at, updated_at))
        } else {
            let mut versions = String::new();
            for line in self.print_last_versions(5, false).lines() {
                versions = versions + "\n";
                if !line.is_empty() {
                    versions = versions + "  " + line;
                }
            }

            write!(f,
                   "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                   format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                   format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                   format_args!("{:<16}{}", "Description:", self.krate["description"]),
                   format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                   format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                   format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                   format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                   format_args!("{:<16}{:#}", "Last updated:", updated_at),
                   format_args!("{:<16}\n{}", "Version history:", versions))
        }
    }
}
<commit_msg>[rustfmt]<commit_after>use std::fmt;

use chrono::{DateTime, Local, NaiveDateTime, TimeZone};
use chrono_humanize::HumanTime;
use json::JsonValue;

// #[derive(Debug, Default)]
// pub struct Error {
//     pub detail: String,
// }
//
// #[derive(Debug)]
// pub struct CrateLinks {
//     pub owners: Option<String>,
//     pub reverse_dependencies: String,
//     pub version_downloads: String,
//     pub versions: Option<String>,
// }
//
// pub struct Crate {
//     pub created_at: String,
//     pub description: Option<String>,
//     pub documentation: Option<String>,
//     pub downloads: i32,
//     pub homepage: Option<String>,
//     pub id: String,
//     pub keywords: Option<Vec<String>>,
//     pub license: Option<String>,
//     pub links: CrateLinks,
//     pub max_version: String,
//     pub name: String,
//     pub repository: Option<String>,
//     pub updated_at: String,
//     pub versions: Option<Vec<u64>>,
// }
//
// #[derive(Debug)]
// pub struct Keyword {
//     pub crates_cnt: u64,
//     pub created_at: String,
//     pub id: String,
//     pub keyword: String,
// }
//
// #[derive(Debug)]
// pub struct VersionLinks {
//     pub authors: String,
//     pub dependencies: String,
//     pub version_downloads: String,
// }
//
// #[derive(Debug)]
// pub struct Version {
//     pub krate: String,
//     pub created_at: String,
//     pub dl_path: String,
//     pub downloads: i32,
//     pub features: HashMap<String, Vec<String>>,
//     pub id: i32,
//     pub links: VersionLinks,
//     pub num: String,
//     pub updated_at: String,
//     pub yanked: bool,
// }
//
// pub struct Reply {
//     pub errors: Error,
//     pub krate: Crate,
//     pub keywords: Vec<Keyword>,
//     pub versions: Vec<Version>,
// }

struct TimeStamp(Option<DateTime<Local>>);

impl<'a> From<&'a JsonValue> for TimeStamp {
    fn from(jv: &JsonValue) -> Self {
        let parse_naive = |s: &str| s.parse::<NaiveDateTime>();
        let naive_to_local = |n: NaiveDateTime| Local.from_utc_datetime(&n);
        let parse_local = |s: &str| s.parse::<DateTime<Local>>();
        let parse = |s: &str| {
            parse_local(s)
                .or_else(|_| parse_naive(s).map(naive_to_local))
                .ok()
        };
        TimeStamp(jv.as_str().and_then(parse))
    }
}

impl fmt::Display for TimeStamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(ts) = self.0 {
            if f.alternate() {
                f.pad(&format!("{}", HumanTime::from(ts)))
            } else {
                f.pad(&format!("{}", ts.naive_local()))
            }
        } else {
            f.pad("")
        }
    }
}

pub struct Crate {
    krate: JsonValue,
    versions: JsonValue,
    keywords: JsonValue,
}

const FIELDS: [&'static str; 5] = [
    "description",
    "documentation",
    "homepage",
    "repository",
    "license",
];

impl Crate {
    pub fn new(json: &JsonValue) -> Self {
        let mut krate = json["crate"].clone();
        // Fix up fields that may be absent

        for field in &FIELDS {
            if krate[*field].is_null() {
                krate[*field] = "".into();
            }
        }

        Crate {
            krate: krate,
            versions: json["versions"].clone(),
            keywords: json["keywords"].clone(),
        }
    }

    pub fn print_repository(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Repository:", self.krate["repository"])
        } else {
            format!("{}", self.krate["repository"])
        }
        // if let JsonValue::String(ref repository) = self.krate["repository"] {
        //     if verbose {
        //         format!("{:<16}{}", "Repository:", repository)
        //     } else {
        //         repository.clone()
        //     }
        // }
    }

    pub fn print_documentation(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Documentation:", self.krate["documentation"])
        } else {
            format!("{}", self.krate["documentation"])
        }
        // if let JsonValue::String(ref documentation) = self.krate["documentation"] {
        //     if verbose {
        //         format!("{:<16}{}", "Documentation:", documentation)
        //     } else {
        //         documentation.clone()
        //     }
        // }
    }

    pub fn print_downloads(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Downloads:", self.krate["downloads"])
        } else {
            format!("{}", self.krate["downloads"])
        }
        // if let JsonValue::Number(downloads) = self.krate["downloads"] {
        //     if verbose {
        //         format!("{:<16}{}", "Downloads:", downloads)
        //     } else {
        //         format!("{}", downloads)
        //     }
        // }
    }

    pub fn print_homepage(&self, verbose: bool) -> String {
        if verbose {
            format!("{:<16}{}", "Homepage:", self.krate["homepage"])
        } else {
            format!("{}", self.krate["homepage"])
        }
        // if let JsonValue::String(ref homepage) = self.krate["homepage"] {
        //     let fmt = if verbose {
        //         format!("{:<16}{}", "Homepage:", homepage)
        //     } else {
        //         homepage.clone()
        //     };
        //     println!("{}", fmt);
        // }
    }

    fn print_version(v: &JsonValue, verbose: bool) -> String {
        let created_at = TimeStamp::from(&v["created_at"]);
        let mut output = format!("{:<11}{:<#16}{:<11}", v["num"], created_at, v["downloads"]);

        if v["yanked"].as_bool() == Some(true) {
            output = output + "\t\t(yanked)";
        }

        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    fn print_version_header(verbose: bool) -> String {
        let output = format!("{:<11}{:<#16}{:<11}\n", "VERSION", "RELEASED", "DOWNLOADS");
        if verbose {
            // Consider adding some more useful information in verbose mode
            output + "\n"
        } else {
            output + "\n"
        }
    }

    pub fn print_last_versions(&self, limit: usize, verbose: bool) -> String {
        let mut output = Crate::print_version_header(verbose);
        for version in self.versions.members().take(limit) {
            output = output + &Crate::print_version(version, verbose);
        }
        let length = self.versions.len();
        if limit < length {
            output = output + &format!("\n... use -VV to show all {} versions\n", length);
        }
        output
    }

    pub fn print_keywords(&self, verbose: bool) -> String {
        if verbose {
            format!("{:#}", self.keywords)
        } else {
            format!("{}", self.keywords)
        }
    }
}

impl fmt::Display for Crate {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let created_at = TimeStamp::from(&self.krate["created_at"]);
        let updated_at = TimeStamp::from(&self.krate["updated_at"]);

        let keywords = self.krate["keywords"]
            .members()
            .filter_map(|jv| jv.as_str())
            .collect::<Vec<_>>();

        if f.alternate() {
            write!(
                f,
                "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                format_args!("{:<16}{}", "Description:", self.krate["description"]),
                format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                format_args!("{:<16}{}", "License:", self.krate["license"]),
                format_args!("{:<16}{:?}", "Keywords:", keywords),
                format_args!("{:<16}{}  ({:#})", "Created at:", created_at, created_at),
                format_args!("{:<16}{}  ({:#})", "Updated at:", updated_at, updated_at)
            )
        } else {
            let mut versions = String::new();
            for line in self.print_last_versions(5, false).lines() {
                versions = versions + "\n";
                if !line.is_empty() {
                    versions = versions + "  " + line;
                }
            }

            write!(
                f,
                "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}",
                format_args!("{:<16}{}", "Crate:", self.krate["name"]),
                format_args!("{:<16}{}", "Version:", self.krate["max_version"]),
                format_args!("{:<16}{}", "Description:", self.krate["description"]),
                format_args!("{:<16}{}", "Downloads:", self.krate["downloads"]),
                format_args!("{:<16}{}", "Homepage:", self.krate["homepage"]),
                format_args!("{:<16}{}", "Documentation:", self.krate["documentation"]),
                format_args!("{:<16}{}", "Repository:", self.krate["repository"]),
                format_args!("{:<16}{:#}", "Last updated:", updated_at),
                format_args!("{:<16}\n{}", "Version history:", versions)
            )
        }
    }
}
<|endoftext|>


<commit_before>use num::Num;

#[inline(always)]
pub fn new<T: Num>(x: T, y: T, z: T) -> [T; 3] {[x, y, z]}
#[inline(always)]
pub fn create<T: Num>(x: T, y: T, z: T) -> [T; 3] {new(x, y, z)}
#[test]
fn test_new() {
    let v = new(1, 2, 3);
    assert!(v[0] == 1);
    assert!(v[1] == 2);
    assert!(v[2] == 3);
}

#[inline(always)]
pub fn clone<'b, T: Num>(v: &'b [T; 3]) -> [T; 3] {new(v[0], v[1], v[2])}

#[inline(always)]
pub fn copy<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out
}
#[test]
fn test_copy() {
    let mut v = [0, 0, 0];
    copy(&mut v, &[1, 2, 3]);
    assert!(v == [1, 2, 3]);
}
<commit_msg>clean up<commit_after>use num::Num;

#[inline(always)]
pub fn new<T: Num>(x: T, y: T, z: T) -> [T; 3] {[x, y, z]}
#[inline(always)]
pub fn create<T: Num>(x: T, y: T, z: T) -> [T; 3] {new(x, y, z)}
#[test]
fn test_new() {
    let v = new(1, 2, 3);
    assert!(v[0] == 1);
    assert!(v[1] == 2);
    assert!(v[2] == 3);
}

#[inline(always)]
pub fn clone<'b, T: Num>(v: &'b [T; 3]) -> [T; 3] {new(v[0], v[1], v[2])}

#[inline(always)]
pub fn copy<'a, 'b, T: Num>(out: &'a mut [T; 3], a: &'b [T; 3]) -> &'a mut [T; 3] {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out
}
#[test]
fn test_copy() {
    let mut v = [0, 0, 0];
    copy(&mut v, &[1, 2, 3]);
    assert!(v == [1, 2, 3]);
}

#[inline(always)]
pub fn from_vec2<'a, 'b, T: Num>(out: &'a mut [T; 3], v: &'b [T; 2]) -> &'a mut [T; 3] {
    out[0] = v[0];
    out[1] = v[1];
    out
}
#[inline(always)]
pub fn from_vec4<'a, 'b, T: Num>(out: &'a mut [T; 3], v: &'b [T; 4]) -> &'a mut [T; 3] {
    out[0] = v[0];
    out[1] = v[1];
    out[2] = v[2];
    out
}
<|endoftext|>