<commit_before>//! Crate **ruma_identifiers** contains types for [Matrix](https://matrix.org/) identifiers
//! for events, rooms, room aliases, and users.

#![deny(missing_docs)]

#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate url;

use std::fmt::{Display, Formatter, Result as FmtResult};

use regex::Regex;
use url::{Host, ParseError, Url};

/// All events must be 255 bytes or less.
const MAX_BYTES: usize = 255;
/// The minimum number of characters an ID can be.
///
/// This is an optimization and not required by the spec. The shortest possible valid ID is a sigil
/// + a single character local ID + a colon + a single character hostname.
const MIN_CHARS: usize = 4;
/// The number of bytes in a valid sigil.
const SIGIL_BYTES: usize = 1;

lazy_static! {
    static ref USER_LOCALPART_PATTERN: Regex =
        Regex::new(r"\A[a-z0-9._=-]+\z").expect("Failed to create user localpart regex.");
}

/// An error encountered when trying to parse an invalid ID string.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// The ID's localpart contains invalid characters.
    ///
    /// Only relevant for user IDs.
    InvalidCharacters,
    /// The domain part of the the ID string is not a valid IP address or DNS name.
    InvalidHost,
    /// The ID exceeds 255 bytes.
    MaximumLengthExceeded,
    /// The ID is less than 4 characters.
    MinimumLengthNotSatisfied,
    /// The ID is missing the colon delimiter between localpart and server name.
    MissingDelimiter,
    /// The ID is missing the leading sigil.
    MissingSigil,
}

/// A Matrix event ID.
///
/// An `EventId` is created from a string slice, and can be converted back into a string as needed:
///
/// ```
/// # use ruma_identifiers::EventId;
/// assert_eq!(EventId::new("$h29iv0s8:example.com").unwrap().to_string(), "$h29iv0s8:example.com");
/// ```
#[derive(Debug)]
pub struct EventId {
    hostname: Host,
    opaque_id: String,
    port: u16,
}

/// A Matrix room ID.
///
/// An `RoomId` is created from a string slice, and can be converted back into a string as needed:
///
/// ```
/// # use ruma_identifiers::RoomId;
/// assert_eq!(RoomId::new("!n8f893n9:example.com").unwrap().to_string(), "!n8f893n9:example.com");
/// ```
#[derive(Debug)]
pub struct RoomId {
    hostname: Host,
    opaque_id: String,
    port: u16,
}

/// A Matrix user ID.
///
/// A `UserId` is created from a string slice, and can be converted back into a string as needed:
///
/// ```
/// # use ruma_identifiers::UserId;
/// assert_eq!(UserId::new("@carl:example.com").unwrap().to_string(), "@carl:example.com");
/// ```
#[derive(Debug)]
pub struct UserId {
    hostname: Host,
    localpart: String,
    port: u16,
}

fn display(f: &mut Formatter, sigil: char, localpart: &str, hostname: &Host, port: u16)
-> FmtResult {
    if port == 443 {
        write!(f, "{}{}:{}", sigil, localpart, hostname)
    } else {
        write!(f, "{}{}:{}:{}", sigil, localpart, hostname, port)
    }
}

fn parse_id<'a>(required_sigil: char, id: &'a str) -> Result<(&'a str, Host, u16), Error> {
    if id.len() > MAX_BYTES {
        return Err(Error::MaximumLengthExceeded);
    }

    let mut chars = id.chars();

    if id.len() < MIN_CHARS {
        return Err(Error::MinimumLengthNotSatisfied);
    }

    let sigil = chars.nth(0).expect("ID missing first character.");

    if sigil != required_sigil {
        return Err(Error::MissingSigil);
    }

    let delimiter_index = match chars.position(|c| c == ':') {
        Some(index) => index + 1,
        None => return Err(Error::MissingDelimiter),
    };

    let localpart = &id[1..delimiter_index];
    let raw_host = &id[delimiter_index + SIGIL_BYTES..];
    let url_string = format!("https://{}", raw_host);
    let url = try!(Url::parse(&url_string));

    let host = match url.host() {
        Some(host) => host.to_owned(),
        None => return Err(Error::InvalidHost),
    };

    let port = url.port().unwrap_or(443);

    Ok((localpart, host, port))
}

impl EventId {
    /// Creates a new Matrix event ID from a string representation.
    ///
    /// The string must include the leading $ sigil, the opaque ID, a literal colon, and a valid
    /// server name.
    pub fn new(event_id: &str) -> Result<Self, Error> {
        let (opaque_id, host, port) = try!(parse_id('$', event_id));

        Ok(EventId {
            hostname: host,
            opaque_id: opaque_id.to_owned(),
            port: port,
        })
    }

    /// Returns a `url::Host` for the event ID, containing the server name (minus the port) of the
    /// originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the event's opaque ID.
    pub fn opaque_id(&self) -> &str {
        &self.opaque_id
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl RoomId {
    /// Creates a new Matrix room ID from a string representation.
    ///
    /// The string must include the leading ! sigil, the opaque ID, a literal colon, and a valid
    /// server name.
    pub fn new(room_id: &str) -> Result<Self, Error> {
        let (opaque_id, host, port) = try!(parse_id('!', room_id));

        Ok(RoomId {
            hostname: host,
            opaque_id: opaque_id.to_owned(),
            port: port,
        })
    }

    /// Returns a `url::Host` for the room ID, containing the server name (minus the port) of the
    /// originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the event's opaque ID.
    pub fn opaque_id(&self) -> &str {
        &self.opaque_id
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl UserId {
    /// Creates a new Matrix user ID from a string representation.
    ///
    /// The string must include the leading @ sigil, the localpart, a literal colon, and a valid
    /// server name.
    pub fn new(user_id: &str) -> Result<UserId, Error> {
        let (localpart, host, port) = try!(parse_id('@', user_id));

        if !USER_LOCALPART_PATTERN.is_match(localpart) {
            return Err(Error::InvalidCharacters);
        }

        Ok(UserId {
            hostname: host,
            port: port,
            localpart: localpart.to_owned(),
        })
    }

    /// Returns a `url::Host` for the user ID, containing the server name (minus the port) of the
    /// originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the user's localpart.
    pub fn localpart(&self) -> &str {
        &self.localpart
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl From<ParseError> for Error {
    fn from(_: ParseError) -> Error {
        Error::InvalidHost
    }
}

impl Display for EventId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '$', &self.opaque_id, &self.hostname, self.port)
    }
}

impl Display for RoomId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '!', &self.opaque_id, &self.hostname, self.port)
    }
}

impl Display for UserId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '@', &self.localpart, &self.hostname, self.port)
    }
}

#[cfg(test)]
mod tests {
    use super::{Error, EventId, RoomId, UserId};

