<commit_before>//! Models about OAuth2 applications.

use std::fmt;

use super::id::{snowflake, ApplicationId, UserId};
use super::{user::User, utils::*};

/// Information about a user's application. An application does not necessarily
/// have an associated bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ApplicationInfo {
    /// The bot user associated with the application. See [`BotApplication`] for
    /// more information.
    pub bot: Option<BotApplication>,
    /// Indicator of whether the bot is public.
    ///
    /// If a bot is public, anyone may invite it to their [`Guild`]. While a bot
    /// is private, only the owner may add it to a guild.
    ///
    /// [`Guild`]: super::guild::Guild
    #[serde(default = "default_true")]
    pub bot_public: bool,
    /// Indicator of whether the bot requires an OAuth2 code grant.
    pub bot_require_code_grant: bool,
    /// A description of the application, assigned by the application owner.
    pub description: String,
    /// A set of bitflags assigned to the application, which represent gated
    /// feature flags that have been enabled for the application.
    ///
    /// You can get a usable value from this by using [`ApplicationFlags::from_u64`]
    pub flags: Option<u64>,
    /// A hash pointing to the application's icon.
    ///
    /// This is not necessarily equivalent to the bot user's avatar.
    pub icon: Option<String>,
    /// The unique numeric Id of the application.
    pub id: ApplicationId,
    /// The name assigned to the application by the application owner.
    pub name: String,
    /// A list of redirect URIs assigned to the application.
    pub redirect_uris: Vec<String>,
    /// A list of RPC Origins assigned to the application.
    pub rpc_origins: Vec<String>,
    /// The application team group.
    pub team: Option<Vec<Team>>,
    /// The given secret to the application.
    ///
    /// This is not equivalent to the application's bot user's token.
    pub secret: String,
}

impl fmt::Debug for ApplicationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ApplicationInfo")
            .field("bot", &self.bot)
            .field("bot_public", &self.bot_public)
            .field("bot_require_code_grant", &self.bot_require_code_grant)
            .field("description", &self.description)
            .field("flags", &self.flags)
            .field("icon", &self.icon)
            .field("id", &self.id)
            .field("name", &self.name)
            .field("redirect_uris", &self.redirect_uris)
            .field("rpc_origins", &self.rpc_origins)
            .field("team", &self.team)
            .finish()
    }
}

/// Information about an application with an application's bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct BotApplication {
    /// The unique Id of the bot user.
    pub id: UserId,
    /// A hash of the avatar, if one is assigned.
    ///
    /// Can be used to generate a full URL to the avatar.
    pub avatar: Option<String>,
    /// Indicator of whether it is a bot.
    #[serde(default)]
    pub bot: bool,
    /// The discriminator assigned to the bot user.
    ///
    /// While discriminators are not unique, the `username#discriminator` pair
    /// is.
    pub discriminator: u16,
    /// The bot user's username.
    pub name: String,
    /// The token used to authenticate as the bot user.
    ///
    /// **Note**: Keep this information private, as untrusted sources can use it
    /// to perform any action with a bot user.
    pub token: String,
}

impl fmt::Debug for BotApplication {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BotApplication")
            .field("id", &self.id)
            .field("avatar", &self.avatar)
            .field("bot", &self.bot)
            .field("discriminator", &self.discriminator)
            .field("name", &self.name)
            .finish()
    }
}

/// Partial information about the given application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PartialCurrentApplicationInfo {
    /// The unique Id of the user.
    pub id: ApplicationId,
    /// The flags associated with the application.
    ///
    /// You can get a usable value from this by using [`ApplicationFlags::from_u64`]
    pub flags: u64,
}

/// Information about the current application and its owner.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CurrentApplicationInfo {
    pub description: String,
    pub icon: Option<String>,
    pub id: ApplicationId,
    pub name: String,
    pub owner: User,
    #[serde(default)]
    pub rpc_origins: Vec<String>,
    pub bot_public: bool,
    pub bot_require_code_grant: bool,
    pub team: Option<Team>,
}

/// Information about the Team group of the application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Team {
    /// The icon of the team.
    pub icon: Option<String>,
    /// The snowflake ID of the team.
    #[serde(with = "snowflake")]
    pub id: u64,
    /// The name of the team.
    pub name: String,
    /// The members of the team
    pub members: Vec<TeamMember>,
    /// The user id of the team owner.
    pub owner_user_id: UserId,
}

/// Information about a Member on a Team.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TeamMember {
    /// The member's membership state.
    pub membership_state: MembershipState,
    /// The list of permissions of the member on the team.
    ///
    /// NOTE: Will always be ["*"] for now.
    pub permissions: Vec<String>,
    /// The ID of the team they are a member of.
    #[serde(with = "snowflake")]
    pub team_id: u64,
    /// The user type of the team member.
    pub user: User,
}

#[derive(Clone, Debug, Copy, PartialEq)]
pub enum MembershipState {
    Invited = 1,
    Accepted = 2,
    Unknown = !0,
}

enum_number!(MembershipState {
    Invited,
    Accepted
});

bitflags! {
    /// The flags of the application.
    #[derive(Default)]
    pub struct ApplicationFlags: u64 {
        const GATEWAY_PRESENCE = 1 << 12;
        const GATEWAY_PRESENCE_LIMITED = 1 << 13;
        const GATEWAY_GUILD_MEMBERS = 1 << 14;
        const GATEWAY_GUILD_MEMBERS_LIMITED = 1 << 15;
        const VERIFICATION_PENDING_GUILD_LIMIT = 2 << 16;
        const EMBEDDED = 2 << 17;
        const GATEWAY_MESSAGE_CONTENT = 2 << 18;
        const GATEWAY_MESSAGE_CONTENT_LIMITED = 2 << 19;
    }
}

impl ApplicationFlags {
    pub fn from_u64(bits: u64) -> Self {
        Self {
            bits,
        }
    }
}
<commit_msg>Use `ApplicationFlags` bitflags in the application info structs (#1783)<commit_after>//! Models about OAuth2 applications.

use std::fmt;

use super::id::{snowflake, ApplicationId, UserId};
use super::{user::User, utils::*};

/// Information about a user's application. An application does not necessarily
/// have an associated bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ApplicationInfo {
    /// The bot user associated with the application. See [`BotApplication`] for
    /// more information.
    pub bot: Option<BotApplication>,
    /// Indicator of whether the bot is public.
    ///
    /// If a bot is public, anyone may invite it to their [`Guild`]. While a bot
    /// is private, only the owner may add it to a guild.
    ///
    /// [`Guild`]: super::guild::Guild
    #[serde(default = "default_true")]
    pub bot_public: bool,
    /// Indicator of whether the bot requires an OAuth2 code grant.
    pub bot_require_code_grant: bool,
    /// A description of the application, assigned by the application owner.
    pub description: String,
    /// A set of bitflags assigned to the application, which represent gated
    /// feature flags that have been enabled for the application.
    pub flags: Option<ApplicationFlags>,
    /// A hash pointing to the application's icon.
    ///
    /// This is not necessarily equivalent to the bot user's avatar.
    pub icon: Option<String>,
    /// The unique numeric Id of the application.
    pub id: ApplicationId,
    /// The name assigned to the application by the application owner.
    pub name: String,
    /// A list of redirect URIs assigned to the application.
    pub redirect_uris: Vec<String>,
    /// A list of RPC Origins assigned to the application.
    pub rpc_origins: Vec<String>,
    /// The application team group.
    pub team: Option<Vec<Team>>,
    /// The given secret to the application.
    ///
    /// This is not equivalent to the application's bot user's token.
    pub secret: String,
}

impl fmt::Debug for ApplicationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("ApplicationInfo")
            .field("bot", &self.bot)
            .field("bot_public", &self.bot_public)
            .field("bot_require_code_grant", &self.bot_require_code_grant)
            .field("description", &self.description)
            .field("flags", &self.flags)
            .field("icon", &self.icon)
            .field("id", &self.id)
            .field("name", &self.name)
            .field("redirect_uris", &self.redirect_uris)
            .field("rpc_origins", &self.rpc_origins)
            .field("team", &self.team)
            .finish()
    }
}

/// Information about an application with an application's bot user.
#[derive(Clone, Deserialize, Serialize)]
#[non_exhaustive]
pub struct BotApplication {
    /// The unique Id of the bot user.
    pub id: UserId,
    /// A hash of the avatar, if one is assigned.
    ///
    /// Can be used to generate a full URL to the avatar.
    pub avatar: Option<String>,
    /// Indicator of whether it is a bot.
    #[serde(default)]
    pub bot: bool,
    /// The discriminator assigned to the bot user.
    ///
    /// While discriminators are not unique, the `username#discriminator` pair
    /// is.
    pub discriminator: u16,
    /// The bot user's username.
    pub name: String,
    /// The token used to authenticate as the bot user.
    ///
    /// **Note**: Keep this information private, as untrusted sources can use it
    /// to perform any action with a bot user.
    pub token: String,
}

impl fmt::Debug for BotApplication {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BotApplication")
            .field("id", &self.id)
            .field("avatar", &self.avatar)
            .field("bot", &self.bot)
            .field("discriminator", &self.discriminator)
            .field("name", &self.name)
            .finish()
    }
}

/// Partial information about the given application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PartialCurrentApplicationInfo {
    /// The unique Id of the user.
    pub id: ApplicationId,
    /// The flags associated with the application.
    pub flags: ApplicationFlags,
}

/// Information about the current application and its owner.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct CurrentApplicationInfo {
    pub description: String,
    pub icon: Option<String>,
    pub id: ApplicationId,
    pub name: String,
    pub owner: User,
    #[serde(default)]
    pub rpc_origins: Vec<String>,
    pub bot_public: bool,
    pub bot_require_code_grant: bool,
    pub team: Option<Team>,
}