    #[test]
    fn valid_event_id() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com")
                .expect("Failed to create EventId.")
                .to_string(),
            "$39hvsi03hlne:example.com"
        );
    }

    #[test]
    fn valid_event_id_with_explicit_standard_port() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com:443")
                .expect("Failed to create EventId.")
                .to_string(),
            "$39hvsi03hlne:example.com"
        );
    }

    #[test]
    fn valid_event_id_with_non_standard_port() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com:5000")
                .expect("Failed to create EventId.")
                .to_string(),
            "$39hvsi03hlne:example.com:5000"
        );
    }

    #[test]
    fn missing_event_id_sigil() {
        assert_eq!(
            EventId::new("39hvsi03hlne:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_event_id_delimiter() {
        assert_eq!(
            EventId::new("$39hvsi03hlne").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_event_id_host() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_event_id_port() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn valid_room_id() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com")
                .expect("Failed to create RoomId.")
                .to_string(),
            "!29fhd83h92h0:example.com"
        );
    }

    #[test]
    fn valid_room_id_with_explicit_standard_port() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com:443")
                .expect("Failed to create RoomId.")
                .to_string(),
            "!29fhd83h92h0:example.com"
        );
    }

    #[test]
    fn valid_room_id_with_non_standard_port() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com:5000")
                .expect("Failed to create RoomId.")
                .to_string(),
            "!29fhd83h92h0:example.com:5000"
        );
    }

    #[test]
    fn missing_room_id_sigil() {
        assert_eq!(
            RoomId::new("carl:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_room_id_delimiter() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_room_id_host() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_room_id_port() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn valid_user_id() {
        assert_eq!(
            UserId::new("@carl:example.com")
                .expect("Failed to create UserId.")
                .to_string(),
            "@carl:example.com"
        );
    }

    #[test]
    fn valid_user_id_with_explicit_standard_port() {
        assert_eq!(
            UserId::new("@carl:example.com:443")
                .expect("Failed to create UserId.")
                .to_string(),
            "@carl:example.com"
        );
    }

    #[test]
    fn valid_user_id_with_non_standard_port() {
        assert_eq!(
            UserId::new("@carl:example.com:5000")
                .expect("Failed to create UserId.")
                .to_string(),
            "@carl:example.com:5000"
        );
    }

    #[test]
    fn invalid_characters_in_user_id_localpart() {
        assert_eq!(
            UserId::new("@CARL:example.com").err().unwrap(),
            Error::InvalidCharacters
        );
    }

    #[test]
    fn missing_user_id_sigil() {
        assert_eq!(
            UserId::new("carl:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_user_id_delimiter() {
        assert_eq!(
            UserId::new("@carl").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_user_id_host() {
        assert_eq!(
            UserId::new("@carl:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_user_id_port() {
        assert_eq!(
            UserId::new("@carl:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }
}
<commit_msg>Add RoomAliasId.<commit_after>//! Crate **ruma_identifiers** contains types for [Matrix](https://matrix.org/) identifiers
//! for events, rooms, room aliases, and users.

#![deny(missing_docs)]

#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate url;

use std::fmt::{Display, Formatter, Result as FmtResult};

use regex::Regex;
use url::{Host, ParseError, Url};

/// All events must be 255 bytes or less.
const MAX_BYTES: usize = 255;
/// The minimum number of characters an ID can be.
///
/// This is an optimization and not required by the spec. The shortest possible valid ID is a sigil
/// + a single character local ID + a colon + a single character hostname.
const MIN_CHARS: usize = 4;
/// The number of bytes in a valid sigil.
const SIGIL_BYTES: usize = 1;

lazy_static! {
    static ref USER_LOCALPART_PATTERN: Regex =
        Regex::new(r"\A[a-z0-9._=-]+\z").expect("Failed to create user localpart regex.");
}

/// An error encountered when trying to parse an invalid ID string.
#[derive(Debug, PartialEq)]
pub enum Error {
    /// The ID's localpart contains invalid characters.
    ///
    /// Only relevant for user IDs.
    InvalidCharacters,
    /// The domain part of the the ID string is not a valid IP address or DNS name.
    InvalidHost,
    /// The ID exceeds 255 bytes.
    MaximumLengthExceeded,
    /// The ID is less than 4 characters.
    MinimumLengthNotSatisfied,
    /// The ID is missing the colon delimiter between localpart and server name.
    MissingDelimiter,
    /// The ID is missing the leading sigil.
    MissingSigil,
}

/// A Matrix event ID.
///
/// An `EventId` is created from a string slice, and can be converted back into a string as needed:
///
/// ```
/// # use ruma_identifiers::EventId;
/// assert_eq!(EventId::new("$h29iv0s8:example.com").unwrap().to_string(), "$h29iv0s8:example.com");
/// ```
#[derive(Debug)]
pub struct EventId {
    hostname: Host,
    opaque_id: String,
    port: u16,
}

/// A Matrix room alias ID.
///
/// A `RoomAliasId` is created from a string slice, and can be converted back into a string as
/// needed:
///
/// ```
/// # use ruma_identifiers::RoomAliasId;
/// assert_eq!(RoomAliasId::new("#ruma:example.com").unwrap().to_string(), "#ruma:example.com");
/// ```
#[derive(Debug)]
pub struct RoomAliasId {
    alias: String,
    hostname: Host,
    port: u16,
}

/// A Matrix room ID.
///
/// A `RoomId` is created from a string slice, and can be converted back into a string as needed:
///
/// ```
/// # use ruma_identifiers::RoomId;
/// assert_eq!(RoomId::new("!n8f893n9:example.com").unwrap().to_string(), "!n8f893n9:example.com");
/// ```
#[derive(Debug)]
pub struct RoomId {
    hostname: Host,
    opaque_id: String,
    port: u16,
}

/// A Matrix user ID.
///
/// A `UserId` is created from a string slice, and can be converted back into a string as needed:
///
/// ```
/// # use ruma_identifiers::UserId;
/// assert_eq!(UserId::new("@carl:example.com").unwrap().to_string(), "@carl:example.com");
/// ```
#[derive(Debug)]
pub struct UserId {
    hostname: Host,
    localpart: String,
    port: u16,
}

fn display(f: &mut Formatter, sigil: char, localpart: &str, hostname: &Host, port: u16)
-> FmtResult {
    if port == 443 {
        write!(f, "{}{}:{}", sigil, localpart, hostname)
    } else {
        write!(f, "{}{}:{}:{}", sigil, localpart, hostname, port)
    }
}

fn parse_id<'a>(required_sigil: char, id: &'a str) -> Result<(&'a str, Host, u16), Error> {
    if id.len() > MAX_BYTES {
        return Err(Error::MaximumLengthExceeded);
    }

    let mut chars = id.chars();

    if id.len() < MIN_CHARS {
        return Err(Error::MinimumLengthNotSatisfied);
    }

    let sigil = chars.nth(0).expect("ID missing first character.");

    if sigil != required_sigil {
        return Err(Error::MissingSigil);
    }

    let delimiter_index = match chars.position(|c| c == ':') {
        Some(index) => index + 1,
        None => return Err(Error::MissingDelimiter),
    };

    let localpart = &id[1..delimiter_index];
    let raw_host = &id[delimiter_index + SIGIL_BYTES..];
    let url_string = format!("https://{}", raw_host);
    let url = try!(Url::parse(&url_string));

    let host = match url.host() {
        Some(host) => host.to_owned(),
        None => return Err(Error::InvalidHost),
    };

    let port = url.port().unwrap_or(443);

    Ok((localpart, host, port))
}

impl EventId {
    /// Creates a new Matrix event ID from a string representation.
    ///
    /// The string must include the leading $ sigil, the opaque ID, a literal colon, and a valid
    /// server name.
    pub fn new(event_id: &str) -> Result<Self, Error> {
        let (opaque_id, host, port) = try!(parse_id('$', event_id));

        Ok(EventId {
            hostname: host,
            opaque_id: opaque_id.to_owned(),
            port: port,
        })
    }

    /// Returns a `url::Host` for the event ID, containing the server name (minus the port) of the
    /// originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the event's opaque ID.
    pub fn opaque_id(&self) -> &str {
        &self.opaque_id
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl RoomId {
    /// Creates a new Matrix room ID from a string representation.
    ///
    /// The string must include the leading ! sigil, the opaque ID, a literal colon, and a valid
    /// server name.
    pub fn new(room_id: &str) -> Result<Self, Error> {
        let (opaque_id, host, port) = try!(parse_id('!', room_id));

        Ok(RoomId {
            hostname: host,
            opaque_id: opaque_id.to_owned(),
            port: port,
        })
    }

    /// Returns a `url::Host` for the room ID, containing the server name (minus the port) of the
    /// originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the event's opaque ID.
    pub fn opaque_id(&self) -> &str {
        &self.opaque_id
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl RoomAliasId {
    /// Creates a new Matrix room alias ID from a string representation.
    ///
    /// The string must include the leading # sigil, the alias, a literal colon, and a valid
    /// server name.
    pub fn new(room_id: &str) -> Result<Self, Error> {
        let (alias, host, port) = try!(parse_id('#', room_id));

        Ok(RoomAliasId {
            alias: alias.to_owned(),
            hostname: host,
            port: port,
        })
    }

    /// Returns a `url::Host` for the room alias ID, containing the server name (minus the port) of
    /// the originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the room's alias.
    pub fn alias(&self) -> &str {
        &self.alias
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl UserId {
    /// Creates a new Matrix user ID from a string representation.
    ///
    /// The string must include the leading @ sigil, the localpart, a literal colon, and a valid
    /// server name.
    pub fn new(user_id: &str) -> Result<UserId, Error> {
        let (localpart, host, port) = try!(parse_id('@', user_id));

        if !USER_LOCALPART_PATTERN.is_match(localpart) {
            return Err(Error::InvalidCharacters);
        }

        Ok(UserId {
            hostname: host,
            port: port,
            localpart: localpart.to_owned(),
        })
    }

    /// Returns a `url::Host` for the user ID, containing the server name (minus the port) of the
    /// originating homeserver.
    ///
    /// The host can be either a domain name, an IPv4 address, or an IPv6 address.
    pub fn hostname(&self) -> &Host {
        &self.hostname
    }

    /// Returns the user's localpart.
    pub fn localpart(&self) -> &str {
        &self.localpart
    }

    /// Returns the port the originating homeserver can be accessed on.
    pub fn port(&self) -> u16 {
        self.port
    }
}

impl From<ParseError> for Error {
    fn from(_: ParseError) -> Error {
        Error::InvalidHost
    }
}

impl Display for EventId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '$', &self.opaque_id, &self.hostname, self.port)
    }
}

impl Display for RoomAliasId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '#', &self.alias, &self.hostname, self.port)
    }
}

impl Display for RoomId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '!', &self.opaque_id, &self.hostname, self.port)
    }
}

impl Display for UserId {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        display(f, '@', &self.localpart, &self.hostname, self.port)
    }
}

#[cfg(test)]
mod tests {
    use super::{Error, EventId, RoomAliasId, RoomId, UserId};

    #[test]
    fn valid_event_id() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com")
                .expect("Failed to create EventId.")
                .to_string(),
            "$39hvsi03hlne:example.com"
        );
    }

    #[test]
    fn valid_event_id_with_explicit_standard_port() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com:443")
                .expect("Failed to create EventId.")
                .to_string(),
            "$39hvsi03hlne:example.com"
        );
    }

    #[test]
    fn valid_event_id_with_non_standard_port() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com:5000")
                .expect("Failed to create EventId.")
                .to_string(),
            "$39hvsi03hlne:example.com:5000"
        );
    }

    #[test]
    fn missing_event_id_sigil() {
        assert_eq!(
            EventId::new("39hvsi03hlne:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_event_id_delimiter() {
        assert_eq!(
            EventId::new("$39hvsi03hlne").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_event_id_host() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_event_id_port() {
        assert_eq!(
            EventId::new("$39hvsi03hlne:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn valid_room_alias_id() {
        assert_eq!(
            RoomAliasId::new("#ruma:example.com")
                .expect("Failed to create RoomAliasId.")
                .to_string(),
            "#ruma:example.com"
        );
    }

    #[test]
    fn valid_room_alias_id_with_explicit_standard_port() {
        assert_eq!(
            RoomAliasId::new("#ruma:example.com:443")
                .expect("Failed to create RoomAliasId.")
                .to_string(),
            "#ruma:example.com"
        );
    }

    #[test]
    fn valid_room_alias_id_with_non_standard_port() {
        assert_eq!(
            RoomAliasId::new("#ruma:example.com:5000")
                .expect("Failed to create RoomAliasId.")
                .to_string(),
            "#ruma:example.com:5000"
        );
    }

    #[test]
    fn missing_room_alias_id_sigil() {
        assert_eq!(
            RoomAliasId::new("39hvsi03hlne:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_room_alias_id_delimiter() {
        assert_eq!(
            RoomAliasId::new("#ruma").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_room_alias_id_host() {
        assert_eq!(
            RoomAliasId::new("#ruma:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_room_alias_id_port() {
        assert_eq!(
            RoomAliasId::new("#ruma:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }
    #[test]
    fn valid_room_id() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com")
                .expect("Failed to create RoomId.")
                .to_string(),
            "!29fhd83h92h0:example.com"
        );
    }

    #[test]
    fn valid_room_id_with_explicit_standard_port() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com:443")
                .expect("Failed to create RoomId.")
                .to_string(),
            "!29fhd83h92h0:example.com"
        );
    }

    #[test]
    fn valid_room_id_with_non_standard_port() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com:5000")
                .expect("Failed to create RoomId.")
                .to_string(),
            "!29fhd83h92h0:example.com:5000"
        );
    }

    #[test]
    fn missing_room_id_sigil() {
        assert_eq!(
            RoomId::new("carl:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_room_id_delimiter() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_room_id_host() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_room_id_port() {
        assert_eq!(
            RoomId::new("!29fhd83h92h0:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn valid_user_id() {
        assert_eq!(
            UserId::new("@carl:example.com")
                .expect("Failed to create UserId.")
                .to_string(),
            "@carl:example.com"
        );
    }

    #[test]
    fn valid_user_id_with_explicit_standard_port() {
        assert_eq!(
            UserId::new("@carl:example.com:443")
                .expect("Failed to create UserId.")
                .to_string(),
            "@carl:example.com"
        );
    }

    #[test]
    fn valid_user_id_with_non_standard_port() {
        assert_eq!(
            UserId::new("@carl:example.com:5000")
                .expect("Failed to create UserId.")
                .to_string(),
            "@carl:example.com:5000"
        );
    }

    #[test]
    fn invalid_characters_in_user_id_localpart() {
        assert_eq!(
            UserId::new("@CARL:example.com").err().unwrap(),
            Error::InvalidCharacters
        );
    }

    #[test]
    fn missing_user_id_sigil() {
        assert_eq!(
            UserId::new("carl:example.com").err().unwrap(),
            Error::MissingSigil
        );
    }

    #[test]
    fn missing_user_id_delimiter() {
        assert_eq!(
            UserId::new("@carl").err().unwrap(),
            Error::MissingDelimiter
        );
    }

    #[test]
    fn invalid_user_id_host() {
        assert_eq!(
            UserId::new("@carl:-").err().unwrap(),
            Error::InvalidHost
        );
    }

    #[test]
    fn invalid_user_id_port() {
        assert_eq!(
            UserId::new("@carl:example.com:notaport").err().unwrap(),
            Error::InvalidHost
        );
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]

#![feature(read_exact)]

extern crate byteorder;
extern crate time;

use std::io;
use std::io::prelude::*;
use std::net::TcpStream;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::thread;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use byteorder::{ByteOrder, LittleEndian};
use time::{Duration, PreciseTime};

pub struct Ntr {
    tcp_stream: TcpStream,
    current_seq: AtomicUsize,
    is_heartbeat_sendable: AtomicBool,
    read_mem_rx: Receiver<Vec<u8>>,
}
unsafe impl Sync for Ntr {} // TODO: fix this properly
impl Ntr {
    pub fn connect(address: &str) -> io::Result<Arc<Self>> {
        let tcp_stream = try!(TcpStream::connect(&(address.to_owned() + ":8000") as &str));
        let (read_mem_tx, read_mem_rx) = mpsc::channel();

        let ntr = Arc::new(Ntr {
            tcp_stream: tcp_stream,
            current_seq: AtomicUsize::new(1000),
            is_heartbeat_sendable: AtomicBool::new(true),
            read_mem_rx: read_mem_rx,
        });

        // spawn receiver thread
        {
            let ntr = ntr.clone();
            thread::spawn(move || {
                let mut ntr_stream = NtrStream::new(&ntr);
                let mut buf = [0u8; 84];
                loop {
                    if let Err(_) = ntr_stream.tcp_stream().read_exact(&mut buf) {
                        break;
                    }
                    //let seq = LittleEndian::read_u32(&buf[4..8]);
                    let cmd = LittleEndian::read_u32(&buf[12..16]);
                    let data_len = LittleEndian::read_u32(&buf[80..84]) as usize;

                    if data_len != 0 {
                        let mut data_buf = vec![0u8; data_len];
                        ntr_stream.tcp_stream().read_exact(&mut data_buf[0..data_len]).unwrap();
                        if cmd == 0 {
                            ntr_stream.is_heartbeat_sendable().store(true, Ordering::SeqCst);
                        } else if cmd == 9 {
                            read_mem_tx.send(data_buf).unwrap();
                        }
                    }
                }
            });
        }

        // spawn heartbeat thread
        {
            let ntr = ntr.clone();
            thread::spawn(move || {
                let mut ntr_stream = NtrStream::new(&ntr);
                let one_second = Duration::seconds(1);
                let mut heartbeat_sent_time = PreciseTime::now();
                ntr_stream.send_heartbeat_packet().unwrap();
                loop {
                    if heartbeat_sent_time.to(PreciseTime::now()) >= one_second
                     && ntr_stream.is_heartbeat_sendable().compare_and_swap(true, false, Ordering::SeqCst) {
                        ntr_stream.send_heartbeat_packet().unwrap();
                        heartbeat_sent_time = PreciseTime::now();
                    }
                    thread::sleep_ms(100);
                }
            });
        }

        Ok(ntr)
    }

    pub fn read_mem(&self, addr: u32, size: u32, pid: u32) -> Result<Vec<u8>, ()> {
        let mut ntr_stream = NtrStream::new(&self);
        try!(ntr_stream.send_read_mem_packet(addr, size, pid).map_err(|_x| ()));
        self.read_mem_rx.recv().map_err(|_x| ())
    }

    pub fn write_mem(&self, addr: u32, data: Vec<u8>) {
        unimplemented!();
    }
}

#[derive(Debug)]
struct NtrStream<'a> {
    tcp_stream: TcpStream,
    current_seq: &'a AtomicUsize,
    is_heartbeat_sendable: &'a AtomicBool,
}
impl<'a> NtrStream<'a> {
    fn new(ntr: &'a Ntr) -> Self {
        NtrStream {
            tcp_stream: ntr.tcp_stream.try_clone().unwrap(),
            current_seq: &ntr.current_seq,
            is_heartbeat_sendable: &ntr.is_heartbeat_sendable,
        }
    }

    fn send_packet(&mut self, packet_type: u32, cmd: u32, args: &[u32], data_len: u32) -> io::Result<usize> {
        let mut buf = [0u8; 84];

        LittleEndian::write_u32(&mut buf[0..4], 0x12345678);
        LittleEndian::write_u32(&mut buf[4..8], self.current_seq.fetch_add(1000, Ordering::SeqCst) as u32);
        LittleEndian::write_u32(&mut buf[8..12], packet_type);
        LittleEndian::write_u32(&mut buf[12..16], cmd);
        for i in 0..16 {
            LittleEndian::write_u32(&mut buf[(4 * i + 16)..(4 * i + 20)], args[i]);
        }
        LittleEndian::write_u32(&mut buf[80..84], data_len);

        self.tcp_stream.write(&buf)
    }

    fn send_read_mem_packet(&mut self, addr: u32, size: u32, pid: u32) -> io::Result<usize> {
        self.send_empty_packet(9, pid, addr, size)
    }

    fn send_write_mem_packet(&mut self, addr: u32, pid: u32, buf: &Vec<u8>) -> io::Result<usize> {
        let args = &mut [0u32; 16];
        args[0] = pid;
        args[1] = addr;
        args[2] = buf.len() as u32;
        self.send_packet(1, 10, args, args[2])
            .and(self.tcp_stream.write(buf))
    }

    fn send_heartbeat_packet(&mut self) -> io::Result<usize> {
        self.send_packet(0, 0, &[0u32; 16], 0)
    }

    fn send_hello_packet(&mut self) -> io::Result<usize> {
        self.send_packet(0, 3, &[0u32; 16], 0)
    }

    fn send_reload_packet(&mut self) -> io::Result<usize> {
        self.send_packet(0, 4, &[0u32; 16], 0)
    }

    fn send_empty_packet(&mut self, cmd: u32, arg0: u32, arg1: u32, arg2: u32) -> io::Result<usize> {
        let mut args = [0u32; 16];
        args[0] = arg0;
        args[1] = arg1;
        args[2] = arg2;
        self.send_packet(0, cmd, &args, 0)
    }

    fn tcp_stream(&mut self) -> &TcpStream {
        &self.tcp_stream
    }

    fn is_heartbeat_sendable(&self) -> &AtomicBool {
        &self.is_heartbeat_sendable
    }
}<commit_msg>implement memory writing; break heartbeat sending<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]

#![feature(read_exact)]

extern crate byteorder;
extern crate time;

use std::io;
use std::io::prelude::*;
use std::net::TcpStream;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::thread;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use byteorder::{ByteOrder, LittleEndian};
use time::{Duration, PreciseTime};

pub struct Ntr {
    tcp_stream: TcpStream,
    current_seq: AtomicUsize,
    is_heartbeat_sendable: AtomicBool,
    mem_read_rx: Receiver<Vec<u8>>,
}
unsafe impl Sync for Ntr {} // TODO: fix this properly
impl Ntr {
    pub fn connect(address: &str) -> io::Result<Arc<Self>> {
        let tcp_stream = try!(TcpStream::connect(&(address.to_owned() + ":8000") as &str));
        let (mem_read_tx, mem_read_rx) = mpsc::channel();

        let ntr = Arc::new(Ntr {
            tcp_stream: tcp_stream,
            current_seq: AtomicUsize::new(1000),
            is_heartbeat_sendable: AtomicBool::new(true),
            mem_read_rx: mem_read_rx,
        });

        // spawn receiver thread
        {
            let ntr = ntr.clone();
            thread::spawn(move || {
                let mut ntr_stream = NtrStream::new(&ntr);
                let mut buf = [0u8; 84];
                loop {
                    if let Err(_) = ntr_stream.tcp_stream().read_exact(&mut buf) {
                        break;
                    }
                    let cmd = LittleEndian::read_u32(&buf[12..16]);
                    let data_len = LittleEndian::read_u32(&buf[80..84]) as usize;

                    if data_len != 0 {
                        let mut data_buf = vec![0u8; data_len];
                        ntr_stream.tcp_stream().read_exact(&mut data_buf[0..data_len]).unwrap();
                        if cmd == 0 {
                            ntr_stream.is_heartbeat_sendable().store(true, Ordering::SeqCst);
                        } else if cmd == 9 {
                            mem_read_tx.send(data_buf).unwrap();
                        }
                    }
                }
            });
        }

        // spawn heartbeat thread
        /*{
            let ntr = ntr.clone();
            thread::spawn(move || {
                let mut ntr_stream = NtrStream::new(&ntr);
                let one_second = Duration::seconds(1);
                let mut heartbeat_sent_time = PreciseTime::now();
                ntr_stream.send_heartbeat_packet().unwrap();
                loop {
                    if heartbeat_sent_time.to(PreciseTime::now()) >= one_second
                     && ntr_stream.is_heartbeat_sendable().compare_and_swap(true, false, Ordering::SeqCst) {
                        ntr_stream.send_heartbeat_packet().unwrap();
                        heartbeat_sent_time = PreciseTime::now();
                    }
                    thread::sleep_ms(100);
                }
            });
        }*/

        Ok(ntr)
    }

    pub fn mem_read(&self, addr: u32, size: u32, pid: u32) -> Result<Vec<u8>, ()> {
        let mut ntr_stream = NtrStream::new(&self);
        try!(ntr_stream.send_mem_read_packet(addr, size, pid).map_err(|_x| ()));
        self.mem_read_rx.recv().map_err(|_x| ())
    }

    pub fn mem_write(&self, addr: u32, data: &Vec<u8>, pid: u32) -> io::Result<usize> {
        NtrStream::new(&self).send_mem_write_packet(addr, pid, data)
    }
}

#[derive(Debug)]
struct NtrStream<'a> {
    tcp_stream: TcpStream,
    current_seq: &'a AtomicUsize,
    is_heartbeat_sendable: &'a AtomicBool,
}
impl<'a> NtrStream<'a> {
    fn new(ntr: &'a Ntr) -> Self {
        NtrStream {
            tcp_stream: ntr.tcp_stream.try_clone().unwrap(),
            current_seq: &ntr.current_seq,
            is_heartbeat_sendable: &ntr.is_heartbeat_sendable,
        }
    }

    fn send_packet(&mut self, packet_type: u32, cmd: u32, args: &[u32], data_len: u32) -> io::Result<usize> {
        let mut buf = [0u8; 84];

        LittleEndian::write_u32(&mut buf[0..4], 0x12345678);
        LittleEndian::write_u32(&mut buf[4..8], self.current_seq.fetch_add(1000, Ordering::SeqCst) as u32);
        LittleEndian::write_u32(&mut buf[8..12], packet_type);
        LittleEndian::write_u32(&mut buf[12..16], cmd);
        for i in 0..16 {
            LittleEndian::write_u32(&mut buf[(4 * i + 16)..(4 * i + 20)], args[i]);
        }
        LittleEndian::write_u32(&mut buf[80..84], data_len);

        self.tcp_stream.write(&buf)
    }

    fn send_mem_read_packet(&mut self, addr: u32, size: u32, pid: u32) -> io::Result<usize> {
        self.send_empty_packet(9, pid, addr, size)
    }

    fn send_mem_write_packet(&mut self, addr: u32, pid: u32, buf: &Vec<u8>) -> io::Result<usize> {
        let args = &mut [0u32; 16];
        args[0] = pid;
        args[1] = addr;
        args[2] = buf.len() as u32;
        try!(self.send_packet(1, 10, args, args[2]));
        self.tcp_stream.write(buf)
    }

    fn send_heartbeat_packet(&mut self) -> io::Result<usize> {
        self.send_packet(0, 0, &[0u32; 16], 0)
    }

    fn send_hello_packet(&mut self) -> io::Result<usize> {
        self.send_packet(0, 3, &[0u32; 16], 0)
    }

    fn send_reload_packet(&mut self) -> io::Result<usize> {
        self.send_packet(0, 4, &[0u32; 16], 0)
    }

    fn send_empty_packet(&mut self, cmd: u32, arg0: u32, arg1: u32, arg2: u32) -> io::Result<usize> {
        let mut args = [0u32; 16];
        args[0] = arg0;
        args[1] = arg1;
        args[2] = arg2;
        self.send_packet(0, cmd, &args, 0)
    }

    fn tcp_stream(&mut self) -> &TcpStream {
        &self.tcp_stream
    }

    fn is_heartbeat_sendable(&self) -> &AtomicBool {
        &self.is_heartbeat_sendable
    }
}<|endoftext|>


<commit_before>extern crate json_schema;
extern crate serde_json;

#[macro_use]
extern crate quote;

use std::borrow::Cow;
use std::error::Error;

use json_schema::{Schema, Type};

use quote::{Tokens, ToTokens};

struct Ident<S>(S);

impl<S: AsRef<str>> ToTokens for Ident<S> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.0.as_ref())
    }
}

fn field(s: &str) -> Ident<Cow<str>> {
    Ident(if ["type", "struct", "enum"].iter().any(|&keyword| keyword == s) {
        format!("{}_", s).into()
    } else {
        s.into()
    })
}

fn merge(result: &mut Schema, r: &Schema) {
    use std::collections::hash_map::Entry;

    for (k, v) in &r.properties {
        match result.properties.entry(k.clone()) {
            Entry::Vacant(entry) => {
                entry.insert(v.clone());
            }
            Entry::Occupied(mut entry) => merge(entry.get_mut(), v),
        }
    }
}

struct Expander<'r> {
    root: &'r Schema,
}

impl<'r> Expander<'r> {
    fn type_ref(&self, s: &str) -> String {
        s.split('/').last().expect("Component").into()
    }

    fn schema(&self, s: &'r Schema) -> &'r Schema {
        if let Some(ref ref_) = s.ref_ {
            self.schema_ref(ref_)
        } else {
            s
        }
    }

    fn schema_ref(&self, s: &str) -> &'r Schema {
        s.split('/').fold(self.root, |schema, comp| {
            if comp == "#" {
                self.root
            } else if comp == "definitions" {
                schema
            } else {
                schema.definitions
                    .get(comp)
                    .unwrap_or_else(|| panic!("Expected definition: `{}` {}", s, comp))
            }
        })
    }

    fn expand_type(&mut self, typ: &Schema) -> String {
        if let Some(ref ref_) = typ.ref_ {
            self.type_ref(ref_)
        } else if typ.type_.len() == 1 {
            match typ.type_[0] {
                Type::String => {
                    if !typ.enum_.is_empty() {
                        "serde_json::Value".into()
                    } else {
                        "String".into()
                    }
                }
                Type::Integer => "i64".into(),
                Type::Boolean => "bool".into(),
                Type::Number => "f64".into(),
                Type::Object => "serde_json::Value".into(),
                Type::Array => {
                    let item_schema =
                        typ.items.as_ref().expect("Array type must have items schema");
                    format!("Vec<{}>", self.expand_type(item_schema))
                }
                _ => panic!("Type"),
            }
        } else {
            "serde_json::Value".into()
        }
    }

    fn expand_fields(&mut self, schema: &Schema) -> Vec<Tokens> {
        if let Some(ref ref_) = schema.ref_ {
            let schema = self.schema_ref(ref_);
            self.expand_fields(schema)
        } else if !schema.allOf.is_empty() {
            let first = schema.allOf.first().unwrap().clone();
            let result = schema.allOf
                .iter()
                .skip(1)
                .fold(first, |mut result, def| {
                    merge(&mut result, self.schema(def));
                    result
                });
            self.expand_fields(&result)
        } else {
            schema.properties
                .iter()
                .map(|(key, value)| {
                    let key = field(key);
                    let typ = Ident(self.expand_type(value));
                    quote!( #key : #typ )
                })
                .collect()
        }
    }

    pub fn expand_schema(&mut self, schema: &Schema) -> Tokens {
        let mut types = Vec::new();
        for (name, def) in &schema.definitions {
            let fields = self.expand_fields(def);
            let name = Ident(name);
            let tokens = quote! {
                pub struct #name {
                    #(#fields),*
                }
            };
            types.push(tokens);
        }
        quote! { #(
            #types
            )*
        }
    }
}

pub fn generate(s: &str) -> Result<String, Box<Error>> {
    use std::process::{Command, Stdio};
    use std::io::Write;

    let schema = serde_json::from_str(s).unwrap();
    let mut expander = Expander { root: &schema };
    let output = expander.expand_schema(&schema).to_string();
    let mut child =
        try!(Command::new("rustfmt").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn());
    try!(child.stdin.as_mut().expect("stdin").write_all(output.as_bytes()));
    let output = try!(child.wait_with_output());
    Ok(try!(String::from_utf8(output.stdout)))
}

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

    #[test]
    fn attempt() {
        let s = include_str!("../../json-schema/tests/debugserver-schema.json");

        let s = generate(s).unwrap().to_string();
        println!("{}", s);
        assert!(false);
    }
}
<commit_msg>fix: Make the generated fields public<commit_after>extern crate json_schema;
extern crate serde_json;

#[macro_use]
extern crate quote;

use std::borrow::Cow;
use std::error::Error;

use json_schema::{Schema, Type};

use quote::{Tokens, ToTokens};

struct Ident<S>(S);

impl<S: AsRef<str>> ToTokens for Ident<S> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.0.as_ref())
    }
}

fn field(s: &str) -> Ident<Cow<str>> {
    Ident(if ["type", "struct", "enum"].iter().any(|&keyword| keyword == s) {
        format!("{}_", s).into()
    } else {
        s.into()
    })
}

fn merge(result: &mut Schema, r: &Schema) {
    use std::collections::hash_map::Entry;

    for (k, v) in &r.properties {
        match result.properties.entry(k.clone()) {
            Entry::Vacant(entry) => {
                entry.insert(v.clone());
            }
            Entry::Occupied(mut entry) => merge(entry.get_mut(), v),
        }
    }
}

struct Expander<'r> {
    root: &'r Schema,
}

impl<'r> Expander<'r> {
    fn type_ref(&self, s: &str) -> String {
        s.split('/').last().expect("Component").into()
    }

    fn schema(&self, s: &'r Schema) -> &'r Schema {
        if let Some(ref ref_) = s.ref_ {
            self.schema_ref(ref_)
        } else {
            s
        }
    }

    fn schema_ref(&self, s: &str) -> &'r Schema {
        s.split('/').fold(self.root, |schema, comp| {
            if comp == "#" {
                self.root
            } else if comp == "definitions" {
                schema
            } else {
                schema.definitions
                    .get(comp)
                    .unwrap_or_else(|| panic!("Expected definition: `{}` {}", s, comp))
            }
        })
    }

    fn expand_type(&mut self, typ: &Schema) -> String {
        if let Some(ref ref_) = typ.ref_ {
            self.type_ref(ref_)
        } else if typ.type_.len() == 1 {
            match typ.type_[0] {
                Type::String => {
                    if !typ.enum_.is_empty() {
                        "serde_json::Value".into()
                    } else {
                        "String".into()
                    }
                }
                Type::Integer => "i64".into(),
                Type::Boolean => "bool".into(),
                Type::Number => "f64".into(),
                Type::Object => "serde_json::Value".into(),
                Type::Array => {
                    let item_schema =
                        typ.items.as_ref().expect("Array type must have items schema");
                    format!("Vec<{}>", self.expand_type(item_schema))
                }
                _ => panic!("Type"),
            }
        } else {
            "serde_json::Value".into()
        }
    }