/// Information about the Team group of the application.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Team {
    /// The icon of the team.
    pub icon: Option<String>,
    /// The snowflake ID of the team.
    #[serde(with = "snowflake")]
    pub id: u64,
    /// The name of the team.
    pub name: String,
    /// The members of the team
    pub members: Vec<TeamMember>,
    /// The user id of the team owner.
    pub owner_user_id: UserId,
}

/// Information about a Member on a Team.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TeamMember {
    /// The member's membership state.
    pub membership_state: MembershipState,
    /// The list of permissions of the member on the team.
    ///
    /// NOTE: Will always be ["*"] for now.
    pub permissions: Vec<String>,
    /// The ID of the team they are a member of.
    #[serde(with = "snowflake")]
    pub team_id: u64,
    /// The user type of the team member.
    pub user: User,
}

#[derive(Clone, Debug, Copy, PartialEq)]
pub enum MembershipState {
    Invited = 1,
    Accepted = 2,
    Unknown = !0,
}

enum_number!(MembershipState {
    Invited,
    Accepted
});

bitflags! {
    /// The flags of the application.
    #[derive(Default)]
    pub struct ApplicationFlags: u64 {
        const GATEWAY_PRESENCE = 1 << 12;
        const GATEWAY_PRESENCE_LIMITED = 1 << 13;
        const GATEWAY_GUILD_MEMBERS = 1 << 14;
        const GATEWAY_GUILD_MEMBERS_LIMITED = 1 << 15;
        const VERIFICATION_PENDING_GUILD_LIMIT = 2 << 16;
        const EMBEDDED = 2 << 17;
        const GATEWAY_MESSAGE_CONTENT = 2 << 18;
        const GATEWAY_MESSAGE_CONTENT_LIMITED = 2 << 19;
    }
}
<|endoftext|>


<commit_before>//! FBX binary parser.

use std::io;
use std::io::Read;

pub use self::error::{Result, Error, Warning};
pub use self::event::{Event, FbxHeader, FbxFooter, StartNode};
pub use self::event::{Attributes, Attribute, SpecialAttributeType};
pub use self::event::{PrimitiveAttribute, ArrayAttribute, SpecialAttribute};
pub use self::event::ArrayAttributeReader;
use self::event::{EventBuilder, NodeHeader, StartNodeBuilder};
use self::event::read_fbx_header;
pub use self::reader::{BasicSource, SeekableSource};
use self::reader::ParserSource;

mod error;
mod event;
mod reader;

/// Parser state without error.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
    /// Reading file header.
    Header,
    /// A node started.
    ///
    /// This status means:
    ///
    /// - there might be some attributes remain unread, or
    /// - the most recent opened node might close without no null node header.
    NodeStarted,
    /// A node ended.
    ///
    /// This status means:
    ///
    /// - if the next event is `NodeEnd`, there must be a null node header, and
    /// - if the parser got an extra null header, it indicates end of implicit root node.
    NodeEnded,
}

/// Information about opened (but not yet closed) node.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct OpenNode {
    /// Start offset of the node attribute.
    ///
    /// Note that this doesn't mean start offset of node header.
    begin: u64,
    /// End offset of the node.
    end: u64,
    /// End offset of attributes of the node.
    attributes_end: u64,
}

/// Pull parser for FBX binary format.
#[derive(Debug)]
pub struct BinaryParser<R> {
    /// Source reader.
    source: R,
    /// Parser state.
    ///
    /// `Ok(State)` if the parser is working without critical error,
    /// `Err(Error)` if the parsing failed and cannot be continued.
    state: Result<State>,
    /// Warnings.
    warnings: Vec<Warning>,
    /// FBX version.
    fbx_version: Option<u32>,
    /// Open nodes stack.
    open_nodes: Vec<OpenNode>,
}

impl<R: Read> BinaryParser<BasicSource<R>> {
    /// Creates a new binary parser.
    pub fn new(source: R) -> Self {
        BinaryParser {
            source: BasicSource::new(source),
            state: Ok(State::Header),
            warnings: Vec::new(),
            fbx_version: None,
            open_nodes: Vec::new(),
        }
    }
}

impl<R: Read + io::Seek> BinaryParser<SeekableSource<R>> {
    /// Creates a new binary parser.
    pub fn from_seekable(source: R) -> Self {
        BinaryParser {
            source: SeekableSource::new(source),
            state: Ok(State::Header),
            warnings: Vec::new(),
            fbx_version: None,
            open_nodes: Vec::new(),
        }
    }
}

impl<R: ParserSource> BinaryParser<R> {
    /// Returns FBX version of the reading input.
    ///
    /// Returns `None` if unknown yet.
    pub fn fbx_version(&self) -> Option<u32> {
        self.fbx_version
    }

    /// Returns the parser error if available.
    pub fn error(&self) -> Option<&Error> {
        self.state.as_ref().err()
    }

    /// Returns reference to the warnings.
    pub fn warnings(&self) -> &Vec<Warning> {
        &self.warnings
    }

    /// Parses FBX from the given stream and returns the next event.
    pub fn next_event(&mut self) -> Result<Event<R>> {
        let builder = match try!(self.state.clone()) {
            State::Header => self.read_fbx_header(),
            State::NodeStarted => self.read_after_node_start(),
            State::NodeEnded => self.read_after_node_end(),
        };
        if let Err(ref err) = builder {
            self.set_error(err);
        }
        Ok(try!(builder).build(self))
    }

    /// Returns the number of the opened (and not closed) node.
    pub fn num_open_nodes(&self) -> usize {
        self.open_nodes.len()
    }

    /// Set the parser state as finished parsing.
    fn set_finish(&mut self) {
        self.state = Err(Error::Finished);
    }

    /// Set the parser state as error.
    fn set_error(&mut self, err: &Error) {
        error!("FBX binary parser error: {}", err);
        debug!("Parser: {:#?}", self);
        self.state = Err(err.clone());
    }

    /// Add warning.
    fn warn(&mut self, warning: Warning) {
        warn!("FBX binary parser warning: {}", warning);
        debug!("Parser: {:#?}", self);
        self.warnings.push(warning);
    }

    /// Reads FBX header.
    fn read_fbx_header(&mut self) -> Result<EventBuilder> {
        let header = try!(read_fbx_header(self));
        self.fbx_version = Some(header.version);
        self.state = Ok(State::NodeEnded);
        Ok(header.into())
    }

    /// Gets event after node start.
    fn read_after_node_start(&mut self) -> Result<EventBuilder> {
        // Attributes of recent opened node might remain partially unread.
        // They should be skipped before getting a next node event.
        try!(self.skip_attributes());

        // Most recent opened node might ends here without a null node header.
        if let Some(end) = self.open_nodes.last().map(|v| v.end) {
            if self.source.position() == end {
                // Most recent opened node ends here (without a null node header).
                self.state = Ok(State::NodeEnded);
                self.open_nodes.pop();
                return Ok(EventBuilder::EndNode);
            }
        }

        let builder = try!(self.read_node_event());
        Ok(builder)
    }

    /// Gets event after node end.
    fn read_after_node_end(&mut self) -> Result<EventBuilder> {
        self.read_node_event()
    }

    /// Reads a next node-related event from the source.
    ///
    /// This always returns `Ok(EventBuilder::StartNode)`, `Ok(EventBuilder::EndNode)`,
    /// `Ok(EventBuilder::EndFbx)` or `Err(_)`.
    fn read_node_event(&mut self) -> Result<EventBuilder> {
        let header = try!(NodeHeader::read_from_parser(self));
        if header.is_node_end() {
            if let Some(last_node) = self.open_nodes.pop() {
                // There is open nodes, so this is not end of the FBX.
                let current_pos = self.source.position();
                if current_pos != last_node.end {
                    // Invalid node header.
                    return Err(Error::WrongNodeEndOffset {
                        begin: last_node.begin,
                        expected_end: last_node.end,
                        real_end: current_pos,
                    });
                }
            } else {
                assert_eq!(self.state.as_ref().ok(),
                           Some(&State::NodeEnded),
                           "End of implicit root node is read with unexpected parser state {:?}",
                           self.state);
                // No open nodes, so this `EndNode` event indicates the end of
                // the implicit root node.
                // FBX file has no more nodes.
                let footer = self.read_fbx_footer();
                return Ok(footer.into());
            }

            self.state = Ok(State::NodeEnded);
            Ok(EventBuilder::EndNode)
        } else {
            let mut name_vec = vec![0u8; header.bytelen_name as usize];
            try!(self.source.read_exact(&mut name_vec));
            let name = try!(String::from_utf8(name_vec).map_err(Error::node_name_invalid_utf8));
            let current_pos = self.source.position();
            self.open_nodes.push(OpenNode {
                begin: current_pos,
                end: header.end_offset,
                attributes_end: current_pos + header.bytelen_attributes,
            });

            // Zero or more attributes come after node start.
            self.state = Ok(State::NodeStarted);
            Ok(StartNodeBuilder {
                name: name,
                header: header,
            }
            .into())
        }
    }

    /// Reads an FBX footer.
    fn read_fbx_footer(&mut self) -> Result<FbxFooter> {
        self.set_finish();
        FbxFooter::read_from_parser(self)
    }

    /// Skip attributes of the most recent opened node.
    fn skip_attributes(&mut self) -> io::Result<()> {
        let attributes_end = self.open_nodes
            .last()
            .expect("`BinaryParser::skip_attributes()` is called but no nodes are open")
            .attributes_end;
        self.source.skip_to(attributes_end)
    }
}
<commit_msg>Make `LimitedSeekReader` public<commit_after>//! FBX binary parser.

use std::io;
use std::io::Read;

pub use self::error::{Result, Error, Warning};
pub use self::event::{Event, FbxHeader, FbxFooter, StartNode};
pub use self::event::{Attributes, Attribute, SpecialAttributeType};
pub use self::event::{PrimitiveAttribute, ArrayAttribute, SpecialAttribute};
pub use self::event::ArrayAttributeReader;
use self::event::{EventBuilder, NodeHeader, StartNodeBuilder};
use self::event::read_fbx_header;
pub use self::reader::{BasicSource, SeekableSource, LimitedSeekReader};
use self::reader::ParserSource;