    fn expand_fields(&mut self, schema: &Schema) -> Vec<Tokens> {
        if let Some(ref ref_) = schema.ref_ {
            let schema = self.schema_ref(ref_);
            self.expand_fields(schema)
        } else if !schema.allOf.is_empty() {
            let first = schema.allOf.first().unwrap().clone();
            let result = schema.allOf
                .iter()
                .skip(1)
                .fold(first, |mut result, def| {
                    merge(&mut result, self.schema(def));
                    result
                });
            self.expand_fields(&result)
        } else {
            schema.properties
                .iter()
                .map(|(key, value)| {
                    let key = field(key);
                    let typ = Ident(self.expand_type(value));
                    quote!( pub #key : #typ )
                })
                .collect()
        }
    }

    pub fn expand_schema(&mut self, schema: &Schema) -> Tokens {
        let mut types = Vec::new();
        for (name, def) in &schema.definitions {
            let fields = self.expand_fields(def);
            let name = Ident(name);
            let tokens = quote! {
                pub struct #name {
                    #(#fields),*
                }
            };
            types.push(tokens);
        }
        quote! { #(
            #types
            )*
        }
    }
}

pub fn generate(s: &str) -> Result<String, Box<Error>> {
    use std::process::{Command, Stdio};
    use std::io::Write;

    let schema = serde_json::from_str(s).unwrap();
    let mut expander = Expander { root: &schema };
    let output = expander.expand_schema(&schema).to_string();
    let mut child =
        try!(Command::new("rustfmt").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn());
    try!(child.stdin.as_mut().expect("stdin").write_all(output.as_bytes()));
    let output = try!(child.wait_with_output());
    Ok(try!(String::from_utf8(output.stdout)))
}

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

    #[test]
    fn attempt() {
        let s = include_str!("../../json-schema/tests/debugserver-schema.json");

        let s = generate(s).unwrap().to_string();
        println!("{}", s);
        assert!(false);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod batch_iterator;
pub mod color;
pub mod data_provider;
pub mod errors;
pub mod math;
pub mod octree;
pub mod read_write;

use cgmath::Vector3;
use std::collections::BTreeMap;

#[derive(Debug, Clone)]
pub struct Point {
    pub position: cgmath::Vector3<f64>,
    // TODO(sirver): Make color optional, we might not always have it.
    pub color: color::Color<u8>,

    // The intensity of the point if it exists. This value is usually handed through directly by a
    // sensor and has therefore no defined range - or even meaning.
    pub intensity: Option<f32>,
}

pub fn attribute_extension(attribute: &str) -> &str {
    match attribute {
        "position" => "xyz",
        "color" => "rgb",
        _ => attribute,
    }
}

/// General field to describe point feature attributes such as color, intensity, ...
#[derive(Debug, Clone)]
pub enum AttributeData {
    U8(Vec<u8>),
    I64(Vec<i64>),
    U64(Vec<u64>),
    F32(Vec<f32>),
    F64(Vec<f64>),
    U8Vec3(Vec<Vector3<u8>>),
    F64Vec3(Vec<Vector3<f64>>),
}

#[derive(Debug, Clone)]
pub enum AttributeDataType {
    U8,
    I64,
    U64,
    F32,
    F64,
    U8Vec3,
    F64Vec3,
}

impl AttributeData {
    pub fn len(&self) -> usize {
        match self {
            AttributeData::U8(data) => data.len(),
            AttributeData::I64(data) => data.len(),
            AttributeData::U64(data) => data.len(),
            AttributeData::F32(data) => data.len(),
            AttributeData::F64(data) => data.len(),
            AttributeData::U8Vec3(data) => data.len(),
            AttributeData::F64Vec3(data) => data.len(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn dim(&self) -> usize {
        match self {
            AttributeData::U8(_)
            | AttributeData::I64(_)
            | AttributeData::U64(_)
            | AttributeData::F32(_)
            | AttributeData::F64(_) => 1,
            AttributeData::U8Vec3(_) | AttributeData::F64Vec3(_) => 3,
        }
    }
}

/// General structure that contains points and attached feature attributes.
pub struct PointsBatch {
    pub position: Vec<Vector3<f64>>,
    // BTreeMap for deterministic iteration order.
    pub attributes: BTreeMap<String, AttributeData>,
}

pub use point_viewer_proto_rust::proto;

/// size for batch
pub const NUM_POINTS_PER_BATCH: usize = 500_000;
<commit_msg>Clonable points batch. (#327)<commit_after>// Copyright 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod batch_iterator;
pub mod color;
pub mod data_provider;
pub mod errors;
pub mod math;
pub mod octree;
pub mod read_write;

use cgmath::Vector3;
use std::collections::BTreeMap;

#[derive(Debug, Clone)]
pub struct Point {
    pub position: cgmath::Vector3<f64>,
    // TODO(sirver): Make color optional, we might not always have it.
    pub color: color::Color<u8>,

    // The intensity of the point if it exists. This value is usually handed through directly by a
    // sensor and has therefore no defined range - or even meaning.
    pub intensity: Option<f32>,
}

pub fn attribute_extension(attribute: &str) -> &str {
    match attribute {
        "position" => "xyz",
        "color" => "rgb",
        _ => attribute,
    }
}

/// General field to describe point feature attributes such as color, intensity, ...
#[derive(Debug, Clone)]
pub enum AttributeData {
    U8(Vec<u8>),
    I64(Vec<i64>),
    U64(Vec<u64>),
    F32(Vec<f32>),
    F64(Vec<f64>),
    U8Vec3(Vec<Vector3<u8>>),
    F64Vec3(Vec<Vector3<f64>>),
}

#[derive(Debug, Clone)]
pub enum AttributeDataType {
    U8,
    I64,
    U64,
    F32,
    F64,
    U8Vec3,
    F64Vec3,
}

impl AttributeData {
    pub fn len(&self) -> usize {
        match self {
            AttributeData::U8(data) => data.len(),
            AttributeData::I64(data) => data.len(),
            AttributeData::U64(data) => data.len(),
            AttributeData::F32(data) => data.len(),
            AttributeData::F64(data) => data.len(),
            AttributeData::U8Vec3(data) => data.len(),
            AttributeData::F64Vec3(data) => data.len(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn dim(&self) -> usize {
        match self {
            AttributeData::U8(_)
            | AttributeData::I64(_)
            | AttributeData::U64(_)
            | AttributeData::F32(_)
            | AttributeData::F64(_) => 1,
            AttributeData::U8Vec3(_) | AttributeData::F64Vec3(_) => 3,
        }
    }
}

/// General structure that contains points and attached feature attributes.
#[derive(Debug, Clone)]
pub struct PointsBatch {
    pub position: Vec<Vector3<f64>>,
    // BTreeMap for deterministic iteration order.
    pub attributes: BTreeMap<String, AttributeData>,
}

pub use point_viewer_proto_rust::proto;

/// size for batch
pub const NUM_POINTS_PER_BATCH: usize = 500_000;
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#![feature(alloc, core)]

extern crate alloc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
extern crate draw_state;
extern crate num;

/// public re-exported traits
pub mod traits {
    pub use device::{Device, Factory};
    pub use extra::canvas::IntoCanvas;
    pub use extra::device::DeviceExt;
    pub use extra::factory::FactoryExt;
    pub use extra::stream::{Stream, StreamFactory};
    pub use render::RenderFactory;
    pub use render::mesh::ToSlice;
    pub use render::target::Output;
}

// draw state re-exports
pub use draw_state::{DrawState, BlendPreset};
pub use draw_state::state;
pub use draw_state::target::*;

// public re-exports
pub use device::{Device, SubmitInfo, Factory, Resources};
pub use device::{attrib, tex};
pub use device::as_byte_slice;
pub use device::{BufferRole, BufferInfo, BufferUsage};
pub use device::{VertexCount, InstanceCount};
pub use device::PrimitiveType;
pub use device::draw::{CommandBuffer, Gamma};
pub use device::shade::{ProgramInfo, UniformValue};
pub use render::{Renderer, DrawError};
pub use render::batch;
pub use render::mesh::{Attribute, Mesh, VertexFormat};
pub use render::mesh::Error as MeshError;
pub use render::mesh::{Slice, ToSlice, SliceKind};
pub use render::shade;
pub use render::target::{Frame, Output, Plane};
pub use render::ParamStorage;
pub use extra::canvas::{Canvas, Window};
pub use extra::device::Graphics;
pub use extra::shade::{ShaderSource, ProgramError};
pub use extra::stream::{OwnedStream, Stream};

pub use device::handle::Buffer as BufferHandle;
pub use device::handle::IndexBuffer as IndexBufferHandle;
pub use device::handle::RawBuffer as RawBufferHandle;
pub use device::handle::Shader as ShaderHandle;
pub use device::handle::Program as ProgramHandle;
pub use device::handle::FrameBuffer as FrameBufferHandle;
pub use device::handle::Surface as SurfaceHandle;
pub use device::handle::Texture as TextureHandle;
pub use device::handle::Sampler as SamplerHandle;

pub mod device;
pub mod extra;
pub mod render;
<commit_msg>Remove handle typedefs<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#![feature(alloc, core)]

extern crate alloc;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate log;
extern crate draw_state;
extern crate num;

/// public re-exported traits
pub mod traits {
    pub use device::{Device, Factory};
    pub use extra::canvas::IntoCanvas;
    pub use extra::device::DeviceExt;
    pub use extra::factory::FactoryExt;
    pub use extra::stream::{Stream, StreamFactory};
    pub use render::RenderFactory;
    pub use render::mesh::ToSlice;
    pub use render::target::Output;
}

// draw state re-exports
pub use draw_state::{DrawState, BlendPreset};
pub use draw_state::state;
pub use draw_state::target::*;

// public re-exports
pub use device::{Device, SubmitInfo, Factory, Resources};
pub use device::{attrib, tex, handle};
pub use device::as_byte_slice;
pub use device::{BufferRole, BufferInfo, BufferUsage};
pub use device::{VertexCount, InstanceCount};
pub use device::PrimitiveType;
pub use device::draw::{CommandBuffer, Gamma};
pub use device::shade::{ProgramInfo, UniformValue};
pub use render::{Renderer, DrawError};
pub use render::batch;
pub use render::mesh::{Attribute, Mesh, VertexFormat};
pub use render::mesh::Error as MeshError;
pub use render::mesh::{Slice, ToSlice, SliceKind};
pub use render::shade;
pub use render::target::{Frame, Output, Plane};
pub use render::ParamStorage;
pub use extra::canvas::{Canvas, Window};
pub use extra::device::Graphics;
pub use extra::shade::{ShaderSource, ProgramError};
pub use extra::stream::{OwnedStream, Stream};

pub mod device;
pub mod extra;
pub mod render;
<|endoftext|>


<commit_before>/// An implementation of mux in Rust.
/// See: https://github.com/twitter/finagle/blob/master/finagle-mux/src/main/scala/com/twitter/finagle/mux/package.scala
pub mod mux {
    // TODO these should be moved into other crates...
    pub mod misc {
        use std::fmt;
        use std::str;

        /// A simple wrapper type for an array of bytes.
        #[deriving(PartialEq,Eq)]
        pub struct Buf<'t>(&'t [u8]);
        static EMPTY_BUF: Buf<'static> = Buf(&[]);
        impl<'t> Buf<'t> {
            #[inline]
            pub fn empty() -> Buf<'t> { EMPTY_BUF }

            pub fn as_bytes(&'t self) -> &'t [u8] {
                let Buf(bytes) = *self;
                bytes
            }

            pub fn as_str(&'t self) -> Option<&'t str> {
                let Buf(bytes) = *self;
                str::from_utf8(bytes)
            }

            pub fn from_str<'u>(s: &'u str) -> Option<Buf<'u>> { Some(Buf(s.as_bytes())) }
        }

        impl<'t> fmt::Show for Buf<'t> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                let Buf(bytes) = *self;
                write!(f, "{}", str::from_utf8(bytes))
            }
        }

        #[deriving(PartialEq,Eq,Show)]
        pub struct Path<'t>(pub &'t [Buf<'t>]);
        static EMPTY_PATH: Path<'static> = Path(&[]);
        impl<'t> Path<'t> {
            #[inline]
            pub fn empty() -> Path<'t> { EMPTY_PATH }

            // TODO
            pub fn from_str<'u>(_: &'u [str]) -> Path<'u> { EMPTY_PATH }
        }

        #[deriving(PartialEq,Eq,Show)]
        pub struct Dentry<'t>(pub &'t str, pub &'t str);
        impl<'t> Dentry<'t> {
            pub fn source(&self) -> &'t str {
                let Dentry(source, _) = *self;
                source
            }

            pub fn target(&self) -> &'t str {
                let Dentry(_, target) = *self;
                target
            }
        }

        #[deriving(PartialEq,Eq,Show)]
        pub struct Dtab<'t>(pub &'t [Dentry<'t>]);
        static EMPTY_DTAB: Dtab<'static> = Dtab(&[]);
        impl<'t> Dtab<'t> {
            #[inline]
            pub fn empty() -> Dtab<'t> { EMPTY_DTAB }

            pub fn dentries(&self) -> &'t [Dentry<'t>] {
                let Dtab(dentries) = *self;
                dentries
            }
        }

        #[deriving(PartialEq,Eq,Show)]
        pub struct Context<'t>(pub Buf<'t>, pub Buf<'t>);
        impl<'t> Context<'t> {
            pub fn key(&self) -> Buf<'t> {
                let Context(k, _) = *self;
                k
            }

            pub fn val(&self) -> Buf<'t> {
                let Context(_, v) = *self;
                v
            }
        }

        #[deriving(PartialEq,Eq,Show)]
        pub struct Contexts<'t>(pub &'t [Context<'t>]);
        static EMPTY_CONTEXTS: Contexts<'static> = Contexts(&[]);
        impl<'t> Contexts<'t> {
            #[inline]
            pub fn empty() -> Contexts<'t> { EMPTY_CONTEXTS }
        }
    }

    /*
     * TODO

    pub struct Request {
        destination: Path,
        body: Buf,
    }

    pub struct Response {
        body: Buf,
    }
     */

    /// Mux protocol support for de/serializing mux messages.
    pub mod proto {
        use std::io::{IoResult, IoError, Reader, BufReader};
        use super::misc::{Buf, Context, Contexts, Path, Dtab};

        #[deriving(PartialEq,Eq,Show)]
        pub struct Tag(u64);

        #[deriving(PartialEq,Eq,Show)]
        pub enum Message<'t> {
            // Treq(Tag, Option<TraceId>, Buf),
            // RreqOk(Tag, Buf),
            // RreqError(Tag, str),
            //RreqNack(Tag),

            Tdispatch(Tag, Contexts<'t>, Path<'t>, Dtab<'t>, Buf<'t>),
            RdispatchOk(Tag, Contexts<'t>, Buf<'t>),
            RdispatchError(Tag, Contexts<'t>, &'t str),
            RdispatchNack(Tag, Contexts<'t>),

            Tdrain(Tag),
            Rdrain(Tag),

            Tping(Tag),
            Rping(Tag),
            Tdiscarded(Tag, &'t str),
            Tlease(u8, u64),

            Rerr(Tag, &'t str),
        }

        trait MessageReader<'t> {
            fn read_type(&mut self) -> IoResult<i8>;
            fn read_tag(&mut self) -> IoResult<Tag>;
            fn read_contexts(&mut self) -> IoResult<Contexts<'t>>;

            //fn read_message(&mut self) -> IoResult<Message<'t>, IoError>
        }

        impl<'t, R: Reader> MessageReader<'t> for R {
            fn read_type(&mut self) -> IoResult<i8> { self.read_i8() }

            fn read_tag(&mut self) -> IoResult<Tag> {
                self.read_be_uint_n(3).map(|n| -> Tag { Tag(n) })
            }

            fn read_contexts(&mut self) -> IoResult<Contexts<'t>> {
                match self.read_be_u16() {
                    Err(io) => Err(io),

                    Ok(n) if n == 0 =>
                        Ok(Contexts::empty()),

                    Ok(_n) => {
                        let n = _n as uint;
                        let mut contexts: Vec<Context> = Vec::with_capacity(n);
                        for i in range(0, n) {
                            contexts.insert(i, Context(Buf::empty(), Buf::empty()));
                        }
                        Ok(Contexts(contexts.as_slice().clone()))
                    }
                }
            }
        }

        pub enum DecodeErr {
            IoErr(IoError),
            UnknownType(i8),
        }

        impl<'t> Message<'t> {

            /// Decode a slice of bytes as a mux message.
            pub fn decode<'u>(bytes: &'u [u8]) -> Result<Message<'u>, DecodeErr> {
                let mut reader = BufReader::new(bytes);

                match reader.read_type() {
                    // Ok( 1) => Some(decodeTreq(tag, rest)),
                    // Ok(-1) => Some(decodeRreq(tag, rest)),

                    // Ok( 2) => decodeTdispatch(tag, rest),
                    // Ok(-2) => decodeRdispatch(tag, rest),

                    Ok(kind) => Err(UnknownType(kind)),
                    Err(ioe) => Err(IoErr(ioe)),
                }
            }

            // fn decode_tdispatch<'u>(tag: Tag, bytes: &'u [u8]) -> Decoded<'u, Message<'u>> {
            //     decodeContexts
            // }

            /// Encode a mux message as bytes.
            pub fn encode(&self) -> Vec<u8> {
                match *self {
                    Tdispatch(tag, Contexts(contexts), Path(path), dtab, buf) => {
                        let tagsz = 3;
                        let ctxsz = Message::context_sz(contexts);
                        Vec::with_capacity(tagsz + ctxsz)
                    },

                    _ => Vec::new(),
                }
            }

            fn context_sz<'u>(contexts: &'u [Context]) -> uint {
                (*contexts).iter().fold(0u, |sum, &Context(kbuf, vbuf)| -> uint {
                    sum + kbuf.as_bytes().len() + vbuf.as_bytes().len()
                })
            }
        }

        #[cfg(test)]
        mod test {
            use mux::misc::{Contexts, Path, Dtab, Buf};
            use super::{Tag, Tdispatch, Message, IoErr, UnknownType};

            fn mk_tdispatch<'t>() -> Message<'t> {
                let tag = Tag(1u as u64);
                let contexts = Contexts::empty();
                let path = Path::empty();
                let dtab = Dtab::empty();
                let body = Buf::empty();
                Tdispatch(tag, contexts, path, dtab, body)
            }

            #[test]
            fn tdispatch() {
                let orig = mk_tdispatch();
                let bytes = orig.encode();

                match Message::decode(bytes.as_slice()) {
                    Ok(decoded@Tdispatch(_,_,_,_,_)) =>
                        assert_eq!(orig, decoded),

                    Ok(other) =>
                        fail!("decoded unexpected message type: {}", other),

                    Err(IoErr(ioe)) =>
                        fail!("I/O error: {}", ioe),

                    Err(UnknownType(typ)) =>
                        fail!("unknown message type: {}", typ),
                }
            }
        }
    }
}

<commit_msg>more hacking on decoding (with an immutable Reader<commit_after>/// An implementation of mux in Rust.
/// See: https://github.com/twitter/finagle/blob/master/finagle-mux/src/main/scala/com/twitter/finagle/mux/package.scala
pub mod mux {
    // TODO these should be moved into other crates...
    pub mod misc {
        use std::fmt;
        use std::str;

        /// A simple wrapper type for an array of bytes.
        #[deriving(Clone,PartialEq,Eq)]
        pub struct Buf<'t>(&'t [u8]);
        static EMPTY_BUF: Buf<'static> = Buf(&[]);
        impl<'t> Buf<'t> {
            pub fn new(bytes: &'t [u8]) -> Buf<'t> { Buf(bytes) }

            #[inline]
            pub fn empty() -> Buf<'t> { EMPTY_BUF }

            pub fn as_bytes(&'t self) -> &'t [u8] {
                let Buf(bytes) = *self;
                bytes
            }

            pub fn as_str(&'t self) -> Option<&'t str> {
                let Buf(bytes) = *self;
                str::from_utf8(bytes)
            }

            pub fn from_str<'u>(s: &'u str) -> Option<Buf<'u>> { Some(Buf(s.as_bytes())) }
        }

        impl<'t> fmt::Show for Buf<'t> {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                let Buf(bytes) = *self;
                write!(f, "{}", str::from_utf8(bytes))
            }
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub struct Path<'t>(pub &'t [Buf<'t>]);
        static EMPTY_PATH: Path<'static> = Path(&[]);
        impl<'t> Path<'t> {
            #[inline]
            pub fn empty() -> Path<'t> { EMPTY_PATH }

            // TODO
            pub fn from_str(_: &'t [str]) -> Path<'t> { EMPTY_PATH }

            // TODO
            pub fn from_bytes<'u>(_: &'u [u8]) -> Path<'u> { EMPTY_PATH }
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub struct Dentry<'t>(pub &'t str, pub &'t str);
        impl<'t> Dentry<'t> {
            pub fn source(&self) -> &'t str {
                let Dentry(source, _) = *self;
                source
            }

            pub fn target(&self) -> &'t str {
                let Dentry(_, target) = *self;
                target
            }
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub struct Dtab<'t>(pub &'t [Dentry<'t>]);
        static EMPTY_DTAB: Dtab<'static> = Dtab(&[]);
        impl<'t> Dtab<'t> {
            #[inline]
            pub fn empty() -> Dtab<'t> { EMPTY_DTAB }

            pub fn dentries(&self) -> &'t [Dentry<'t>] {
                let Dtab(dentries) = *self;
                dentries
            }
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub struct Context<'t>(pub Buf<'t>, pub Buf<'t>);
        impl<'t> Context<'t> {
            pub fn key(&self) -> Buf<'t> {
                let Context(k, _) = *self;
                k
            }

            pub fn val(&self) -> Buf<'t> {
                let Context(_, v) = *self;
                v
            }
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub struct Contexts<'t>(pub &'t [Context<'t>]);
        static EMPTY_CONTEXTS: Contexts<'static> = Contexts(&[]);
        impl<'t> Contexts<'t> {
            #[inline]
            pub fn empty() -> Contexts<'t> { EMPTY_CONTEXTS }
        }

        pub trait Reader<'a> {
            fn len(self) -> uint;
            fn read_u8(self) -> Result<Read<'a, Self, u8>, ReadErr<'a, Self>>;
            fn read_i8(self) -> Result<Read<'a, Self, i8>, ReadErr<'a, Self>>;
            fn read_u16_be(self) -> Result<Read<'a, Self, u16>, ReadErr<'a, Self>>;
            fn read_uint_be(self, nbytes: uint) -> Result<Read<'a, Self, u64>, ReadErr<'a, Self>>;
            fn read_slice(self, nbytes: uint) -> Result<Read<'a, Self, &'a [u8]>, ReadErr<'a, Self>>;
        }
        pub enum ReadErr<'a, R: Reader<'a>> {
            ReadUnderflow(R)
        }

        pub struct Read<'a, R: Reader<'a>, T>(pub R, pub T);

        pub trait FlatMap<'a, R: Reader<'a>, T> {
            fn flat_map<U>(self, f: |Read<'a, R, T>| -> Result<Read<'a, R, U>, ReadErr<'a, R>>) -> Result<Read<'a, R, U>, ReadErr<'a, R>>;
        }

        impl<'a, R: Reader<'a>, T> FlatMap<'a, R, T> for Result<Read<'a, R, T>, ReadErr<'a, R>> {
            fn flat_map<U>(self, f: |Read<'a, R, T>| -> Result<Read<'a, R, U>, ReadErr<'a, R>>) -> Result<Read<'a, R, U>, ReadErr<'a, R>> {
                match self {
                    Err(e) => Err(e),
                    Ok(read) => f(read),
                }
            }
        }

        impl<'a> Reader<'a> for Buf<'a> {

            fn len(self) -> uint {
                self.as_bytes().len()
            }

            fn read_u8(self) -> Result<Read<'a, Buf<'a>, u8>, ReadErr<'a, Buf<'a>>> {
                match self {
                    Buf(bytes) if bytes.len() == 0 =>
                        Err(ReadUnderflow(self)),
                    Buf(bytes) =>
                        Ok(Read(Buf(bytes.slice_from(1)), bytes[0])),
                }
            }

            fn read_i8(self) -> Result<Read<'a, Buf<'a>, i8>, ReadErr<'a, Buf<'a>>> {
                self.read_u8().map(|Read(reader, u)| -> Read<'a, Buf<'a>, i8> { Read(reader, u as i8) })
            }

            fn read_slice(self, nbytes: uint) -> Result<Read<'a, Buf<'a>, &'a [u8]>, ReadErr<'a, Buf<'a>>> {
                match self {
                    Buf(bytes) if bytes.len() < nbytes =>
                        Err(ReadUnderflow(self)),
                    Buf(bytes) =>
                        Ok(Read(Buf(bytes.slice_from(nbytes)), bytes.slice_to(nbytes)))
                }
            }

            /// Lifted from std::io::Reader
            fn read_uint_be(self, nbytes: uint) -> Result<Read<'a, Buf<'a>, u64>, ReadErr<'a, Buf<'a>>> {
                if self.len() < nbytes {
                    return Err(ReadUnderflow(self));
                }
                let mut val = 0u64;
                let mut i = nbytes;
                let mut reader: Buf<'a> = self;
                while i > 0 {
                    i -= 1;
                    match reader.read_u8() {
                        Err(e) => return Err(e),
                        Ok(Read(next_reader, n)) => {
                            val += n as u64 << i * 8;
                            reader = next_reader;
                        },
                    }
                }
                Ok(Read(reader, val))
            }

            fn read_u16_be(self) -> Result<Read<'a, Buf<'a>, u16>, ReadErr<'a, Buf<'a>>> {
                self.read_uint_be(2).map(|Read(r, n)| -> Read<'a, Buf<'a>, u16> { Read(r, n as u16) })
            }
        }
    }

    /*
     * TODO

    pub struct Request {
        destination: Path,
        body: Buf,
    }

    pub struct Response {
        body: Buf,
    }
     */

    /// Mux protocol support for de/serializing mux messages.
    pub mod proto {
        use super::misc::{Buf, Context, Contexts, Path, Dtab, Reader, Read, ReadErr, ReadUnderflow, FlatMap};

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub struct Tag(u64);

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub enum Type {
            TreqType,
            RreqType,
            TdispatchType,
            RdispatchType,
            TdrainType,
            RdrainType,
            TpingType,
            RpingType,
            TdiscardedType,
            TleaseType,
            RerrType,
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub enum Message<'t> {
            // Treq(Tag, Option<TraceId>, Buf),
            // RreqOk(Tag, Buf),
            // RreqError(Tag, str),
            //RreqNack(Tag),

            Tdispatch(Tag, Contexts<'t>, Path<'t>, Dtab<'t>, Buf<'t>),
            RdispatchOk(Tag, Contexts<'t>, Buf<'t>),
            RdispatchError(Tag, Contexts<'t>, &'t str),
            RdispatchNack(Tag, Contexts<'t>),

            Tdrain(Tag),
            Rdrain(Tag),

            Tping(Tag),
            Rping(Tag),
            Tdiscarded(Tag, &'t str),
            Tlease(u8, u64),

            Rerr(Tag, &'t str),
        }

        #[deriving(Clone,PartialEq,Eq,Show)]
        pub enum DecodeErr<E> {
            DecodeUnderflow,
            UnknownType(i8),
            OtherErr(E),
        }

        pub type Decoded<T, E> = Result<T, DecodeErr<E>>;

        impl<'t> Message<'t> {

            fn decode_type<R: Reader<'t>, T, E>(reader: R, f: |R, Type| -> Decoded<T, E>) -> Decoded<T, E> {
                match reader.read_i8() {
                    Err(ReadUnderflow(_)) => Err(DecodeUnderflow),
                    Ok(Read(reader, val)) => match val {
                         1 => f(reader, TreqType),
                        -1 => f(reader, RreqType),

                         2 => f(reader, TdispatchType),
                        -2 => f(reader, RdispatchType),

                         64 => f(reader, TdrainType),
                        -64 => f(reader, RdrainType),

                         65 => f(reader, TpingType),
                        -65 => f(reader, RpingType),

                        66 => f(reader, TdiscardedType),
                        67 => f(reader, TleaseType),

                        -128 => f(reader, RerrType),

                        t => Err(UnknownType(t))
                    }
                }
            }

            fn decode_tag<R: Reader<'t>, T, E>(reader: R, f: |R, Tag| -> Decoded<T, E>) -> Decoded<T, E> {
                match reader.read_uint_be(3) {
                    Err(ReadUnderflow(_)) => Err(DecodeUnderflow),
                    Ok(Read(r, n)) => f(r, Tag(n)),
                }
            }

            fn decode_buf<R: Reader<'t>, T, E>(reader: R, f: |R, Buf<'t>| -> Decoded<T, E>) -> Decoded<T, E> {
                let read_slice = reader.read_u16_be().flat_map(
                    |Read(reader, nbytes)| -> Result<Read<'t, R, &'t [u8]>, ReadErr<'t, R>> {
                        reader.read_slice(nbytes as uint)
                    });
                match read_slice {
                    Err(ReadUnderflow(_)) => Err(DecodeUnderflow),
                    Ok(Read(reader, slice)) => f(reader, Buf::new(slice)),
                }
            }

            fn decode_context<R: Reader<'t>, T, E>(reader: R, f: |R, Context<'t>| -> Decoded<T, E>) -> Decoded<T, E> {
                Message::decode_buf(reader, |reader, key| -> Decoded<T, E> {
                    Message::decode_buf(reader, |reader, val| -> Decoded<T, E> {
                        f(reader, Context(key, val))
                    })
                })
            }

            fn decode_contexts<R: Reader<'t>, T, E>(reader: R, f: |R, Contexts<'t>| -> Decoded<T, E>) -> Decoded<T, E> {
                match reader.read_u16_be() {
                    Err(ReadUnderflow(_)) => Err(DecodeUnderflow),

                    Ok(Read(reader, _n)) =>
                        if _n == 0 {
                            f(reader, Contexts::empty())
                        } else {
                            let n = _n as uint;
                            let mut vec: Vec<Context> = Vec::with_capacity(n);
                            for i in range(0, n) {
                                vec.insert(i, Context(Buf::empty(), Buf::empty()));
                            }
                            //let slice = vec.as_slice();
                            // FIXME lifetime
                            f(reader, Contexts::empty())
                        }
                }
            }

            fn decode_destination<R: Reader<'t>, T, E>(reader: R, f: |R, Path<'t>| -> Decoded<T, E>) -> Decoded<T, E> {
                Message::decode_buf(reader, |reader, buf| -> Decoded<T, E> {
                    // FIXME
                    f(reader, Path::empty())
                })
            }

            fn with_message<R: Reader<'t>, T, E>(reader: R, f: |R, Message<'t>| -> Decoded<T, E>) -> Decoded<T, E> {
                Message::decode_type(reader, |reader, typ| -> Decoded<T, E> {
                    Message::decode_tag(reader, |reader, tag| -> Decoded<T, E> {
                        match typ {
                            TdispatchType => Message::decode_contexts(reader, |_, _| -> Decoded<T, E> {
                                Err(UnknownType(2))
                            }),
                            _ => Err(UnknownType(-128)),
                        }
                    })
                })
            }

            /// Decode a slice of bytes as a mux message.
            pub fn decoded<T, E>(bytes: &'t [u8], f: |Message<'t>| -> Decoded<T, E>) -> Decoded<T, E> {
                let buf = Buf::new(bytes);
                Message::with_message(buf, |_, msg| -> Decoded<T, E> { f(msg) })
            }

            /// Encode a mux message as bytes.
            pub fn encode(&self) -> Vec<u8> {
                match *self {
                    Tdispatch(tag, Contexts(contexts), Path(path), dtab, buf) => {
                        let tagsz = 3;
                        let ctxsz = Message::context_sz(contexts);
                        Vec::with_capacity(tagsz + ctxsz)
                    },

                    _ => Vec::new(),
                }
            }

            fn context_sz<'u>(contexts: &'u [Context]) -> uint {
                (*contexts).iter().fold(0u, |sum, &Context(kbuf, vbuf)| -> uint {
                    sum + 2+kbuf.len() + 2+vbuf.len()
                })
            }
        }

        #[cfg(test)]
        mod test {
            use mux::misc::{Contexts, Path, Dtab, Buf};
            use super::{Tag, Tdispatch, Message, Decoded};

            fn mk_tdispatch<'t>() -> Message<'t> {
                let tag = Tag(1u as u64);
                let contexts = Contexts::empty();
                let path = Path::empty();
                let dtab = Dtab::empty();
                let body = Buf::empty();
                Tdispatch(tag, contexts, path, dtab, body)
            }

            #[test]
            fn tdispatch() {
                let orig = mk_tdispatch();
                let bytes = orig.encode();

                let mut decoded: Option<Message> = None;
                let result: Decoded<bool, &str> = Message::decoded(bytes.as_slice(), |msg| {
                    decoded = Some(msg);
                    Ok(true)
                 });
                assert_eq!(decoded, Some(orig));
                assert_eq!(result, Ok(true));
            }
        }
    }
}