mod error;
mod event;
mod reader;

/// Parser state without error.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum State {
    /// Reading file header.
    Header,
    /// A node started.
    ///
    /// This status means:
    ///
    /// - there might be some attributes remain unread, or
    /// - the most recent opened node might close without no null node header.
    NodeStarted,
    /// A node ended.
    ///
    /// This status means:
    ///
    /// - if the next event is `NodeEnd`, there must be a null node header, and
    /// - if the parser got an extra null header, it indicates end of implicit root node.
    NodeEnded,
}

/// Information about opened (but not yet closed) node.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct OpenNode {
    /// Start offset of the node attribute.
    ///
    /// Note that this doesn't mean start offset of node header.
    begin: u64,
    /// End offset of the node.
    end: u64,
    /// End offset of attributes of the node.
    attributes_end: u64,
}

/// Pull parser for FBX binary format.
#[derive(Debug)]
pub struct BinaryParser<R> {
    /// Source reader.
    source: R,
    /// Parser state.
    ///
    /// `Ok(State)` if the parser is working without critical error,
    /// `Err(Error)` if the parsing failed and cannot be continued.
    state: Result<State>,
    /// Warnings.
    warnings: Vec<Warning>,
    /// FBX version.
    fbx_version: Option<u32>,
    /// Open nodes stack.
    open_nodes: Vec<OpenNode>,
}

impl<R: Read> BinaryParser<BasicSource<R>> {
    /// Creates a new binary parser.
    pub fn new(source: R) -> Self {
        BinaryParser {
            source: BasicSource::new(source),
            state: Ok(State::Header),
            warnings: Vec::new(),
            fbx_version: None,
            open_nodes: Vec::new(),
        }
    }
}

impl<R: Read + io::Seek> BinaryParser<SeekableSource<R>> {
    /// Creates a new binary parser.
    pub fn from_seekable(source: R) -> Self {
        BinaryParser {
            source: SeekableSource::new(source),
            state: Ok(State::Header),
            warnings: Vec::new(),
            fbx_version: None,
            open_nodes: Vec::new(),
        }
    }
}

impl<R: ParserSource> BinaryParser<R> {
    /// Returns FBX version of the reading input.
    ///
    /// Returns `None` if unknown yet.
    pub fn fbx_version(&self) -> Option<u32> {
        self.fbx_version
    }

    /// Returns the parser error if available.
    pub fn error(&self) -> Option<&Error> {
        self.state.as_ref().err()
    }

    /// Returns reference to the warnings.
    pub fn warnings(&self) -> &Vec<Warning> {
        &self.warnings
    }

    /// Parses FBX from the given stream and returns the next event.
    pub fn next_event(&mut self) -> Result<Event<R>> {
        let builder = match try!(self.state.clone()) {
            State::Header => self.read_fbx_header(),
            State::NodeStarted => self.read_after_node_start(),
            State::NodeEnded => self.read_after_node_end(),
        };
        if let Err(ref err) = builder {
            self.set_error(err);
        }
        Ok(try!(builder).build(self))
    }

    /// Returns the number of the opened (and not closed) node.
    pub fn num_open_nodes(&self) -> usize {
        self.open_nodes.len()
    }

    /// Set the parser state as finished parsing.
    fn set_finish(&mut self) {
        self.state = Err(Error::Finished);
    }

    /// Set the parser state as error.
    fn set_error(&mut self, err: &Error) {
        error!("FBX binary parser error: {}", err);
        debug!("Parser: {:#?}", self);
        self.state = Err(err.clone());
    }

    /// Add warning.
    fn warn(&mut self, warning: Warning) {
        warn!("FBX binary parser warning: {}", warning);
        debug!("Parser: {:#?}", self);
        self.warnings.push(warning);
    }

    /// Reads FBX header.
    fn read_fbx_header(&mut self) -> Result<EventBuilder> {
        let header = try!(read_fbx_header(self));
        self.fbx_version = Some(header.version);
        self.state = Ok(State::NodeEnded);
        Ok(header.into())
    }

    /// Gets event after node start.
    fn read_after_node_start(&mut self) -> Result<EventBuilder> {
        // Attributes of recent opened node might remain partially unread.
        // They should be skipped before getting a next node event.
        try!(self.skip_attributes());

        // Most recent opened node might ends here without a null node header.
        if let Some(end) = self.open_nodes.last().map(|v| v.end) {
            if self.source.position() == end {
                // Most recent opened node ends here (without a null node header).
                self.state = Ok(State::NodeEnded);
                self.open_nodes.pop();
                return Ok(EventBuilder::EndNode);
            }
        }

        let builder = try!(self.read_node_event());
        Ok(builder)
    }

    /// Gets event after node end.
    fn read_after_node_end(&mut self) -> Result<EventBuilder> {
        self.read_node_event()
    }

    /// Reads a next node-related event from the source.
    ///
    /// This always returns `Ok(EventBuilder::StartNode)`, `Ok(EventBuilder::EndNode)`,
    /// `Ok(EventBuilder::EndFbx)` or `Err(_)`.
    fn read_node_event(&mut self) -> Result<EventBuilder> {
        let header = try!(NodeHeader::read_from_parser(self));
        if header.is_node_end() {
            if let Some(last_node) = self.open_nodes.pop() {
                // There is open nodes, so this is not end of the FBX.
                let current_pos = self.source.position();
                if current_pos != last_node.end {
                    // Invalid node header.
                    return Err(Error::WrongNodeEndOffset {
                        begin: last_node.begin,
                        expected_end: last_node.end,
                        real_end: current_pos,
                    });
                }
            } else {
                assert_eq!(self.state.as_ref().ok(),
                           Some(&State::NodeEnded),
                           "End of implicit root node is read with unexpected parser state {:?}",
                           self.state);
                // No open nodes, so this `EndNode` event indicates the end of
                // the implicit root node.
                // FBX file has no more nodes.
                let footer = self.read_fbx_footer();
                return Ok(footer.into());
            }

            self.state = Ok(State::NodeEnded);
            Ok(EventBuilder::EndNode)
        } else {
            let mut name_vec = vec![0u8; header.bytelen_name as usize];
            try!(self.source.read_exact(&mut name_vec));
            let name = try!(String::from_utf8(name_vec).map_err(Error::node_name_invalid_utf8));
            let current_pos = self.source.position();
            self.open_nodes.push(OpenNode {
                begin: current_pos,
                end: header.end_offset,
                attributes_end: current_pos + header.bytelen_attributes,
            });

            // Zero or more attributes come after node start.
            self.state = Ok(State::NodeStarted);
            Ok(StartNodeBuilder {
                name: name,
                header: header,
            }
            .into())
        }
    }

    /// Reads an FBX footer.
    fn read_fbx_footer(&mut self) -> Result<FbxFooter> {
        self.set_finish();
        FbxFooter::read_from_parser(self)
    }

    /// Skip attributes of the most recent opened node.
    fn skip_attributes(&mut self) -> io::Result<()> {
        let attributes_end = self.open_nodes
            .last()
            .expect("`BinaryParser::skip_attributes()` is called but no nodes are open")
            .attributes_end;
        self.source.skip_to(attributes_end)
    }
}
<|endoftext|>


<commit_before>extern crate rocket;

use rocket::request::{FromForm, FormItems};

pub struct WhereStructResult {
    sql: String, values: Vec<String>,
}

// My Results
type QueryOpResult = Result<String, String>;
type WhereResult = Result<WhereStructResult, String>;

// TODO: Move there later
pub struct Params {
    pub k: String, pub v: String,
}
// implement QueryString
pub struct QueryString {
    pub query: Vec<Params>
}

impl<'f> FromForm<'f> for QueryString {
    type Error = ();

    fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<QueryString, ()> {
        let mut qs: QueryString = QueryString{ query: Vec::new() };
        for (k, v) in items {
            qs.query.push(Params{k: k.to_string(), v: v.url_decode().unwrap()});
        }
        Ok(qs)
    }
}

pub fn query_operator(qop: &String) -> QueryOpResult {
    match &qop[..] {
        "$eq" => Ok("=".to_string()),
        "$ne" => Ok("!=".to_string()),
        "$gt" => Ok(">".to_string()),
        "$lt" => Ok("<".to_string()),
        "$gte" => Ok(">=".to_string()),
        "$lte" => Ok("<=".to_string()),
        "$in" => Ok("IN".to_string()),
        "$nin" => Ok("NOT IN".to_string()),
        "$notnull" => Ok("IS NOT NULL".to_string()),
        "$null" => Ok("IS NULL".to_string()),
         _ => Err(format!("operator {} not found", qop)),
    }
}