<|endoftext|>


<commit_before>mod base;
mod boolean;
mod num;
mod flt;

pub use base::{FromAscii};
pub use boolean::{ParseBoolError};
pub use num::{ParseIntError, FromAsciiRadix};
pub use flt::{ParseFloatError};
<commit_msg>Add module level documentation<commit_after>//!
//! This crate provides two traits: `FromAscii` which creates instances from ascii string (`&[u8]`) and `FromAsciiRadix` wich creates only integral values with given radix.
//!
//! Usage example:
//!
//! ```rust
//! extern crate from_ascii;
//!
//! use from_ascii::{FromAscii, FromAsciiRadix};
//!
//!
//! fn main() {
//!     println!("{}", f64::from_ascii(b"123.456"));
//!     println!("{}", i16::from_ascii_radix(b"FF", 16));
//! }
//! ```

mod base;
mod boolean;
mod num;
mod flt;

pub use base::{FromAscii};
pub use boolean::{ParseBoolError};
pub use num::{ParseIntError, FromAsciiRadix};
pub use flt::{ParseFloatError};
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

//! rav1e is an [AV1] video encoder.
//!
//! ## Overview
//!
//! rav1e is an experimental encoder. It is designed to eventually cover all
//! use cases, though in its current form it is most suitable for cases where
//! libaom (the reference encoder) is too slow.
//!
//! ## Features
//!
//! * Intra and inter frames
//! * 64x64 superblocks
//! * 4x4 to 64x64 RDO-selected square and 2:1/1:2 rectangular blocks
//! * DC, H, V, Paeth, smooth, and a subset of directional prediction modes
//! * DCT, ADST and identity transforms (up to 64x64, 16x16 and 32x32
//!   respectively)
//! * 8-, 10- and 12-bit depth color
//! * 4:2:0 (full support), 4:2:2 and 4:4:4 (limited) chroma sampling
//! * Variable speed settings
//! * Near real-time encoding at high speed levels
//!
//! ## Usage
//!
//! Encoding is done through the [`Context`] struct. Examples on
//! [`Context::receive_packet`] show how to create a [`Context`], send frames
//! into it and receive packets of encoded data.
//!
//! [AV1]: https://aomediacodec.github.io/av1-spec/av1-spec.pdf
//! [`Context`]: struct.Context.html
//! [`Context::receive_packet`]: struct.Context.html#method.receive_packet

#![allow(safe_extern_statics)]
#![deny(bare_trait_objects)]

// Override assert! and assert_eq! in tests
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(any(cargo_c, feature = "capi"))]
pub mod capi;

pub(crate) mod asm;
mod cpu_features;
mod dist;
mod ec;
mod partition;
mod predict;
mod quantize;
mod rdo;
mod rdo_tables;
mod transform;
#[macro_use]
mod util;
mod cdef;
mod context;
mod deblock;
mod encoder;
mod entropymode;
mod lrf;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod lrf_simd;
mod mc;
mod me;
mod metrics;
mod rate;
mod recon_intra;
mod scan_order;
mod scenechange;
mod segmentation;
mod tiling;
mod token_cdfs;

mod api;
mod frame;
mod header;

use crate::encoder::*;

pub use crate::api::{Config, Context, EncoderStatus, Packet};
pub use crate::frame::Frame;
pub use crate::util::{CastFromPrimitive, Pixel, PixelType};

/// Commonly used types and traits.
pub mod prelude {
  pub use crate::api::*;
  pub use crate::encoder::Tune;
  pub use crate::frame::Frame;
  pub use crate::frame::FrameParameters;
  pub use crate::frame::FrameTypeOverride;
  pub use crate::frame::Plane;
  pub use crate::frame::PlaneConfig;
  pub use crate::partition::BlockSize;
  pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
}