// Get QueryString and return chunck WHERE statement with values
pub fn ext_where(qs: QueryString) -> WhereResult {
    let where_syntax: String;
    let mut pid: u32 = 0;
    let mut where_values: Vec<String> = Vec::new();
    let mut where_fields: Vec<String> = Vec::new();

    for params in &qs.query {
        pid = pid + 1;
        let result = match params.v.contains(".") {
            true => {
                let v: Vec<&str> = params.v.split(".").collect();
                let op = match query_operator(&v[0].to_string()) {
                    Ok(x) => x,
                    Err(e) => return Err(e.to_string())
                };
                (op, v[1].to_string())
            },
            _ => ("=".to_string(), params.v.to_string())
        };
        where_fields.push(format!("{}{}${}", params.k, result.0, pid));
        where_values.push(result.1);
    }

    if pid > 1 {
        where_syntax = format!("WHERE {}", where_fields.join(" AND "));
    } else {
        where_syntax = format!("WHERE {}", where_fields.join(" "));
    }

    Ok(WhereStructResult {
        sql: where_syntax,
        values: where_values
    })
}

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

    #[test]
    fn get_opetators() {
        use std::collections::HashMap;

        let mut test_cases = HashMap::new();
        test_cases.insert("$eq", "=");
        test_cases.insert("$ne", "!=");
        test_cases.insert("$gt", ">");
        test_cases.insert("$gte", ">=");
        test_cases.insert("$lt", "<");
        test_cases.insert("$lte", "<=");
        test_cases.insert("$in", "IN");
        test_cases.insert("$nin", "NOT IN");
        test_cases.insert("$notnull", "IS NOT NULL");
        test_cases.insert("$null", "IS NULL");

        for (op, expected) in &test_cases {
            match query_operator(&op.to_string()) {
                Ok(x) => assert_eq!(expected.to_string(), x),
                Err(e) => assert_eq!("", e)
            }
        }
    }

    #[test]
    fn get_opetators_error() {
        let invalid = "!tn".to_string();
        match query_operator(&invalid) {
            Ok(_) => println!("no result"),
            Err(e) => assert_eq!(format!("operator {} not found", invalid), e)
        }
    }

    #[test]
    fn where_by_request_one_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1".to_string());
        assert_eq!(result.values, vec!["5".to_string()])
    }

    #[test]
    fn where_by_request_n_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$ne.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id!=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_invalid_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$nt.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        match ext_where(qs) {
            Err(e) => assert_eq!(e, "operator $nt not found"),
            Ok(_) => println!("no result")
        }
    }
}
<commit_msg>Refactor ext_where command<commit_after>extern crate rocket;

use rocket::request::{FromForm, FormItems};

pub struct WhereStructResult {
    sql: String, values: Vec<String>,
}

// My Results
type QueryOpResult = Result<&'static str, String>;
type WhereResult = Result<WhereStructResult, String>;

// TODO: Move there later
#[derive(Clone)]
pub struct Params {
    pub k: String, pub v: String,
}
// implement QueryString
pub struct QueryString {
    pub query: Vec<Params>
}

impl<'f> FromForm<'f> for QueryString {
    type Error = ();

    fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<QueryString, ()> {
        let mut qs: QueryString = QueryString{ query: Vec::new() };
        for (k, v) in items {
            qs.query.push(Params{k: k.to_string(), v: v.url_decode().unwrap()});
        }
        Ok(qs)
    }
}

pub fn query_operator(qop: &str) -> QueryOpResult {
    match &qop[..] {
        "$eq" => Ok("="),
        "$ne" => Ok("!="),
        "$gt" => Ok(">"),
        "$lt" => Ok("<"),
        "$gte" => Ok(">="),
        "$lte" => Ok("<="),
        "$in" => Ok("IN"),
        "$nin" => Ok("NOT IN"),
        "$notnull" => Ok("IS NOT NULL"),
        "$null" => Ok("IS NULL"),
         _ => Err(format!("operator {} not found", qop)),
    }
}

fn collect_params(v: &Vec<Params>, collect_values: bool) -> Vec<String> {
    let mut pid: i32 = 0;
    v.iter()
        .map(|param| {
            pid = pid + 1;
            let p = param.clone();
            let result = match p.v.contains(".") {
                true => {
                    let value_splited = p.v.split(".").collect::<Vec<&str>>();
                    let operator = match query_operator(value_splited[0]) {
                        Ok(op) => op,
                        _ => "operator not found"
                    };
                    (operator, value_splited[1])
                },
                _ => ("=", p.v.as_str())
            };
            if collect_values {
                format!("{}", result.1)
            } else {
                format!("{}{}${}", p.k, result.0, pid)
            }
        })
        .collect()
}

// Get QueryString and return chunck WHERE statement with values
pub fn ext_where(qs: QueryString) -> WhereResult {
    let where_syntax: String;
    let ref iter_params = qs.query;
    let where_values = collect_params(iter_params, true);
    let where_fields = collect_params(iter_params, false);

    if where_fields.len() > 1 {
        where_syntax = format!("WHERE {}", where_fields.join(" AND "));
    } else {
        where_syntax = format!("WHERE {}", where_fields.join(" "));
    }

    Ok(WhereStructResult {
        sql: where_syntax,
        values: where_values
    })
}

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

    #[test]
    fn get_opetators() {
        use std::collections::HashMap;

        let mut test_cases = HashMap::new();
        test_cases.insert("$eq", "=");
        test_cases.insert("$ne", "!=");
        test_cases.insert("$gt", ">");
        test_cases.insert("$gte", ">=");
        test_cases.insert("$lt", "<");
        test_cases.insert("$lte", "<=");
        test_cases.insert("$in", "IN");
        test_cases.insert("$nin", "NOT IN");
        test_cases.insert("$notnull", "IS NOT NULL");
        test_cases.insert("$null", "IS NULL");

        for (op, expected) in &test_cases {
            match query_operator(&op.to_string()) {
                Ok(x) => assert_eq!(expected.to_string(), x),
                Err(e) => assert_eq!("", e)
            }
        }
    }

    #[test]
    fn get_opetators_error() {
        let invalid = "!tn".to_string();
        match query_operator(&invalid) {
            Ok(_) => println!("no result"),
            Err(e) => assert_eq!(format!("operator {} not found", invalid), e)
        }
    }

    #[test]
    fn where_by_request_one_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1".to_string());
        assert_eq!(result.values, vec!["5".to_string()])
    }

    #[test]
    fn where_by_request_n_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$ne.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id!=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_invalid_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$nt.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        match ext_where(qs) {
            Err(e) => assert_eq!(e, "operator $nt not found"),
            Ok(_) => println!("no result")
        }
    }
}
<|endoftext|>


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

use raft::raftpb::{Entry, Snapshot};
use std::collections::VecDeque;

// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
#[derive(Debug, PartialEq)]
pub struct Unstable {
    // the incoming unstable snapshot, if any.
    snapshot: Option<Box<Snapshot>>,
    // all entries that have not yet been written to storage.
    entries: VecDeque<Entry>,
    offset: u64,
}