/// Basic data structures
pub mod data {
  pub use crate::api::{
    ChromaticityPoint, EncoderStatus, FrameType, Packet, Rational,
  };
  pub use crate::frame::Frame;
  pub use crate::frame::FrameParameters;
  pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
}

pub use crate::api::color;

/// Encoder configuration and settings
pub mod config {
  pub use crate::api::{
    Config, EncoderConfig, PredictionModesSetting, SpeedSettings,
  };
}

/// Version information
///
/// The information is recovered from `Cargo.toml` and `git describe`, when available.
///
/// ```
/// use rav1e::version;
/// use semver::Version;
///
/// let major = version::major();
/// let minor = version::minor();
/// let patch = version::patch();
///
/// let short = version::short();
///
/// let v1 = Version::new(major, minor, patch);
/// let v2 = Version::parse(&short).unwrap();
///
/// assert_eq!(v1, v2);
/// ```
pub mod version {
  /// Major version component
  ///
  /// It is increased every time a release presents a incompatible API change.
  pub fn major() -> u64 {
    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
  }
  /// Minor version component
  ///
  /// It is increased every time a release presents new functionalities are added
  /// in a backwards-compatible manner.
  pub fn minor() -> u64 {
    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
  }
  /// Patch version component
  ///
  /// It is increased every time a release provides only backwards-compatible bugfixes.
  pub fn patch() -> u64 {
    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
  }

  /// Version information as presented in `[package]` `version`.
  ///
  /// e.g. `0.1.0``
  ///
  /// Can be parsed by [semver](https://crates.io/crates/semver).
  pub fn short() -> String {
    env!("CARGO_PKG_VERSION").to_string()
  }

  /// Version information as presented in `[package] version` followed by the
  /// short commit hash if present.
  ///
  /// e.g. `0.1.0 - g743d464`
  ///
  pub fn long() -> String {
    let s = short();
    let hash = hash();

    if hash.is_empty() {
      s
    } else {
      format!("{} - {}", s, hash)
    }
  }

  /// Commit hash (short)
  ///
  /// Short hash of the git commit used by this build
  ///
  /// e.g. `g743d464`
  ///
  pub fn hash() -> String {
    env!("VERGEN_SHA_SHORT").to_string()
  }

  /// Version information with the information
  /// provided by `git describe --tags`.
  ///
  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
  ///
  pub fn full() -> String {
    let semver = env!("VERGEN_SEMVER_LIGHTWEIGHT");
    format!("{} ({})", short(), semver)
  }
}
#[cfg(all(test, any(feature = "decode_test", feature = "decode_test_dav1d")))]
mod test_encode_decode;

#[cfg(feature = "bench")]
pub mod bench {
  pub mod api {
    pub use crate::api::*;
  }
  pub mod cdef {
    pub use crate::cdef::*;
  }
  pub mod context {
    pub use crate::context::*;
  }
  pub mod dist {
    pub use crate::dist::*;
  }
  pub mod ec {
    pub use crate::ec::*;
  }
  pub mod encoder {
    pub use crate::encoder::*;
  }
  pub mod partition {
    pub use crate::partition::*;
  }
  pub mod frame {
    pub use crate::frame::*;
  }
  pub mod predict {
    pub use crate::predict::*;
  }
  pub mod rdo {
    pub use crate::rdo::*;
  }
  pub mod tiling {
    pub use crate::tiling::*;
  }
  pub mod transform {
    pub use crate::transform::*;
  }
  pub mod util {
    pub use crate::util::*;
  }
}
<commit_msg>Remove "experimental" from crate-level docs<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

//! rav1e is an [AV1] video encoder. It is designed to eventually cover all use
//! cases, though in its current form it is most suitable for cases where
//! libaom (the reference encoder) is too slow.
//!
//! ## Features
//!
//! * Intra and inter frames
//! * 64x64 superblocks
//! * 4x4 to 64x64 RDO-selected square and 2:1/1:2 rectangular blocks
//! * DC, H, V, Paeth, smooth, and a subset of directional prediction modes
//! * DCT, ADST and identity transforms (up to 64x64, 16x16 and 32x32
//!   respectively)
//! * 8-, 10- and 12-bit depth color
//! * 4:2:0 (full support), 4:2:2 and 4:4:4 (limited) chroma sampling
//! * Variable speed settings
//! * Near real-time encoding at high speed levels
//!
//! ## Usage
//!
//! Encoding is done through the [`Context`] struct. Examples on
//! [`Context::receive_packet`] show how to create a [`Context`], send frames
//! into it and receive packets of encoded data.
//!
//! [AV1]: https://aomediacodec.github.io/av1-spec/av1-spec.pdf
//! [`Context`]: struct.Context.html
//! [`Context::receive_packet`]: struct.Context.html#method.receive_packet

#![allow(safe_extern_statics)]
#![deny(bare_trait_objects)]

// Override assert! and assert_eq! in tests
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(any(cargo_c, feature = "capi"))]
pub mod capi;

pub(crate) mod asm;
mod cpu_features;
mod dist;
mod ec;
mod partition;
mod predict;
mod quantize;
mod rdo;
mod rdo_tables;
mod transform;
#[macro_use]
mod util;
mod cdef;
mod context;
mod deblock;
mod encoder;
mod entropymode;
mod lrf;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod lrf_simd;
mod mc;
mod me;
mod metrics;
mod rate;
mod recon_intra;
mod scan_order;
mod scenechange;
mod segmentation;
mod tiling;
mod token_cdfs;

mod api;
mod frame;
mod header;

use crate::encoder::*;

pub use crate::api::{Config, Context, EncoderStatus, Packet};
pub use crate::frame::Frame;
pub use crate::util::{CastFromPrimitive, Pixel, PixelType};

/// Commonly used types and traits.
pub mod prelude {
  pub use crate::api::*;
  pub use crate::encoder::Tune;
  pub use crate::frame::Frame;
  pub use crate::frame::FrameParameters;
  pub use crate::frame::FrameTypeOverride;
  pub use crate::frame::Plane;
  pub use crate::frame::PlaneConfig;
  pub use crate::partition::BlockSize;
  pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
}

/// Basic data structures
pub mod data {
  pub use crate::api::{
    ChromaticityPoint, EncoderStatus, FrameType, Packet, Rational,
  };
  pub use crate::frame::Frame;
  pub use crate::frame::FrameParameters;
  pub use crate::util::{CastFromPrimitive, Pixel, PixelType};
}

pub use crate::api::color;

/// Encoder configuration and settings
pub mod config {
  pub use crate::api::{
    Config, EncoderConfig, PredictionModesSetting, SpeedSettings,
  };
}

/// Version information
///
/// The information is recovered from `Cargo.toml` and `git describe`, when available.
///
/// ```
/// use rav1e::version;
/// use semver::Version;
///
/// let major = version::major();
/// let minor = version::minor();
/// let patch = version::patch();
///
/// let short = version::short();
///
/// let v1 = Version::new(major, minor, patch);
/// let v2 = Version::parse(&short).unwrap();
///
/// assert_eq!(v1, v2);
/// ```
pub mod version {
  /// Major version component
  ///
  /// It is increased every time a release presents a incompatible API change.
  pub fn major() -> u64 {
    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
  }
  /// Minor version component
  ///
  /// It is increased every time a release presents new functionalities are added
  /// in a backwards-compatible manner.
  pub fn minor() -> u64 {
    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
  }
  /// Patch version component
  ///
  /// It is increased every time a release provides only backwards-compatible bugfixes.
  pub fn patch() -> u64 {
    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
  }

  /// Version information as presented in `[package]` `version`.
  ///
  /// e.g. `0.1.0``
  ///
  /// Can be parsed by [semver](https://crates.io/crates/semver).
  pub fn short() -> String {
    env!("CARGO_PKG_VERSION").to_string()
  }

  /// Version information as presented in `[package] version` followed by the
  /// short commit hash if present.
  ///
  /// e.g. `0.1.0 - g743d464`
  ///
  pub fn long() -> String {
    let s = short();
    let hash = hash();

    if hash.is_empty() {
      s
    } else {
      format!("{} - {}", s, hash)
    }
  }

  /// Commit hash (short)
  ///
  /// Short hash of the git commit used by this build
  ///
  /// e.g. `g743d464`
  ///
  pub fn hash() -> String {
    env!("VERGEN_SHA_SHORT").to_string()
  }

  /// Version information with the information
  /// provided by `git describe --tags`.
  ///
  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
  ///
  pub fn full() -> String {
    let semver = env!("VERGEN_SEMVER_LIGHTWEIGHT");
    format!("{} ({})", short(), semver)
  }
}
#[cfg(all(test, any(feature = "decode_test", feature = "decode_test_dav1d")))]
mod test_encode_decode;

#[cfg(feature = "bench")]
pub mod bench {
  pub mod api {
    pub use crate::api::*;
  }
  pub mod cdef {
    pub use crate::cdef::*;
  }
  pub mod context {
    pub use crate::context::*;
  }
  pub mod dist {
    pub use crate::dist::*;
  }
  pub mod ec {
    pub use crate::ec::*;
  }
  pub mod encoder {
    pub use crate::encoder::*;
  }
  pub mod partition {
    pub use crate::partition::*;
  }
  pub mod frame {
    pub use crate::frame::*;
  }
  pub mod predict {
    pub use crate::predict::*;
  }
  pub mod rdo {
    pub use crate::rdo::*;
  }
  pub mod tiling {
    pub use crate::tiling::*;
  }
  pub mod transform {
    pub use crate::transform::*;
  }
  pub mod util {
    pub use crate::util::*;
  }
}
<|endoftext|>