impl Unstable {
    // maybe_first_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_first_index(&self) -> Option<u64> {
        self.snapshot
            .as_ref()
            .map_or(None, |snap| Some(snap.get_metadata().get_index() + 1))
    }

    // maybe_last_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_last_index(&self) -> Option<u64> {
        match self.entries.len() {
            0 => {
                self.snapshot
                    .as_ref()
                    .map_or(None, |snap| Some(snap.get_metadata().get_index()))
            }
            len => Some(self.offset + len as u64 - 1),
        }
    }

    // maybe_term returns the term of the entry at index idx, if there
    // is any.
    fn maybe_term(&self, idx: u64) -> Option<u64> {
        if idx < self.offset {
            if self.snapshot.is_none() {
                return None;
            }

            let meta = self.snapshot.as_ref().unwrap().get_metadata().clone();
            if idx == meta.get_index() {
                return Some(meta.get_term());
            }
            return None;
        }
        match self.maybe_last_index() {
            None => None,
            Some(last) => {
                if idx > last {
                    return None;
                }
                Some(self.entries[(idx - self.offset) as usize].get_Term())
            }
        }
    }

    fn stable_to(&mut self, idx: u64, term: u64) {
        let t = self.maybe_term(idx);
        if t.is_none() {
            return;
        }

        if t.unwrap() == term && idx >= self.offset {
            let start = idx + 1 - self.offset;
            for _ in 0..start {
                self.entries.pop_front();
            }
            self.offset = idx + 1;
        }
    }

    fn stable_snap_to(&mut self, idx: u64) {
        if self.snapshot.is_none() {
            return;
        }
        if idx == self.snapshot.as_ref().unwrap().get_metadata().get_index() {
            self.snapshot = None;
        }
    }

    fn restore(&mut self, snap: Snapshot) {
        self.entries.clear();
        self.offset = snap.get_metadata().get_index() + 1;
        self.snapshot = Some(Box::new(snap));
    }

    fn truncate_and_append(&mut self, ents: &[Entry]) {
        let after = ents[0].get_Index() - 1;
        if after == self.offset + self.entries.len() as u64 - 1 {
            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else if after < self.offset {
            // The log is being truncated to before our current offset
            // portion, so set the offset and replace the entries
            self.offset = after + 1;
            self.entries.clear();

            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else {
            // truncate to after and copy to self.entries
            // then append
            let off = self.offset.clone();
            let cut_ents = self.cut_slice(off, after + 1);
            self.entries.clear();
            for e in cut_ents {
                self.entries.push_back(e);
            }

            for e in ents {
                self.entries.push_back(e.clone());
            }
        }
    }

    fn cut_slice(&mut self, lo: u64, hi: u64) -> Vec<Entry> {
        self.must_check_outofbounds(lo, hi);
        let l = lo as usize;
        let h = hi as usize;
        let off = self.offset as usize;
        return self.entries.drain(l - off..h - off).map(|e| e).collect();
    }

    fn must_check_outofbounds(&self, lo: u64, hi: u64) {
        if lo > hi {
            panic!("invalid unstable.slice {} > {}", lo, hi)
        }
        let upper = self.offset + self.entries.len() as u64;
        if lo < self.offset || hi > upper {
            panic!("unstable.slice[{}, {}] out of bound[{}, {}]",
                   lo,
                   hi,
                   self.offset,
                   upper)
        }
    }
}

#[cfg(test)]
mod test {
    use raft::raftpb::{Entry, Snapshot};
    use raft::log_unstable::Unstable;
    use std::collections::VecDeque;

    fn new_entry(index: u64, term: u64) -> Entry {
        let mut e = Entry::new();
        e.set_Term(term);
        e.set_Index(index);
        e
    }

    fn new_snapshot(index: u64, term: u64) -> Snapshot {
        use raft::raftpb::{SnapshotMetadata, Snapshot};
        let mut snap = Snapshot::new();
        let mut meta = SnapshotMetadata::new();
        meta.set_index(index);
        meta.set_term(term);
        snap.set_metadata(meta);
        snap
    }

    #[test]
    fn test_maybe_first_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            // no snapshot
            (Some(new_entry(5,1)), 5, None, false, 0),
            (None, 0, None, false, 0),
            // has snapshot
            (Some(new_entry(5, 1)), 5, Some(new_snapshot(4,1)), true, 5),
            (None, 5, Some(new_snapshot(4,1)), true, 5),
        ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(VecDeque::new(), |entry| {
                    vec![entry].into_iter().collect::<VecDeque<Entry>>()
                }),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_first_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_last_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            (Some(new_entry(5,1)), 5, None, true, 5),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), true, 5),
            // last in snapshot
            (None, 5, Some(new_snapshot(4,1)), true, 4),
            // empty unstable
            (None, 0, None, false, 0),
       ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(VecDeque::new(), |entry| {
                    vec![entry].into_iter().collect::<VecDeque<Entry>>()
                }),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_last_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_term() {
        // entry, offset, snap, index, wok, wterm
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, u64, bool, u64)> = vec![
            // term from entries
            (Some(new_entry(5,1)), 5, None, 5, true, 1),
            (Some(new_entry(5,1)), 5, None, 6, false, 0),
            (Some(new_entry(5,1)), 5, None, 4, false, 0),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 5, true, 1),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 6, false, 0),
            // term from snapshot
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 5, Some(new_snapshot(4,1)), 5, false, 0),
            (None, 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 0, None, 5, false, 0),
       ];

        for (entries, offset, snapshot, index, wok, wterm) in tests {
            let u = Unstable {
                entries: entries.map_or(VecDeque::new(), |entry| {
                    vec![entry].into_iter().collect::<VecDeque<Entry>>()
                }),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let term = u.maybe_term(index);
            match term {
                None => assert!(!wok),
                Some(term) => assert_eq!(term, wterm),
            }
        }
    }

    #[test]
    fn test_restore() {
        let mut u = Unstable {
            entries: vec![new_entry(5, 1)].into_iter().collect::<VecDeque<Entry>>(),
            offset: 5,
            snapshot: Some(Box::new(new_snapshot(4, 1))),
        };

        let s = new_snapshot(6, 2);
        u.restore(s.clone());

        assert_eq!(u.offset, s.get_metadata().get_index() + 1);
        assert_eq!(u.entries.len(), 0);
        assert_eq!(*u.snapshot.unwrap(), s);
    }

    #[test]
    fn test_stable_to() {
        // entries, offset, snap, index, term, woffset, wlen
        let tests: Vec<(Vec<Entry>, u64, Option<Snapshot>, u64, u64, u64, usize)> = vec![
            (vec![], 0, None, 5, 1, 0, 0),
            // stable to the first entry
            (vec![new_entry(5,1)], 5, None, 5, 1, 6, 0),
            (vec![new_entry(5,1), new_entry(6, 0)], 5, None, 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, None, 6, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,1)], 5, None, 4, 1, 5, 1),
            (vec![new_entry(5,1)], 5, None, 4, 2, 5, 1),
            // with snapshot
            // stable to the first entry
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 0),
            // stable to the first entry
            (vec![new_entry(5,1), new_entry(6,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, Some(new_snapshot(5,1)), 6, 1, 5, 1),
            // stable to snapshot
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 4, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,2)], 5, Some(new_snapshot(4,2)), 4, 1, 5, 1),
       ];

        for (entries, offset, snapshot, index, term, woffset, wlen) in tests {
            let mut u = Unstable {
                entries: entries.into_iter().collect::<VecDeque<Entry>>(),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            u.stable_to(index, term);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries.len(), wlen);
        }
    }

    #[test]
    fn test_truncate_and_append() {
        // entries, offset, snap, to_append, woffset, wentries
        let tests: Vec<(Vec<Entry>,
                        u64,
                        Option<Snapshot>,
                        Vec<Entry>,
                        u64,
                        Vec<Entry>)> = vec![
            // replace to the end
            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(6, 1), new_entry(7, 1)],
                    5, vec![new_entry(5,1), new_entry(6,1), new_entry(7,1)]),

            // replace to unstable entries
           (vec![new_entry(5, 1)], 5, None,
               vec![new_entry(5, 2), new_entry(6, 2)],
                   5, vec![new_entry(5, 2), new_entry(6, 2)]),

            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(4, 2), new_entry(5, 2), new_entry(6, 2)],
                    4, vec![new_entry(4,2), new_entry(5, 2), new_entry(6, 2)]),

            // truncate existing entries and append
           (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
               vec![new_entry(6, 2)],
                   5, vec![new_entry(5, 1), new_entry(6, 2)]),

            (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
                vec![new_entry(7, 2), new_entry(8, 2)],
                    5, vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 2), new_entry(8, 2)]),
      ];

        for (entries, offset, snapshot, to_append, woffset, wentries) in tests {
            let mut u = Unstable {
                entries: entries.into_iter().collect::<VecDeque<Entry>>(),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            u.truncate_and_append(&to_append);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries, wentries.into_iter().collect::<VecDeque<Entry>>());
        }
    }
}
<commit_msg>Tiny clean up<commit_after>#![allow(dead_code)]

use raft::raftpb::{Entry, Snapshot};
use std::collections::VecDeque;

// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
#[derive(Debug, PartialEq)]
pub struct Unstable {
    // the incoming unstable snapshot, if any.
    snapshot: Option<Box<Snapshot>>,
    // all entries that have not yet been written to storage.
    entries: VecDeque<Entry>,
    offset: u64,
}

impl Unstable {
    // maybe_first_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_first_index(&self) -> Option<u64> {
        self.snapshot
            .as_ref()
            .map_or(None, |snap| Some(snap.get_metadata().get_index() + 1))
    }

    // maybe_last_index returns the last index if it has at least one
    // unstable entry or snapshot.
    fn maybe_last_index(&self) -> Option<u64> {
        match self.entries.len() {
            0 => {
                self.snapshot
                    .as_ref()
                    .map_or(None, |snap| Some(snap.get_metadata().get_index()))
            }
            len => Some(self.offset + len as u64 - 1),
        }
    }

    // maybe_term returns the term of the entry at index idx, if there
    // is any.
    fn maybe_term(&self, idx: u64) -> Option<u64> {
        if idx < self.offset {
            if self.snapshot.is_none() {
                return None;
            }

            let meta = self.snapshot.as_ref().unwrap().get_metadata().clone();
            if idx == meta.get_index() {
                return Some(meta.get_term());
            }
            return None;
        }
        match self.maybe_last_index() {
            None => None,
            Some(last) => {
                if idx > last {
                    return None;
                }
                Some(self.entries[(idx - self.offset) as usize].get_Term())
            }
        }
    }

    fn stable_to(&mut self, idx: u64, term: u64) {
        let t = self.maybe_term(idx);
        if t.is_none() {
            return;
        }

        if t.unwrap() == term && idx >= self.offset {
            let start = idx + 1 - self.offset;
            for _ in 0..start {
                self.entries.pop_front();
            }
            self.offset = idx + 1;
        }
    }

    fn stable_snap_to(&mut self, idx: u64) {
        if self.snapshot.is_none() {
            return;
        }
        if idx == self.snapshot.as_ref().unwrap().get_metadata().get_index() {
            self.snapshot = None;
        }
    }

    fn restore(&mut self, snap: Snapshot) {
        self.entries.clear();
        self.offset = snap.get_metadata().get_index() + 1;
        self.snapshot = Some(Box::new(snap));
    }

    fn truncate_and_append(&mut self, ents: &[Entry]) {
        let after = ents[0].get_Index() - 1;
        if after == self.offset + self.entries.len() as u64 - 1 {
            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else if after < self.offset {
            // The log is being truncated to before our current offset
            // portion, so set the offset and replace the entries
            self.offset = after + 1;
            self.entries.clear();

            for e in ents {
                self.entries.push_back(e.clone());
            }
        } else {
            // truncate to after and copy to self.entries
            // then append
            let off = self.offset.clone();
            let cut_ents = self.cut_slice(off, after + 1);
            self.entries.clear();
            for e in cut_ents {
                self.entries.push_back(e);
            }

            for e in ents {
                self.entries.push_back(e.clone());
            }
        }
    }

    fn cut_slice(&mut self, lo: u64, hi: u64) -> Vec<Entry> {
        self.must_check_outofbounds(lo, hi);
        let l = lo as usize;
        let h = hi as usize;
        let off = self.offset as usize;
        return self.entries.drain(l - off..h - off).map(|e| e).collect();
    }

    fn must_check_outofbounds(&self, lo: u64, hi: u64) {
        if lo > hi {
            panic!("invalid unstable.slice {} > {}", lo, hi)
        }
        let upper = self.offset + self.entries.len() as u64;
        if lo < self.offset || hi > upper {
            panic!("unstable.slice[{}, {}] out of bound[{}, {}]",
                   lo,
                   hi,
                   self.offset,
                   upper)
        }
    }
}

#[cfg(test)]
mod test {
    use raft::raftpb::{Entry, Snapshot};
    use raft::log_unstable::Unstable;
    use std::collections::VecDeque;

    fn new_entry(index: u64, term: u64) -> Entry {
        let mut e = Entry::new();
        e.set_Term(term);
        e.set_Index(index);
        e
    }

    fn new_snapshot(index: u64, term: u64) -> Snapshot {
        use raft::raftpb::{SnapshotMetadata, Snapshot};
        let mut snap = Snapshot::new();
        let mut meta = SnapshotMetadata::new();
        meta.set_index(index);
        meta.set_term(term);
        snap.set_metadata(meta);
        snap
    }

    #[test]
    fn test_maybe_first_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            // no snapshot
            (Some(new_entry(5,1)), 5, None, false, 0),
            (None, 0, None, false, 0),
            // has snapshot
            (Some(new_entry(5, 1)), 5, Some(new_snapshot(4,1)), true, 5),
            (None, 5, Some(new_snapshot(4,1)), true, 5),
        ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(VecDeque::new(), |entry| {
                    vec![entry].into_iter().collect::<VecDeque<Entry>>()
                }),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_first_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_last_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            (Some(new_entry(5,1)), 5, None, true, 5),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), true, 5),
            // last in snapshot
            (None, 5, Some(new_snapshot(4,1)), true, 4),
            // empty unstable
            (None, 0, None, false, 0),
       ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(VecDeque::new(), |entry| {
                    vec![entry].into_iter().collect::<VecDeque<Entry>>()
                }),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_last_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_term() {
        // entry, offset, snap, index, wok, wterm
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, u64, bool, u64)> = vec![
            // term from entries
            (Some(new_entry(5,1)), 5, None, 5, true, 1),
            (Some(new_entry(5,1)), 5, None, 6, false, 0),
            (Some(new_entry(5,1)), 5, None, 4, false, 0),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 5, true, 1),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 6, false, 0),
            // term from snapshot
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 5, Some(new_snapshot(4,1)), 5, false, 0),
            (None, 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 0, None, 5, false, 0),
       ];

        for (entries, offset, snapshot, index, wok, wterm) in tests {
            let u = Unstable {
                entries: entries.map_or(VecDeque::new(), |entry| {
                    vec![entry].into_iter().collect::<VecDeque<Entry>>()
                }),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let term = u.maybe_term(index);
            match term {
                None => assert!(!wok),
                Some(term) => assert_eq!(term, wterm),
            }
        }
    }

    #[test]
    fn test_restore() {
        let mut u = Unstable {
            entries: vec![new_entry(5, 1)].into_iter().collect::<VecDeque<Entry>>(),
            offset: 5,
            snapshot: Some(Box::new(new_snapshot(4, 1))),
        };

        let s = new_snapshot(6, 2);
        u.restore(s.clone());

        assert_eq!(u.offset, s.get_metadata().get_index() + 1);
        assert_eq!(u.entries.len(), 0);
        assert_eq!(*u.snapshot.unwrap(), s);
    }

    #[test]
    fn test_stable_to() {
        // entries, offset, snap, index, term, woffset, wlen
        let tests: Vec<(Vec<Entry>, u64, Option<Snapshot>, u64, u64, u64, usize)> = vec![
            (vec![], 0, None, 5, 1, 0, 0),
            // stable to the first entry
            (vec![new_entry(5,1)], 5, None, 5, 1, 6, 0),
            (vec![new_entry(5,1), new_entry(6, 0)], 5, None, 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, None, 6, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,1)], 5, None, 4, 1, 5, 1),
            (vec![new_entry(5,1)], 5, None, 4, 2, 5, 1),
            // with snapshot
            // stable to the first entry
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 0),
            // stable to the first entry
            (vec![new_entry(5,1), new_entry(6,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, Some(new_snapshot(5,1)), 6, 1, 5, 1),
            // stable to snapshot
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 4, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,2)], 5, Some(new_snapshot(4,2)), 4, 1, 5, 1),
       ];

        for (entries, offset, snapshot, index, term, woffset, wlen) in tests {
            let mut u = Unstable {
                entries: entries.into_iter().collect::<VecDeque<Entry>>(),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            u.stable_to(index, term);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries.len(), wlen);
        }
    }

    #[test]
    fn test_truncate_and_append() {
        // entries, offset, snap, to_append, woffset, wentries
        let tests: Vec<(Vec<Entry>,
                        u64,
                        Option<Snapshot>,
                        Vec<Entry>,
                        u64,
                        Vec<Entry>)> = vec![
            // replace to the end
            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(6, 1), new_entry(7, 1)],
                    5, vec![new_entry(5,1), new_entry(6,1), new_entry(7,1)]),

            // replace to unstable entries
           (vec![new_entry(5, 1)], 5, None,
               vec![new_entry(5, 2), new_entry(6, 2)],
                   5, vec![new_entry(5, 2), new_entry(6, 2)]),

            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(4, 2), new_entry(5, 2), new_entry(6, 2)],
                    4, vec![new_entry(4,2), new_entry(5, 2), new_entry(6, 2)]),

            // truncate existing entries and append
           (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
               vec![new_entry(6, 2)],
                   5, vec![new_entry(5, 1), new_entry(6, 2)]),

            (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
                vec![new_entry(7, 2), new_entry(8, 2)],
                    5, vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 2), new_entry(8, 2)]),
      ];

        for (entries, offset, snapshot, to_append, woffset, wentries) in tests {
            let mut u = Unstable {
                entries: entries.into_iter().collect::<VecDeque<Entry>>(),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            u.truncate_and_append(&to_append);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries, wentries.into_iter().collect::<VecDeque<Entry>>());
        }
    }
}
<|endoftext|>


<commit_before>struct Tup (f64,);
struct GenTup<T>(T,);

// impl of Tup
impl Tup {
    // Borrowing a ref (val) requires lifelines
    fn value<'a>(&'a self) -> &'a f64 {
        let &Tup ( ref val ) = self;

        val
    }
}

// impl of GenTup for a generic type `T`
impl <T> GenTup<T> {
    fn value<'a>(&'a self) -> &'a T {
        let &GenTup (ref val) = self;

        val
    }
}

fn main() {
    let x = Tup(3.0);
    let y = GenTup(3i32);

    println!("{}, {}", x.value(), y.value());
}

<commit_msg>Elide lifetimes in `generics/implementation`<commit_after>struct Tup (f64,);
struct GenTup<T>(T,);

// impl of Tup
impl Tup {
    fn value(&self) -> &f64 {
        let &Tup ( ref val ) = self;

        val
    }
}

// impl of GenTup for a generic type `T`
impl <T> GenTup<T> {
    fn value(&self) -> &T {
        let &GenTup (ref val) = self;

        val
    }
}

fn main() {
    let x = Tup(3.0);
    let y = GenTup(3i32);

    println!("{}, {}", x.value(), y.value());
}

<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata;
use flac::metadata::{SeekPoint, VorbisComment};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata comments [options] <filename>
       metadata seektable <filename>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_filename: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  cmd_seektable: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    let mut index = 1;

    println!("Number of Comments: {}", vorbis_comment.comments.len());

    for (name, value) in &vorbis_comment.comments {
      println!("  {}: \"{}\" = {}", index, name, value);

      index += 1;
    }
  } else {
    if let Some(ref name) = args.flag_name {
      vorbis_comment.comments.get(name)
                             .map(|value| println!("{}", value));
    }
  }
}

fn print_seek_table(seek_points: &[SeekPoint]) {
  let mut count = 0;

  println!("Number of Seek Points: {}", seek_points.len());

  for seek_point in seek_points {
    println!("Seek Point #{}", count);
    println!("  Sample number: {}", seek_point.sample_number);
    println!("  Stream offset: {}", seek_point.stream_offset);
    println!("  Frame samples: {}", seek_point.frame_samples);
    count += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          print_vorbis_comments(v, &args)
        }
      }
      _                                    => continue,
    }
  }
}
<commit_msg>Hook SeekTable printing into CLI<commit_after>extern crate docopt;
extern crate flac;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ReadStream, Stream, StreamProducer};
use flac::metadata;
use flac::metadata::{SeekPoint, VorbisComment};

use std::env;
use std::fs::File;

const USAGE: &'static str = "
Usage: metadata streaminfo [options] <filename>
       metadata comments [options] <filename>
       metadata seektable <filename>
       metadata --help

Options:
  --block-size       Show both the max and min block size from StreamInfo.
  --frame-size       Show both the max and min frame size from StreamInfo.
  --sample-rate      Show the sample rate from StreamInfo.
  --channels         Show the number of channels from StreamInfo.
  --bits-per-sample  Show the size in bits for each sample from StreamInfo.
  --total-samples    Show total number of samples from StreamInfo.
  --md5              Show the MD5 signature from StreamInfo.
  --vendor           Show the vendor string from VorbisComment.
  --name=NAME        Show the comments matching the `NAME` from VorbisComment.
  -h, --help         Show this message.
";

#[derive(Debug, RustcDecodable)]
struct Arguments {
  arg_filename: String,
  cmd_streaminfo: bool,
  cmd_comments: bool,
  cmd_seektable: bool,
  flag_block_size: bool,
  flag_frame_size: bool,
  flag_sample_rate: bool,
  flag_channels: bool,
  flag_bits_per_sample: bool,
  flag_total_samples: bool,
  flag_md5: bool,
  flag_vendor: bool,
  flag_name: Option<String>,
}

macro_rules! format_print (
  ($format_str: expr, $opt_str: expr, $data: expr, $no_flag: expr) => (
    {
      println!($format_str, if $no_flag {
        $opt_str
      } else {
        ""
      }, $data);
    }
  );
);

fn print_stream_info<P>(stream: &Stream<P>, args: &Arguments)
 where P: StreamProducer {
  let info     = stream.info();
  let no_flags = (args.flag_block_size      || args.flag_frame_size    ||
                  args.flag_sample_rate     || args.flag_channels      ||
                  args.flag_bits_per_sample || args.flag_total_samples ||
                  args.flag_md5) == false;

  if no_flags || args.flag_block_size {
    println!("Minimum block size: {} samples", info.min_block_size);
    println!("Maximum block size: {} samples", info.max_block_size);
  }

  if no_flags || args.flag_frame_size {
    println!("Minimum frame size: {} bytes", info.min_frame_size);
    println!("Maximum frame size: {} bytes", info.max_frame_size);
  }

  if no_flags || args.flag_sample_rate {
    format_print!("{}{} Hz", "Sample rate: ", info.sample_rate, no_flags);
  }

  if no_flags || args.flag_channels {
    format_print!("{}{}", "Number of channels: ", info.channels, no_flags);
  }

  if no_flags || args.flag_bits_per_sample {
    format_print!("{}{}", "Bits per samples: ", info.bits_per_sample,
                                                no_flags);
  }

  if no_flags || args.flag_total_samples {
    format_print!("{}{}", "Total samples: ", info.total_samples, no_flags);
  }

  if no_flags || args.flag_md5 {
    let mut md5  = String::with_capacity(32);

    for byte in &info.md5_sum {
      let hex = format!("{:02x}", byte);

      md5.push_str(&hex);
    }

    format_print!("{}{}", "MD5 sum: ", md5, no_flags);
  }
}

fn print_vorbis_comments(vorbis_comment: &VorbisComment, args: &Arguments) {
  let no_flags  = (args.flag_vendor || args.flag_name.is_some()) == false;

  if no_flags || args.flag_vendor {
    format_print!("{}{}", "Vendor string: ", vorbis_comment.vendor_string,
                                             no_flags);
  }

  if no_flags {
    let mut index = 1;

    println!("Number of Comments: {}", vorbis_comment.comments.len());

    for (name, value) in &vorbis_comment.comments {
      println!("  {}: \"{}\" = {}", index, name, value);

      index += 1;
    }
  } else {
    if let Some(ref name) = args.flag_name {
      vorbis_comment.comments.get(name)
                             .map(|value| println!("{}", value));
    }
  }
}

fn print_seek_table(seek_points: &[SeekPoint]) {
  let mut count = 0;

  println!("Number of Seek Points: {}", seek_points.len());

  for seek_point in seek_points {
    println!("Seek Point #{}", count);
    println!("  Sample number: {}", seek_point.sample_number);
    println!("  Stream offset: {}", seek_point.stream_offset);
    println!("  Frame samples: {}", seek_point.frame_samples);
    count += 1;
  }
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  let stream = Stream::<ReadStream<File>>::from_file(&args.arg_filename)
                 .expect("Couldn't parse file");

  if args.cmd_streaminfo {
    print_stream_info(&stream, &args);
  }

  for meta in stream.metadata() {
    match meta.data {
      metadata::Data::VorbisComment(ref v) => {
        if args.cmd_comments {
          print_vorbis_comments(v, &args)
        }
      }
      metadata::Data::SeekTable(ref s)     => {
        if args.cmd_seektable {
          print_seek_table(s);
        }
      }
      _                                    => continue,
    }
  }
}
<|endoftext|>


<commit_before>extern crate timely;

use timely::dataflow::{InputHandle, ProbeHandle};
use timely::dataflow::operators::{Input, Filter, Probe};

fn main() {

    let mut args = std::env::args();
    args.next();
    let rate: usize = args.next().expect("Must specify rate").parse().expect("Rate must be an usize");
    let duration_s: usize = args.next().expect("Must specify duration_s").parse().expect("duration_s must be an usize");

    timely::execute_from_args(args, move |worker| {

        let index = worker.index();
        let peers = worker.peers();

        // re-synchronize all workers (account for start-up).
        timely::synchronization::Barrier::new(worker).wait();

        let timer = std::time::Instant::now();

        let mut input = InputHandle::new();
        let mut probe = ProbeHandle::new();

        // Create a dataflow that discards input data (just syncronizes).
        worker.dataflow(|scope| {
            scope
                .input_from(&mut input)     // read input.
                .filter(|_| false)          // do nothing.
                .probe_with(&mut probe);    // observe output.
        });

        let ns_per_request = 1_000_000_000 / rate;
        let mut insert_counter = index;           // counts up as we insert records.
        let mut retire_counter = index;           // counts up as we retire records.

        let mut inserted_ns = 0;

        // We repeatedly consult the elapsed time, and introduce any data now considered available.
        // At the same time, we observe the output and record which inputs are considered retired.

        let mut counts = vec![[0u64; 16]; 64];

        let counter_limit = rate * duration_s;
        while retire_counter < counter_limit {

            // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
            let elapsed = timer.elapsed();
            let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

            // Determine completed ns.
            let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0]);

            // Notice any newly-retired records.
            while ((retire_counter * ns_per_request) as u64) < acknowledged_ns && retire_counter < counter_limit {
                let requested_at = (retire_counter * ns_per_request) as u64;
                let latency_ns = elapsed_ns - requested_at;

                let count_index = latency_ns.next_power_of_two().trailing_zeros() as usize;
                let low_bits = ((elapsed_ns - requested_at) >> (count_index - 5)) & 0xF;
                counts[count_index][low_bits as usize] += 1;

                retire_counter += peers;
            }

            // Now, should we introduce more records before stepping the worker?
            // Three choices here:
            //
            //   1. Wait until previous batch acknowledged.
            //   2. Tick at most once every millisecond-ish.
            //   3. Geometrically increase outstanding batches.

            // Technique 1:
            // let target_ns = if acknowledged_ns >= inserted_ns { elapsed_ns } else { inserted_ns };

            // Technique 2:
            // let target_ns = elapsed_ns & !((1 << 20) - 1);

            // Technique 3:
            let scale = (inserted_ns - acknowledged_ns).next_power_of_two();
            let target_ns = elapsed_ns & !(scale - 1);

            // Common for each technique.
            if inserted_ns < target_ns {

                while ((insert_counter * ns_per_request) as u64) < target_ns {
                    input.send(insert_counter);
                    insert_counter += peers;
                }
                input.advance_to(target_ns);
                inserted_ns = target_ns;
            }

            worker.step();
        }

        // Report observed latency measurements.
        if index == 0 {

            let mut results = Vec::new();
            let total = counts.iter().map(|x| x.iter().sum::<u64>()).sum();
            let mut sum = 0;
            for index in (10 .. counts.len()).rev() {
                for sub in (0 .. 16).rev() {
                    if sum > 0 && sum < total {
                        let latency = (1 << (index-1)) + (sub << (index-5));
                        let fraction = (sum as f64) / (total as f64);
                        results.push((latency, fraction));
                    }
                    sum += counts[index][sub];
                }
            }
            for (latency, fraction) in results.drain(..).rev() {
                println!("{}\t{}", latency, fraction);
            }
        }

    }).unwrap();
}<commit_msg>Fix the target_ns calculation<commit_after>extern crate timely;

use timely::dataflow::{InputHandle, ProbeHandle};
use timely::dataflow::operators::{Input, Filter, Probe};

fn main() {

    let mut args = std::env::args();
    args.next();
    let rate: usize = args.next().expect("Must specify rate").parse().expect("Rate must be an usize");
    let duration_s: usize = args.next().expect("Must specify duration_s").parse().expect("duration_s must be an usize");

    timely::execute_from_args(args, move |worker| {

        let index = worker.index();
        let peers = worker.peers();

        // re-synchronize all workers (account for start-up).
        timely::synchronization::Barrier::new(worker).wait();

        let timer = std::time::Instant::now();

        let mut input = InputHandle::new();
        let mut probe = ProbeHandle::new();

        // Create a dataflow that discards input data (just syncronizes).
        worker.dataflow(|scope| {
            scope
                .input_from(&mut input)     // read input.
                .filter(|_| false)          // do nothing.
                .probe_with(&mut probe);    // observe output.
        });

        let ns_per_request = 1_000_000_000 / rate;
        let mut insert_counter = index;           // counts up as we insert records.
        let mut retire_counter = index;           // counts up as we retire records.

        let mut inserted_ns = 0;

        // We repeatedly consult the elapsed time, and introduce any data now considered available.
        // At the same time, we observe the output and record which inputs are considered retired.

        let mut counts = vec![[0u64; 16]; 64];

        let counter_limit = rate * duration_s;
        while retire_counter < counter_limit {

            // Open-loop latency-throughput test, parameterized by offered rate `ns_per_request`.
            let elapsed = timer.elapsed();
            let elapsed_ns = elapsed.as_secs() * 1_000_000_000 + (elapsed.subsec_nanos() as u64);

            // Determine completed ns.
            let acknowledged_ns: u64 = probe.with_frontier(|frontier| frontier[0]);

            // Notice any newly-retired records.
            while ((retire_counter * ns_per_request) as u64) < acknowledged_ns && retire_counter < counter_limit {
                let requested_at = (retire_counter * ns_per_request) as u64;
                let latency_ns = elapsed_ns - requested_at;

                let count_index = latency_ns.next_power_of_two().trailing_zeros() as usize;
                let low_bits = ((elapsed_ns - requested_at) >> (count_index - 5)) & 0xF;
                counts[count_index][low_bits as usize] += 1;

                retire_counter += peers;
            }

            // Now, should we introduce more records before stepping the worker?
            // Three choices here:
            //
            //   1. Wait until previous batch acknowledged.
            //   2. Tick at most once every millisecond-ish.
            //   3. Geometrically increase outstanding batches.

            // Technique 1:
            // let target_ns = if acknowledged_ns >= inserted_ns { elapsed_ns } else { inserted_ns };

            // Technique 2:
            // let target_ns = elapsed_ns & !((1 << 20) - 1);

            // Technique 3:
            let target_ns = {
                let delta: u64 = inserted_ns - acknowledged_ns;
                let bits = ::std::mem::size_of::<u64>() * 8 - delta.leading_zeros() as usize;
                let scale = ::std::cmp::max((1 << bits) / 4, 1024);
                elapsed_ns & !(scale - 1)
            };

            // Common for each technique.
            if inserted_ns < target_ns {

                while ((insert_counter * ns_per_request) as u64) < target_ns {
                    input.send(insert_counter);
                    insert_counter += peers;
                }
                input.advance_to(target_ns);
                inserted_ns = target_ns;
            }

            worker.step();
        }

        // Report observed latency measurements.
        if index == 0 {

            let mut results = Vec::new();
            let total = counts.iter().map(|x| x.iter().sum::<u64>()).sum();
            let mut sum = 0;
            for index in (10 .. counts.len()).rev() {
                for sub in (0 .. 16).rev() {
                    if sum > 0 && sum < total {
                        let latency = (1 << (index-1)) + (sub << (index-5));
                        let fraction = (sum as f64) / (total as f64);
                        results.push((latency, fraction));
                    }
                    sum += counts[index][sub];
                }
            }
            for (latency, fraction) in results.drain(..).rev() {
                println!("{}\t{}", latency, fraction);
            }
        }

    }).unwrap();
}
<|endoftext|>


<commit_before>use std::io::{Read, Cursor, Seek, SeekFrom, Write};
use std::fs::{OpenOptions, File};
use std::collections::HashMap;
use std::cell::RefCell;
use std::path::Path;
use std::sync::Arc;
use crc32c::*;

use blockchain::{block::*, index::*};

pub struct BlockStore {
    indexer: Arc<Indexer>,

    height: u64,
    blocks: HashMap<u64, Arc<SignedBlock>>,
    genesis_block: Option<Arc<SignedBlock>>,

    file: RefCell<File>,
    byte_pos_tail: u64
}

impl BlockStore {

    pub fn new(path: &Path, indexer: Arc<Indexer>) -> BlockStore {
        let (file, tail) = {
            let f = OpenOptions::new()
                                .create(true)
                                .read(true)
                                .append(true)
                                .open(path).unwrap();
            let m = f.metadata().unwrap();
            (f, m.len())
        };

        let height = indexer.get_chain_height();
        let mut store = BlockStore {
            indexer,

            height,
            blocks: HashMap::new(),
            genesis_block: None,

            file: RefCell::new(file),
            byte_pos_tail: tail
        };
        store.genesis_block = store.get(0);

        { // Initialize the cache
            let min = if height <= 100 { height } else { height - 100 };
            let max = min + 100;
            for height in min..max {
                if let Some(block) = store.get_from_disk(height) {
                    store.blocks.insert(height, Arc::new(block));
                } else {
                    break;
                }
            }
        }

        store
    }

    #[inline(always)]
    pub fn get_chain_height(&self) -> u64 {
        self.height
    }

    pub fn get(&self, height: u64) -> Option<Arc<SignedBlock>> {
        if height > self.height {
            return None
        } else if height == 0 {
            if let Some(ref block) = self.genesis_block {
                return Some(Arc::clone(block))
            }
        }
        if let Some(block) = self.blocks.get(&height) {
            Some(Arc::clone(block))
        } else {
            Some(Arc::new(self.get_from_disk(height)?))
        }
    }

    fn get_from_disk(&self, height: u64) -> Option<SignedBlock> {
        if height > self.height { return None }

        let pos = self.indexer.get_block_byte_pos(height)?;
        let mut f = self.file.borrow_mut();
        f.seek(SeekFrom::Start(pos)).unwrap();

        let (block_len, crc) = {
            let mut meta = [0u8; 8];
            f.read_exact(&mut meta).unwrap();
            let len = u32_from_buf!(meta, 0) as usize;
            let crc = u32_from_buf!(meta, 4);
            (len, crc)
        };

        let block_vec = {
            let mut buf = Vec::with_capacity(block_len);
            unsafe { buf.set_len(block_len); }
            f.read_exact(&mut buf).unwrap();
            assert_eq!(crc, crc32c(&buf));
            buf
        };

        let mut cursor = Cursor::<&[u8]>::new(&block_vec);
        let block = SignedBlock::decode_with_tx(&mut cursor).unwrap();
        Some(block)
    }

    pub fn insert(&mut self, block: SignedBlock) {
        assert_eq!(self.height + 1, block.height, "invalid block height");
        self.insert_raw(block);
    }

    pub fn insert_genesis(&mut self, block: SignedBlock) {
        assert_eq!(block.height, 0, "expected to be 0");
        assert!(self.genesis_block.is_none(), "expected genesis block to not exist");
        self.insert_raw(block.clone());
        self.genesis_block = Some(Arc::new(block));
    }

    fn insert_raw(&mut self, block: SignedBlock) {
        { // Write to disk
            let vec = &mut Vec::with_capacity(1048576);
            block.encode_with_tx(vec);
            let len = vec.len() as u32;
            let crc = crc32c(vec);

            let mut f = self.file.borrow_mut();
            {
                let mut buf = [0u8; 8];
                buf[0] = (len >> 24) as u8;
                buf[1] = (len >> 16) as u8;
                buf[2] = (len >> 8) as u8;
                buf[3] = len as u8;

                buf[4] = (crc >> 24) as u8;
                buf[5] = (crc >> 16) as u8;
                buf[6] = (crc >> 8) as u8;
                buf[7] = crc as u8;

                f.write_all(&buf).unwrap();
            }

            f.write_all(vec).unwrap();
            f.flush().unwrap();

            self.byte_pos_tail += (len as u64) + 8;
        }

        { // Update internal cache
            let height = block.height;
            self.height = height;
            let opt = self.blocks.insert(height, Arc::new(block));
            if self.blocks.len() > 100 {
                let b = self.blocks.remove(&(height - 100));
                debug_assert!(b.is_some(), "nothing removed from cache");
            }
            debug_assert!(opt.is_none(), "block already in the chain");
        }
    }
}
<commit_msg>Update the index chain height and block byte position<commit_after>use std::io::{Read, Cursor, Seek, SeekFrom, Write};
use std::fs::{OpenOptions, File};
use std::collections::HashMap;
use std::cell::RefCell;
use std::path::Path;
use std::sync::Arc;
use crc32c::*;

use blockchain::{block::*, index::*};

pub struct BlockStore {
    indexer: Arc<Indexer>,

    height: u64,
    blocks: HashMap<u64, Arc<SignedBlock>>,
    genesis_block: Option<Arc<SignedBlock>>,

    file: RefCell<File>,
    byte_pos_tail: u64
}

impl BlockStore {

    pub fn new(path: &Path, indexer: Arc<Indexer>) -> BlockStore {
        let (file, tail) = {
            let f = OpenOptions::new()
                                .create(true)
                                .read(true)
                                .append(true)
                                .open(path).unwrap();
            let m = f.metadata().unwrap();
            (f, m.len())
        };

        let height = indexer.get_chain_height();
        let mut store = BlockStore {
            indexer,

            height,
            blocks: HashMap::new(),
            genesis_block: None,

            file: RefCell::new(file),
            byte_pos_tail: tail
        };
        store.genesis_block = store.get(0);

        { // Initialize the cache
            let min = if height <= 100 { height } else { height - 100 };
            let max = min + 100;
            for height in min..max {
                if let Some(block) = store.get_from_disk(height) {
                    store.blocks.insert(height, Arc::new(block));
                } else {
                    break;
                }
            }
        }

        store
    }

    #[inline(always)]
    pub fn get_chain_height(&self) -> u64 {
        self.height
    }

    pub fn get(&self, height: u64) -> Option<Arc<SignedBlock>> {
        if height > self.height {
            return None
        } else if height == 0 {
            if let Some(ref block) = self.genesis_block {
                return Some(Arc::clone(block))
            }
        }
        if let Some(block) = self.blocks.get(&height) {
            Some(Arc::clone(block))
        } else {
            Some(Arc::new(self.get_from_disk(height)?))
        }
    }

    fn get_from_disk(&self, height: u64) -> Option<SignedBlock> {
        if height > self.height { return None }

        let pos = self.indexer.get_block_byte_pos(height)?;
        let mut f = self.file.borrow_mut();
        f.seek(SeekFrom::Start(pos)).unwrap();

        let (block_len, crc) = {
            let mut meta = [0u8; 8];
            f.read_exact(&mut meta).unwrap();
            let len = u32_from_buf!(meta, 0) as usize;
            let crc = u32_from_buf!(meta, 4);
            (len, crc)
        };

        let block_vec = {
            let mut buf = Vec::with_capacity(block_len);
            unsafe { buf.set_len(block_len); }
            f.read_exact(&mut buf).unwrap();
            assert_eq!(crc, crc32c(&buf));
            buf
        };

        let mut cursor = Cursor::<&[u8]>::new(&block_vec);
        let block = SignedBlock::decode_with_tx(&mut cursor).unwrap();
        Some(block)
    }

    pub fn insert(&mut self, block: SignedBlock) {
        assert_eq!(self.height + 1, block.height, "invalid block height");
        let byte_pos = self.byte_pos_tail;
        self.write_to_disk(&block);

        { // Update internal cache
            let height = block.height;
            self.height = height;
            self.indexer.set_block_byte_pos(height, byte_pos);
            self.indexer.set_chain_height(height);

            let opt = self.blocks.insert(height, Arc::new(block));
            if self.blocks.len() > 100 {
                let b = self.blocks.remove(&(height - 100));
                debug_assert!(b.is_some(), "nothing removed from cache");
            }
            debug_assert!(opt.is_none(), "block already in the chain");
        }
    }

    pub fn insert_genesis(&mut self, block: SignedBlock) {
        assert_eq!(block.height, 0, "expected to be 0");
        assert!(self.genesis_block.is_none(), "expected genesis block to not exist");
        self.write_to_disk(&block);
        self.genesis_block = Some(Arc::new(block));
        self.indexer.set_block_byte_pos(0, 0);
    }

    fn write_to_disk(&mut self, block: &SignedBlock) {
        let vec = &mut Vec::with_capacity(1048576);
        block.encode_with_tx(vec);
        let len = vec.len() as u32;
        let crc = crc32c(vec);

        let mut f = self.file.borrow_mut();
        {
            let mut buf = [0u8; 8];
            buf[0] = (len >> 24) as u8;
            buf[1] = (len >> 16) as u8;
            buf[2] = (len >> 8) as u8;
            buf[3] = len as u8;

            buf[4] = (crc >> 24) as u8;
            buf[5] = (crc >> 16) as u8;
            buf[6] = (crc >> 8) as u8;
            buf[7] = crc as u8;

            f.write_all(&buf).unwrap();
        }

        f.write_all(vec).unwrap();
        f.flush().unwrap();

        self.byte_pos_tail += (len as u64) + 8;
    }
}
<|endoftext|>