<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::{ParserSource, BasicSource, SeekableSource, LimitedSeekReader};

mod error;
mod event;
mod reader;
pub mod utils;

/// Warnings store.
#[derive(Default, Debug, Clone)]
pub struct Warnings(Vec<Warning>);

impl Warnings {
    /// Creates a new `Warnings`.
    pub fn new() -> Self {
        Default::default()
    }

    /// Add a warning.
    pub fn warn(&mut self, warning: Warning) {
        warn!("FBX binary parser warning: {}", warning);
        self.0.push(warning);
    }

    /// Returns the inner vector.
    pub fn inner(self) -> Vec<Warning> {
        self.0
    }
}

impl ::std::ops::Deref for Warnings {
    type Target = [Warning];

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// Parser of a FBX binary node.
pub trait Parser<R: ParserSource> {
    /// Returns the root parser.
    fn root_parser(&self) -> &RootParser<R>;
    /// Parses FBX from the given stream and returns the next event.
    fn next_event(&mut self) -> Result<Event<R>>;
    /// Skips to the end of the current node.
    ///
    /// Returns `Ok(true)` if the current node is skipped and closed,
    /// `Ok(false)` if no nodes are open (i.e. the parser is reading under implicit root node),
    /// `Err(err)` if error happened.
    fn skip_current_node(&mut self) -> Result<bool>;
    /// Creates subtree parser for the current node.
    fn subtree_parser(&mut self) -> SubtreeParser<R>;
}

/// 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 whole FBX with binary format.
#[derive(Debug)]
pub struct RootParser<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: Warnings,
    /// FBX version.
    fbx_version: Option<u32>,
    /// Open nodes stack.
    open_nodes: Vec<OpenNode>,
    /// Node name of the recent opened node.
    recent_node_name: Option<String>,
}

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

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

impl<R: ParserSource> RootParser<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) -> &[Warning] {
        &self.warnings
    }

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

    /// Returns the node name of the recent opened node.
    pub fn recent_node_name(&self) -> Option<&str> {
        self.recent_node_name.as_ref().map(String::as_str)
    }

    /// Returns the node name of the recent opened node with ownership.
    pub fn take_recent_node_name(&mut self) -> Option<String> {
        self.recent_node_name.take()
    }

    /// 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) {
        self.warnings.warn(warning);
        debug!("Parser: {:#?}", self);
    }

    /// Reads FBX header.
    fn read_fbx_header(&mut self) -> Result<EventBuilder> {
        let header = 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.
        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 = 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 = 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 {
            // Reuse node name buffer.
            self.recent_node_name = {
                // Take node name buffer inside the string if the buffer remains.
                // Create a new buffer if the buffer was already taken.
                let mut vecbuf = self.recent_node_name
                    .take()
                    .map(|s| {
                        // Get inner `Vec` of the string.
                        let mut v = s.into_bytes();
                        // Resize buffer.
                        // This reallocates only if the buffer is too small.
                        v.resize(header.bytelen_name as usize, 0);
                        v
                    })
                    .unwrap_or_else(|| vec![0; header.bytelen_name as usize]);
                // Read the node name into the buffer.
                self.source.read_exact(&mut vecbuf)?;
                // Covert the name into `String`.
                // If conversion failed, the buffer will be left empty.
                // This is ok because no more node events would be loaded and
                // the buffer would no longer be used.
                Some(String::from_utf8(vecbuf).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 { 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("`RootParser::skip_attributes()` is called but no nodes are open")
            .attributes_end;
        self.source.skip_to(attributes_end)
    }
}

impl<R: ParserSource> Parser<R> for RootParser<R> {
    fn root_parser(&self) -> &RootParser<R> {
        self
    }

    fn next_event(&mut self) -> Result<Event<R>> {
        let builder = match 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(builder?.build(self))
    }

    fn skip_current_node(&mut self) -> Result<bool> {
        if let Some(end) = self.open_nodes.pop().map(|v| v.end) {
            self.source.skip_to(end)?;
            self.state = Ok(State::NodeEnded);
            Ok(true)
        } else {
            Ok(false)
        }
    }

    fn subtree_parser(&mut self) -> SubtreeParser<R> {
        SubtreeParser::new(self)
    }
}

/// Pull parser for a subtree of the FBX binary.
pub struct SubtreeParser<'a, R: 'a> {
    /// Root parser.
    root_parser: &'a mut RootParser<R>,
    /// Initial depth.
    ///
    /// Depth of the implicit root node is `0`.
    initial_depth: usize,
}

impl<'a, R: 'a + ParserSource> SubtreeParser<'a, R> {
    /// Creates a new `SubtreeParser`.
    pub fn new(root_parser: &'a mut RootParser<R>) -> Self {
        let initial_depth = root_parser.num_open_nodes();
        SubtreeParser {
            root_parser: root_parser,
            initial_depth: initial_depth,
        }
    }

    /// Checks if the subtree parser can emit more events.
    ///
    /// Returns `Ok(())` if more events can be read,
    /// `Err(Error::Finished)` if the subtree is all read,
    /// `Err(_)` if error happened.
    fn check_finished(&self) -> Result<()> {
        if self.is_finished()? {
            Err(Error::Finished)
        } else {
            Ok(())
        }
    }

    /// Checks if the subtree parser finished reading events.
    fn is_finished(&self) -> Result<bool> {
        if let Some(err) = self.root_parser.error() {
            return Err(err.clone());
        }
        Ok(self.root_parser.num_open_nodes() < self.initial_depth)
    }

    /// Skip to the end of the subtree parser's readable range.
    ///
    /// Note that this is not intended to called for `SubtreeParser` reading implicit root node.
    /// If the subtree parser can read whole data, the parser skips all events including `FbxEnd`
    /// and returns `Err(Error::Finished)`.
    pub fn skip_to_end(self) -> Result<()> {
        if self.is_finished()? {
            return Ok(());
        }
        self.root_parser.open_nodes.truncate(self.initial_depth);
        if let Some(end) = self.root_parser.open_nodes.pop().map(|v| v.end) {
            self.root_parser.source.skip_to(end)?;
            self.root_parser.state = Ok(State::NodeEnded);
            Ok(())
        } else {
            self.root_parser.state = Err(Error::Finished);
            Err(Error::Finished)
        }
    }
}

impl<'a, R: 'a + ParserSource> Parser<R> for SubtreeParser<'a, R> {
    fn root_parser(&self) -> &RootParser<R> {
        self.root_parser
    }

    fn next_event(&mut self) -> Result<Event<R>> {
        self.check_finished()?;
        self.root_parser.next_event()
    }

    fn skip_current_node(&mut self) -> Result<bool> {
        self.check_finished()?;
        self.root_parser.skip_current_node()
    }

    fn subtree_parser(&mut self) -> SubtreeParser<R> {
        SubtreeParser::new(self.root_parser)
    }
}

impl<'a, R: ParserSource, P: Parser<R>> Parser<R> for &'a mut P {
    fn root_parser(&self) -> &RootParser<R> {
        (**self).root_parser()
    }

    fn next_event(&mut self) -> Result<Event<R>> {
        (**self).next_event()
    }

    fn skip_current_node(&mut self) -> Result<bool> {
        (**self).skip_current_node()
    }

    fn subtree_parser(&mut self) -> SubtreeParser<R> {
        (**self).subtree_parser()
    }
}
<commit_msg>Rename `check_finished()` to `ensure_not_finished()`<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::{ParserSource, BasicSource, SeekableSource, LimitedSeekReader};

mod error;
mod event;
mod reader;
pub mod utils;

/// Warnings store.
#[derive(Default, Debug, Clone)]
pub struct Warnings(Vec<Warning>);

impl Warnings {
    /// Creates a new `Warnings`.
    pub fn new() -> Self {
        Default::default()
    }

    /// Add a warning.
    pub fn warn(&mut self, warning: Warning) {
        warn!("FBX binary parser warning: {}", warning);
        self.0.push(warning);
    }

    /// Returns the inner vector.
    pub fn inner(self) -> Vec<Warning> {
        self.0
    }
}

impl ::std::ops::Deref for Warnings {
    type Target = [Warning];

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// Parser of a FBX binary node.
pub trait Parser<R: ParserSource> {
    /// Returns the root parser.
    fn root_parser(&self) -> &RootParser<R>;
    /// Parses FBX from the given stream and returns the next event.
    fn next_event(&mut self) -> Result<Event<R>>;
    /// Skips to the end of the current node.
    ///
    /// Returns `Ok(true)` if the current node is skipped and closed,
    /// `Ok(false)` if no nodes are open (i.e. the parser is reading under implicit root node),
    /// `Err(err)` if error happened.
    fn skip_current_node(&mut self) -> Result<bool>;
    /// Creates subtree parser for the current node.
    fn subtree_parser(&mut self) -> SubtreeParser<R>;
}

/// 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 whole FBX with binary format.
#[derive(Debug)]
pub struct RootParser<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: Warnings,
    /// FBX version.
    fbx_version: Option<u32>,
    /// Open nodes stack.
    open_nodes: Vec<OpenNode>,
    /// Node name of the recent opened node.
    recent_node_name: Option<String>,
}

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

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

impl<R: ParserSource> RootParser<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) -> &[Warning] {
        &self.warnings
    }

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

    /// Returns the node name of the recent opened node.
    pub fn recent_node_name(&self) -> Option<&str> {
        self.recent_node_name.as_ref().map(String::as_str)
    }

    /// Returns the node name of the recent opened node with ownership.
    pub fn take_recent_node_name(&mut self) -> Option<String> {
        self.recent_node_name.take()
    }

    /// 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) {
        self.warnings.warn(warning);
        debug!("Parser: {:#?}", self);
    }

    /// Reads FBX header.
    fn read_fbx_header(&mut self) -> Result<EventBuilder> {
        let header = 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.
        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 = 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 = 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 {
            // Reuse node name buffer.
            self.recent_node_name = {
                // Take node name buffer inside the string if the buffer remains.
                // Create a new buffer if the buffer was already taken.
                let mut vecbuf = self.recent_node_name
                    .take()
                    .map(|s| {
                        // Get inner `Vec` of the string.
                        let mut v = s.into_bytes();
                        // Resize buffer.
                        // This reallocates only if the buffer is too small.
                        v.resize(header.bytelen_name as usize, 0);
                        v
                    })
                    .unwrap_or_else(|| vec![0; header.bytelen_name as usize]);
                // Read the node name into the buffer.
                self.source.read_exact(&mut vecbuf)?;
                // Covert the name into `String`.
                // If conversion failed, the buffer will be left empty.
                // This is ok because no more node events would be loaded and
                // the buffer would no longer be used.
                Some(String::from_utf8(vecbuf).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 { 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("`RootParser::skip_attributes()` is called but no nodes are open")
            .attributes_end;
        self.source.skip_to(attributes_end)
    }
}

impl<R: ParserSource> Parser<R> for RootParser<R> {
    fn root_parser(&self) -> &RootParser<R> {
        self
    }

    fn next_event(&mut self) -> Result<Event<R>> {
        let builder = match 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(builder?.build(self))
    }

    fn skip_current_node(&mut self) -> Result<bool> {
        if let Some(end) = self.open_nodes.pop().map(|v| v.end) {
            self.source.skip_to(end)?;
            self.state = Ok(State::NodeEnded);
            Ok(true)
        } else {
            Ok(false)
        }
    }

    fn subtree_parser(&mut self) -> SubtreeParser<R> {
        SubtreeParser::new(self)
    }
}

/// Pull parser for a subtree of the FBX binary.
pub struct SubtreeParser<'a, R: 'a> {
    /// Root parser.
    root_parser: &'a mut RootParser<R>,
    /// Initial depth.
    ///
    /// Depth of the implicit root node is `0`.
    initial_depth: usize,
}

impl<'a, R: 'a + ParserSource> SubtreeParser<'a, R> {
    /// Creates a new `SubtreeParser`.
    pub fn new(root_parser: &'a mut RootParser<R>) -> Self {
        let initial_depth = root_parser.num_open_nodes();
        SubtreeParser {
            root_parser: root_parser,
            initial_depth: initial_depth,
        }
    }

    /// Checks if the subtree parser can emit more events.
    ///
    /// Returns `Ok(())` if more events can be read,
    /// `Err(Error::Finished)` if the subtree is all read,
    /// `Err(_)` if error happened.
    fn ensure_not_finished(&self) -> Result<()> {
        if self.is_finished()? {
            Err(Error::Finished)
        } else {
            Ok(())
        }
    }

    /// Checks if the subtree parser finished reading events.
    fn is_finished(&self) -> Result<bool> {
        if let Some(err) = self.root_parser.error() {
            return Err(err.clone());
        }
        Ok(self.root_parser.num_open_nodes() < self.initial_depth)
    }

    /// Skip to the end of the subtree parser's readable range.
    ///
    /// Note that this is not intended to called for `SubtreeParser` reading implicit root node.
    /// If the subtree parser can read whole data, the parser skips all events including `FbxEnd`
    /// and returns `Err(Error::Finished)`.
    pub fn skip_to_end(self) -> Result<()> {
        if self.is_finished()? {
            return Ok(());
        }
        self.root_parser.open_nodes.truncate(self.initial_depth);
        if let Some(end) = self.root_parser.open_nodes.pop().map(|v| v.end) {
            self.root_parser.source.skip_to(end)?;
            self.root_parser.state = Ok(State::NodeEnded);
            Ok(())
        } else {
            self.root_parser.state = Err(Error::Finished);
            Err(Error::Finished)
        }
    }
}

impl<'a, R: 'a + ParserSource> Parser<R> for SubtreeParser<'a, R> {
    fn root_parser(&self) -> &RootParser<R> {
        self.root_parser
    }

    fn next_event(&mut self) -> Result<Event<R>> {
        self.ensure_not_finished()?;
        self.root_parser.next_event()
    }

    fn skip_current_node(&mut self) -> Result<bool> {
        self.ensure_not_finished()?;
        self.root_parser.skip_current_node()
    }

    fn subtree_parser(&mut self) -> SubtreeParser<R> {
        SubtreeParser::new(self.root_parser)
    }
}

impl<'a, R: ParserSource, P: Parser<R>> Parser<R> for &'a mut P {
    fn root_parser(&self) -> &RootParser<R> {
        (**self).root_parser()
    }

    fn next_event(&mut self) -> Result<Event<R>> {
        (**self).next_event()
    }

    fn skip_current_node(&mut self) -> Result<bool> {
        (**self).skip_current_node()
    }

    fn subtree_parser(&mut self) -> SubtreeParser<R> {
        (**self).subtree_parser()
    }
}
<|endoftext|>


<commit_before>
use {
    AddColor,
    AddImage,
    AddRound,
    Borrowed,
    Field,
    Image,
    ImageRectangleContext,
    Matrix2d,
    Rectangle,
    RectangleColorContext,
    RoundRectangleContext,
    Value,
    View,
};
use vecmath::{
    identity,
};
use internal::{
    CanRectangle,
    CanTransform,
    HasRectangle,
    HasTransform,
};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> HasTransform<'a, Matrix2d> for RectangleContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, RectangleContext<'a>, Matrix2d> for RectangleContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> HasRectangle<'a, Rectangle> for RectangleContext<'a> {
    #[inline(always)]
    fn get_rectangle(&'a self) -> &'a Rectangle {
        self.rect.get()
    }
}

impl<'a> CanRectangle<'a, RectangleContext<'a>, Rectangle> for RectangleContext<'a> {
    #[inline(always)]
    fn rectangle(&'a self, rect: Rectangle) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(rect),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context, AddRectangle};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

impl<'a> AddRound<'a, RoundRectangleContext<'a>> for RectangleContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleContext<'a> {
        RoundRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            round_radius: Value(radius),
        }
    }
}

impl<'a> View<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddImage<'a, ImageRectangleContext<'a>> for RectangleContext<'a> {
    fn image(&'a self, image: Image) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            image: Value(image),
        }
    }
}

<commit_msg>Implemented `AddBevel` for `BevelRectangleContext`<commit_after>
use {
    AddBevel,
    AddColor,
    AddImage,
    AddRound,
    BevelRectangleContext,
    Borrowed,
    Field,
    Image,
    ImageRectangleContext,
    Matrix2d,
    Rectangle,
    RectangleColorContext,
    RoundRectangleContext,
    Value,
    View,
};
use vecmath::{
    identity,
};
use internal::{
    CanRectangle,
    CanTransform,
    HasRectangle,
    HasTransform,
};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> HasTransform<'a, Matrix2d> for RectangleContext<'a> {
    #[inline(always)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a> CanTransform<'a, RectangleContext<'a>, Matrix2d> for RectangleContext<'a> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> HasRectangle<'a, Rectangle> for RectangleContext<'a> {
    #[inline(always)]
    fn get_rectangle(&'a self) -> &'a Rectangle {
        self.rect.get()
    }
}

impl<'a> CanRectangle<'a, RectangleContext<'a>, Rectangle> for RectangleContext<'a> {
    #[inline(always)]
    fn rectangle(&'a self, rect: Rectangle) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(rect),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context, AddRectangle};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

impl<'a> AddRound<'a, RoundRectangleContext<'a>> for RectangleContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleContext<'a> {
        RoundRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            round_radius: Value(radius),
        }
    }
}

impl<'a> AddBevel<'a, BevelRectangleContext<'a>> for RectangleContext<'a> {
    #[inline(always)]
    fn bevel(&'a self, radius: f64) -> BevelRectangleContext<'a> {
        BevelRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            bevel_radius: Value(radius),
        }
    }
}

impl<'a> View<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.base.get()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn reset(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Value(identity()),
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn store_view(&'a self) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.transform.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddImage<'a, ImageRectangleContext<'a>> for RectangleContext<'a> {
    fn image(&'a self, image: Image) -> ImageRectangleContext<'a> {
        ImageRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Borrowed(self.rect.get()),
            image: Value(image),
        }
    }
}

<|endoftext|>


<commit_before>

// class Solution:
//     # @param {integer[][]} matrix
//     # @param {integer} target
//     # @return {boolean}
//     def searchMatrix(self, matrix, target):
//         colLength = len(matrix)
//         if colLength == 0:  return False
//         rowLength = len(matrix[0])
//         if rowLength == 0:  return False
//         leftElem = [matrix[i][0] for i in range(0,len(matrix))]
//         rightElem = [matrix[i][-1] for i in range(0,len(matrix))]
//         leftIndex = self.binSearch(leftElem, target)+1
//         rightIndex = self.binSearch(rightElem, target)
//         if leftIndex == 0 or rightIndex == len(matrix) - 1:
//             if target != matrix[-1][-1] and target != matrix[0][0]:
//                 return False
//             else:   return True
//         if leftIndex < rightIndex:  return False
//         if rightIndex >= 0 and matrix[rightIndex] == target:    return True
//         for i in xrange(rightIndex, leftIndex):
//             index = self.binSearch(matrix[i], target)
//             if index >= 0 and matrix[i][index] == target:   return True
//         return False

pub fn bin_search(ve : &Vec<usize>, target: usize, start : usize) -> usize {
    let l = ve.len();
    match l {
        0 => { return start; },
        1 | 2 | 3 => {
            let mut j = 0;
            for x in 0..l {
                if ve[x] > target {
                    break;
                } else {
                    j = x;
                }
            }
            return j+start;
        },
        _ => {
            let x = l/2;
            if ve[x] == target {
                return x+start;
            } else if ve[x] > target {
                if ve[x-1] <= target {
                    return x-1+start;
                } else {
                    let ve_left = split_vec(ve, 0, x);
                    return bin_search(&ve_left, target, start);
                }
            } else {
                    let ve_right = split_vec(ve, x+1, l);
                    return bin_search(&ve_right, target, start+x+1);
                }
            }
        }
    }

pub fn split_vec(col : &Vec<usize>, start_x : usize, end_x : usize) -> Vec<usize> {
    if end_x > col.len() || start_x > end_x {
        panic!("invalid index");
    }
    let mut subcol = vec![];
    let mut ix = start_x;

    loop {
        if ix >= end_x {
            break;
        }
        subcol.push(col[ix]);
        ix += 1;
    }
    return subcol;
}

// #[test]
// fn test_search_matrix() {
//     let ma = vec![
//       vec![1,   4,  7, 11, 15],
//       vec![2,   5,  8, 12, 19],
//       vec![3,   6,  9, 16, 22],
//       vec![10, 13, 14, 17, 24],
//       vec![18, 21, 23, 26, 30]
//     ];
//     assert!(search_matrix(&ma, 5));
//     assert!(!search_matrix(&ma, 20));
//     assert!(search_matrix(&ma, 16));
// }

#[test]
fn test_bin_search() {
    let ve = vec![1,  4,  7, 11, 15, 23, 34, 35, 41, 47, 55, 59, 80];
    assert_eq!(bin_search(&ve, 15, 0), 4);
    assert_eq!(bin_search(&ve, 39, 0), 7);
    assert_eq!(bin_search(&ve, 5, 0), 1);
}
<commit_msg>240. so simple O(M+N)<commit_after>
pub type Matrix = Vec<Vec<usize>>;

/// O(m + n)
pub fn search_matrix(ma : &Matrix, target : usize) -> bool {
    let yl = ma.len();
    match yl {
        0 => { false },
        _ => {
            let xl = ma[0].len();
            match xl {
                0 => { false },
                _ => {
                    let mut i = 0;
                    let mut j = yl-1;
                    loop {
                        if i < xl && j >=0 {
                            if target == ma[j][i] {
                                return true;
                            } else if target > ma[j][i] {
                                i += 1;
                            } else {
                                j -= 1;
                            }
                        } else {
                            break;
                        }
                    }
                    return false;
                }
            }
        }
    }
}

#[test]
fn test_search_matrix() {
    let ma = vec![
      vec![1,   4,  7, 11, 15],
      vec![2,   5,  8, 12, 19],
      vec![3,   6,  9, 16, 22],
      vec![10, 13, 14, 17, 24],
      vec![18, 21, 23, 26, 30]
    ];
    assert!(search_matrix(&ma, 5));
    assert!(!search_matrix(&ma, 20));
    assert!(search_matrix(&ma, 16));
}
<|endoftext|>


<commit_before>use crate::{
    error::ParseResult,
    stream::{
        FullRangeStream, Positioned, RangeStreamOnce, ResetStream, StreamErrorFor, StreamOnce,
    },
};

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct StateStream<S, U> {
    pub stream: S,
    pub state: U,
}

impl<S, U> Positioned for StateStream<S, U>
where
    S: Positioned,
{
    #[inline(always)]
    fn position(&self) -> Self::Position {
        self.stream.position()
    }
}

impl<S, U> ResetStream for StateStream<S, U>
where
    S: ResetStream,
{
    type Checkpoint = S::Checkpoint;

    #[inline(always)]
    fn checkpoint(&self) -> Self::Checkpoint {
        self.stream.checkpoint()
    }

    #[inline(always)]
    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
        self.stream.reset(checkpoint)
    }
}

impl<S, U> StreamOnce for StateStream<S, U>
where
    S: StreamOnce,
{
    type Item = S::Item;
    type Range = S::Range;
    type Position = S::Position;
    type Error = S::Error;

    #[inline(always)]
    fn uncons(&mut self) -> Result<S::Item, StreamErrorFor<Self>> {
        self.stream.uncons()
    }

    fn is_partial(&self) -> bool {
        true
    }
}

impl<S, U> RangeStreamOnce for StateStream<S, U>
where
    S: RangeStreamOnce,
{
    #[inline(always)]
    fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
        self.stream.uncons_range(size)
    }

    #[inline(always)]
    fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
    where
        F: FnMut(Self::Item) -> bool,
    {
        self.stream.uncons_while(f)
    }

    fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
    where
        F: FnMut(Self::Item) -> bool,
    {
        self.stream.uncons_while1(f)
    }

    #[inline(always)]
    fn distance(&self, end: &Self::Checkpoint) -> usize {
        self.stream.distance(end)
    }
}

impl<S, U> FullRangeStream for StateStream<S, U>
where
    S: FullRangeStream,
{
    #[inline(always)]
    fn range(&self) -> Self::Range {
        self.stream.range()
    }
}
<commit_msg>Fix is_partial<commit_after>use crate::{
    error::ParseResult,
    stream::{
        FullRangeStream, Positioned, RangeStreamOnce, ResetStream, StreamErrorFor, StreamOnce,
    },
};

#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
pub struct StateStream<S, U> {
    pub stream: S,
    pub state: U,
}

impl<S, U> Positioned for StateStream<S, U>
where
    S: Positioned,
{
    #[inline(always)]
    fn position(&self) -> Self::Position {
        self.stream.position()
    }
}

impl<S, U> ResetStream for StateStream<S, U>
where
    S: ResetStream,
{
    type Checkpoint = S::Checkpoint;

    #[inline(always)]
    fn checkpoint(&self) -> Self::Checkpoint {
        self.stream.checkpoint()
    }

    #[inline(always)]
    fn reset(&mut self, checkpoint: Self::Checkpoint) -> Result<(), Self::Error> {
        self.stream.reset(checkpoint)
    }
}

impl<S, U> StreamOnce for StateStream<S, U>
where
    S: StreamOnce,
{
    type Item = S::Item;
    type Range = S::Range;
    type Position = S::Position;
    type Error = S::Error;

    #[inline(always)]
    fn uncons(&mut self) -> Result<S::Item, StreamErrorFor<Self>> {
        self.stream.uncons()
    }

    fn is_partial(&self) -> bool {
        self.stream.is_partial()
    }
}

impl<S, U> RangeStreamOnce for StateStream<S, U>
where
    S: RangeStreamOnce,
{
    #[inline(always)]
    fn uncons_range(&mut self, size: usize) -> Result<Self::Range, StreamErrorFor<Self>> {
        self.stream.uncons_range(size)
    }

    #[inline(always)]
    fn uncons_while<F>(&mut self, f: F) -> Result<Self::Range, StreamErrorFor<Self>>
    where
        F: FnMut(Self::Item) -> bool,
    {
        self.stream.uncons_while(f)
    }

    fn uncons_while1<F>(&mut self, f: F) -> ParseResult<Self::Range, StreamErrorFor<Self>>
    where
        F: FnMut(Self::Item) -> bool,
    {
        self.stream.uncons_while1(f)
    }

    #[inline(always)]
    fn distance(&self, end: &Self::Checkpoint) -> usize {
        self.stream.distance(end)
    }
}

impl<S, U> FullRangeStream for StateStream<S, U>
where
    S: FullRangeStream,
{
    #[inline(always)]
    fn range(&self) -> Self::Range {
        self.stream.range()
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::path::Path;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => panic!("An error occured during package finding.", why),
    });
}

fn find_package(name: &str, list:&Path) -> Result<String, &str>
{
    let mut list = custom_try!(match File::open(list));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    //TODO: Use JSON.
}<commit_msg>Incomplete package list functionality<commit_after>use std::error::Error;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::path::Path;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => panic!("An error occured during package finding.", why),
    });
}

#[derive(Serialize, Deserialize)]
struct Package {
    name: String,
    version: String,
    crc32: String,
    dependencies: Vec<Package>
}

#[derive(Serialize, Deserialize)]
struct PackageList {
    packages: Vec<Package>,
    last_updated: Date
}

fn find_package(name: &str, path:&Path) -> Result<String, &str>
{
    let mut list = custom_try!(match File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = reader.read_to_string();
    let packages: PackageList = custom_try!(serde_json::from_str(buffer));
}<|endoftext|>


<commit_before>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// New test for #53818: modifying static memory at compile-time is not allowed.
// The test should never succeed.

#![feature(const_raw_ptr_deref)]
#![feature(const_let)]

use std::cell::UnsafeCell;

struct Foo(UnsafeCell<u32>);

unsafe impl Send for Foo {}
unsafe impl Sync for Foo {}

static FOO: Foo = Foo(UnsafeCell::new(42));

static BAR: () = unsafe {
    *FOO.0.get() = 5;
    //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants

    // This error is caused by a separate bug that the feature gate error is reported
    // even though the feature gate "const_let" is active.
    //~| statements in statics are unstable (see issue #48821)
};

fn main() {
    println!("{}", unsafe { *FOO.0.get() });
}
<commit_msg>fix mod-static-with-const-fn.rs.<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// New test for #53818: modifying static memory at compile-time is not allowed.
// The test should never succeed.

#![feature(const_raw_ptr_deref)]
#![feature(const_let)]

use std::cell::UnsafeCell;

struct Foo(UnsafeCell<u32>);

unsafe impl Send for Foo {}
unsafe impl Sync for Foo {}

static FOO: Foo = Foo(UnsafeCell::new(42));

static BAR: () = unsafe {
    *FOO.0.get() = 5;
    //~^ ERROR statements in statics are unstable (see issue #48821)
    // This error is caused by a separate bug that the feature gate error is reported
    // even though the feature gate "const_let" is active.
};

fn main() {
    println!("{}", unsafe { *FOO.0.get() });
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use rustc_serialize::json::Json;

use analysis::Analyzer;

use query::{Query, TermMatcher};
use query::parser::{QueryParseContext, QueryParseError};
use query::parser::utils::{parse_string, parse_float, Operator, parse_operator};

pub fn parse(context: Cow<QueryParseContext>, json: &Json) -> Result<Query, QueryParseError> {
    let object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));

    // Match queries are single-key objects. The key is the field name, the value is either a
    // string or a sub-object with extra configuration:
    //
    // {
    //     "foo": "bar"
    // }
    //
    // {
    //     "foo": {
    //         "query": "bar",
    //         "boost": 2.0
    //     }
    // }
    //
    let field_name = if object.len() == 1 {
        object.keys().collect::<Vec<_>>()[0]
    } else {
        return Err(QueryParseError::ExpectedSingleKey)
    };

    // Get configuration
    let mut query = String::new();
    let mut boost = 1.0f64;
    let mut operator = Operator::Or;

    match object[field_name] {
        Json::String(ref string) => query = string.clone(),
        Json::Object(ref inner_object) => {
            let mut has_query_key = false;

            for (key, value) in object.iter() {
                match key.as_ref() {
                    "query" => {
                        has_query_key = true;
                        query = try!(parse_string(value));
                    }
                    "boost" => {
                        boost = try!(parse_float(value));
                    }
                    "operator" => {
                        operator = try!(parse_operator(value))
                    }
                    _ => return Err(QueryParseError::UnrecognisedKey(key.clone()))
                }

                if !has_query_key {
                    return Err(QueryParseError::ExpectedKey("query"))
                }
            }
        }
        _ => return Err(QueryParseError::ExpectedObjectOrString),
    }

    // Convert query string into term query objects
    let mut sub_queries = Vec::new();
    for term in Analyzer::Standard.run(query) {
        sub_queries.push(Query::MatchTerm {
            fields: vec![field_name.clone()],
            value: term,
            matcher: TermMatcher::Exact,
            boost: 1.0f64,
        });
    }

    match operator {
        Operator::Or => {
            Ok(Query::Bool {
                must: vec![],
                must_not: vec![],
                should: sub_queries,
                filter: vec![],
                minimum_should_match: 1,
                boost: boost,
            })
        }
        Operator::And => {
            Ok(Query::Bool {
                must: sub_queries,
                must_not: vec![],
                should: vec![],
                filter: vec![],
                minimum_should_match: 0,
                boost: boost,
            })
        }
    }
}
<commit_msg>Fixed location of query key check<commit_after>use std::borrow::Cow;

use rustc_serialize::json::Json;

use analysis::Analyzer;

use query::{Query, TermMatcher};
use query::parser::{QueryParseContext, QueryParseError};
use query::parser::utils::{parse_string, parse_float, Operator, parse_operator};

pub fn parse(context: Cow<QueryParseContext>, json: &Json) -> Result<Query, QueryParseError> {
    let object = try!(json.as_object().ok_or(QueryParseError::ExpectedObject));

    // Match queries are single-key objects. The key is the field name, the value is either a
    // string or a sub-object with extra configuration:
    //
    // {
    //     "foo": "bar"
    // }
    //
    // {
    //     "foo": {
    //         "query": "bar",
    //         "boost": 2.0
    //     }
    // }
    //
    let field_name = if object.len() == 1 {
        object.keys().collect::<Vec<_>>()[0]
    } else {
        return Err(QueryParseError::ExpectedSingleKey)
    };

    // Get configuration
    let mut query = String::new();
    let mut boost = 1.0f64;
    let mut operator = Operator::Or;

    match object[field_name] {
        Json::String(ref string) => query = string.clone(),
        Json::Object(ref inner_object) => {
            let mut has_query_key = false;

            for (key, value) in object.iter() {
                match key.as_ref() {
                    "query" => {
                        has_query_key = true;
                        query = try!(parse_string(value));
                    }
                    "boost" => {
                        boost = try!(parse_float(value));
                    }
                    "operator" => {
                        operator = try!(parse_operator(value))
                    }
                    _ => return Err(QueryParseError::UnrecognisedKey(key.clone()))
                }
            }

            if !has_query_key {
                return Err(QueryParseError::ExpectedKey("query"))
            }
        }
        _ => return Err(QueryParseError::ExpectedObjectOrString),
    }

    // Convert query string into term query objects
    let mut sub_queries = Vec::new();
    for term in Analyzer::Standard.run(query) {
        sub_queries.push(Query::MatchTerm {
            fields: vec![field_name.clone()],
            value: term,
            matcher: TermMatcher::Exact,
            boost: 1.0f64,
        });
    }

    match operator {
        Operator::Or => {
            Ok(Query::Bool {
                must: vec![],
                must_not: vec![],
                should: sub_queries,
                filter: vec![],
                minimum_should_match: 1,
                boost: boost,
            })
        }
        Operator::And => {
            Ok(Query::Bool {
                must: sub_queries,
                must_not: vec![],
                should: vec![],
                filter: vec![],
                minimum_should_match: 0,
                boost: boost,
            })
        }
    }
}
<|endoftext|>


<commit_before>extern crate game_state;
extern crate cgmath;

use game_state::{
    Identity,
    Identifyable,
};

use game_state::state::{
    State,
    InputAccess,
    WorldAccess,
};
use game_state::input::events::{
    InputEvent,
};
use game_state::input::screen::{
    ScreenPoint,
};

use std::collections::VecDeque;

use game_state::input::InputSource;
use game_state::input::events::JoyButton;

use game_state::time::Duration;

use game_state::thing::Direction;

// this module's purpose is to turn input events into meaningful application input
// this might include closing windows, keyboard presses, mouse drags
// mapping user settings to keyboard and mouse bindings

#[no_mangle]
pub extern "C" fn mod_input_load( state: &mut State ) {
    state.on_input_load();
}

#[no_mangle]
pub extern "C" fn mod_input_update( state: &mut State, dt: &Duration ) {

    state.clear_input_events();
    state.gather_input_events();

    if state.has_pending_input_events() {
        let events = state.get_input_events().clone();
        for e in events {
            let mut camera = &mut state.get_world().get_facets().cameras[0];
            match e {
                InputEvent::KeyUp(_id, keycode) => {
                    match keycode {
                        // TODO: support multiple keypresses
                        17 | 18 | 30 | 31 | 32 | 46 => {
                            camera.movement_dir = None;
                        }
                        _ => {}
                    }
                },
                InputEvent::JoyButtonUp(_src, _id, btn) => {
                    camera.movement_dir = None;
                },
                InputEvent::JoyButtonDown(_src, _id, btn) => {
                    match btn {
                        JoyButton::DPadUp => camera.movement_dir = Some(Direction::Forward),
                        JoyButton::DPadLeft => camera.movement_dir = Some(Direction::Left),
                        JoyButton::DPadDown => camera.movement_dir = Some(Direction::Backward),
                        JoyButton::DPadRight => camera.movement_dir = Some(Direction::Right),
                        _ => {}
                    }
                },
                InputEvent::KeyDown(_id, keycode) => {
                    //
                    // user released 17
                    // user released 30
                    // user released 31
                    // user released 32
                    match keycode {
                        16 => {
                            println!("user pressed 'q' : hard exit.");
                            std::process::exit(0);
                        }
                        18 =>  // e
                            camera.movement_dir = Some(Direction::Up),
                        46 =>  // e
                            camera.movement_dir = Some(Direction::Down),
                        17 =>  // w
                            camera.movement_dir = Some(Direction::Forward),
                        30 => // a
                            camera.movement_dir = Some(Direction::Left),
                        31 =>// s
                            camera.movement_dir = Some(Direction::Backward),
                        32 =>// d
                            camera.movement_dir = Some(Direction::Right),
                        _ => {}
                    }
                },
                InputEvent::MouseMove(_id, _sp, delta) => {
                    let sensitivity = 100.0;
                    let (dx, dy) = (delta.delta_x as f32, delta.delta_y as f32);
                    let xa = dx / sensitivity;
                    let ya = dy / sensitivity;
                    camera.rotate(
                        cgmath::Vector3::new(-ya, -xa, 0.0)
                    );
                },
                evt => {
                    println!("event {:?}", evt);
                }
            }
        }

    }

    {
        let mut camera = &mut state.get_world().get_facets().cameras[0];
        camera.update(dt);
    }
}

#[no_mangle]
pub extern "C" fn mod_input_unload( state: &mut State ) {
    state.on_input_unload();
}
<commit_msg>formatting<commit_after>extern crate game_state;
extern crate cgmath;

use game_state::{
    Identity,
    Identifyable,
};

use game_state::state::{
    State,
    InputAccess,
    WorldAccess,
};
use game_state::input::events::{
    InputEvent,
};
use game_state::input::screen::{
    ScreenPoint,
};

use std::collections::VecDeque;

use game_state::input::InputSource;
use game_state::input::events::JoyButton;

use game_state::time::Duration;

use game_state::thing::Direction;

// this module's purpose is to turn input events into meaningful application input
// this might include closing windows, keyboard presses, mouse drags
// mapping user settings to keyboard and mouse bindings

#[no_mangle]
pub extern "C" fn mod_input_load( state: &mut State ) {
    state.on_input_load();
}

#[no_mangle]
pub extern "C" fn mod_input_update( state: &mut State, dt: &Duration ) {

    state.clear_input_events();
    state.gather_input_events();

    if state.has_pending_input_events() {
        let events = state.get_input_events().clone();
        for e in events {
            let mut camera = &mut state.get_world().get_facets().cameras[0];
            match e {
                InputEvent::KeyUp(_id, keycode) => {
                    match keycode {
                        // TODO: support multiple keypresses
                        17 | 18 | 30 | 31 | 32 | 46 => {
                            camera.movement_dir = None;
                        }
                        _ => {}
                    }
                },
                InputEvent::JoyButtonUp(_src, _id, btn) => {
                    camera.movement_dir = None;
                },
                InputEvent::JoyButtonDown(_src, _id, btn) => {
                    match btn {
                        JoyButton::DPadUp => camera.movement_dir = Some(Direction::Forward),
                        JoyButton::DPadLeft => camera.movement_dir = Some(Direction::Left),
                        JoyButton::DPadDown => camera.movement_dir = Some(Direction::Backward),
                        JoyButton::DPadRight => camera.movement_dir = Some(Direction::Right),
                        _ => {}
                    }
                },
                InputEvent::KeyDown(_id, keycode) => {
                    //
                    // user released 17
                    // user released 30
                    // user released 31
                    // user released 32
                    match keycode {
                        16 => {
                            println!("user pressed 'q' : hard exit.");
                            std::process::exit(0);
                        }
                        // e
                        18 => camera.movement_dir = Some(Direction::Up),
                        // c
                        46 => camera.movement_dir = Some(Direction::Down),
                          // w
                        17 => camera.movement_dir = Some(Direction::Forward),
                         // a
                        30 => camera.movement_dir = Some(Direction::Left),
                        // s
                        31 => camera.movement_dir = Some(Direction::Backward),
                        // d
                        32 => camera.movement_dir = Some(Direction::Right),
                        _ => {}
                    }
                },
                InputEvent::MouseMove(_id, _sp, delta) => {
                    let sensitivity = 100.0;
                    let (dx, dy) = (delta.delta_x as f32, delta.delta_y as f32);
                    let xa = dx / sensitivity;
                    let ya = dy / sensitivity;
                    camera.rotate(
                        cgmath::Vector3::new(-ya, -xa, 0.0)
                    );
                },
                evt => {
                    println!("event {:?}", evt);
                }
            }
        }

    }

    {
        let mut camera = &mut state.get_world().get_facets().cameras[0];
        camera.update(dt);
    }
}

#[no_mangle]
pub extern "C" fn mod_input_unload( state: &mut State ) {
    state.on_input_unload();
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use syntax::{ast, ast_map, ast_util, codemap, visit};
use syntax::ast::Public;
use syntax::attr::AttrMetaMethods;
use rustc::lint::{Context, LintPass, LintArray};
use rustc::middle::ty::expr_ty;
use rustc::middle::{ty, def};
use rustc::middle::typeck::astconv::AstConv;
use rustc::util::ppaux::Repr;

declare_lint!(TRANSMUTE_TYPE_LINT, Allow,
              "Warn and report types being transmuted")
declare_lint!(UNROOTED_MUST_ROOT, Deny,
              "Warn and report usage of unrooted jsmanaged objects")
declare_lint!(PRIVATIZE, Deny,
              "Allows to enforce private fields for struct definitions")

/// Lint for auditing transmutes
///
/// This lint (off by default, enable with `-W transmute-type-lint`) warns about all the transmutes
/// being used, along with the types they transmute to/from.
pub struct TransmutePass;

/// Lint for ensuring safe usage of unrooted pointers
///
/// This lint (disable with `-A unrooted-must-root`/`#[allow(unrooted_must_root)]`) ensures that `#[must_root]` values are used correctly.
/// "Incorrect" usage includes:
///
///  - Not being used in a struct/enum field which is not `#[must_root]` itself
///  - Not being used as an argument to a function (Except onces named `new` and `new_inherited`)
///  - Not being bound locally in a `let` statement, assignment, `for` loop, or `match` statement.
///
/// This helps catch most situations where pointers like `JS<T>` are used in a way that they can be invalidated by a GC pass.
pub struct UnrootedPass;

/// Lint for keeping DOM fields private
///
/// This lint (disable with `-A privatize`/`#[allow(privatize)]`) ensures all types marked with `#[privatize]` have no private fields
pub struct PrivatizePass;

impl LintPass for TransmutePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(TRANSMUTE_TYPE_LINT)
    }

    fn check_expr(&mut self, cx: &Context, ex: &ast::Expr) {
        match ex.node {
            ast::ExprCall(ref expr, ref args) => {
                match expr.node {
                    ast::ExprPath(ref path) => {
                        if path.segments.last()
                                        .map_or(false, |ref segment| segment.identifier.name.as_str() == "transmute")
                           && args.len() == 1 {
                            let tcx = cx.tcx();
                            cx.span_lint(TRANSMUTE_TYPE_LINT, ex.span,
                                         format!("Transmute from {} to {} detected",
                                                 expr_ty(tcx, ex).repr(tcx),
                                                 expr_ty(tcx, &**args.get(0).unwrap()).repr(tcx)
                                        ).as_slice());
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

// Checks if a type has the #[must_root] annotation.
// Unwraps pointers as well
// TODO (#3874, sort of): unwrap other types like Vec/Option/HashMap/etc
fn lint_unrooted_ty(cx: &Context, ty: &ast::Ty, warning: &str) {
    match ty.node {
        ast::TyVec(ref t) | ast::TyFixedLengthVec(ref t, _) |
        ast::TyPtr(ast::MutTy { ty: ref t, ..}) | ast::TyRptr(_, ast::MutTy { ty: ref t, ..}) => lint_unrooted_ty(cx, &**t, warning),
        ast::TyPath(_, _, id) => {
                match cx.tcx.def_map.borrow()[id].clone() {
                    def::DefTy(def_id, _) => {
                        if ty::has_attr(cx.tcx, def_id, "must_root") {
                            cx.span_lint(UNROOTED_MUST_ROOT, ty.span, warning);
                        }
                    }
                    _ => (),
                }
            }
            _ => (),
    };
}

// Determines if a block is in an unsafe context so that an unhelpful
// lint can be aborted.
fn unsafe_context(map: &ast_map::Map, id: ast::NodeId) -> bool {
    match map.get(map.get_parent(id)) {
        ast_map::NodeImplItem(itm) => {
            match *itm {
                ast::MethodImplItem(ref meth) => match meth.node {
                    ast::MethDecl(_, _, _, _, style, _, _, _) => match style {
                        ast::UnsafeFn => true,
                        _ => false,
                    },
                    _ => false,
                },
                _ => false,
            }
        },
        ast_map::NodeItem(itm) => {
            match itm.node {
                ast::ItemFn(_, style, _, _, _) => match style {
                    ast::UnsafeFn => true,
                    _ => false,
                },
                _ => false,
            }
        }
        _ => false // There are probably a couple of other unsafe cases we don't care to lint, those will need to be added.
    }
}

impl LintPass for UnrootedPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNROOTED_MUST_ROOT)
    }
    /// All structs containing #[must_root] types must be #[must_root] themselves
    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef, _i: ast::Ident, _gen: &ast::Generics, id: ast::NodeId) {
        if cx.tcx.map.expect_item(id).attrs.iter().all(|a| !a.check_name("must_root")) {
            for ref field in def.fields.iter() {
                lint_unrooted_ty(cx, &*field.node.ty,
                                 "Type must be rooted, use #[must_root] on the struct definition to propagate");
            }
        }
    }
    /// All enums containing #[must_root] types must be #[must_root] themselves
    fn check_variant(&mut self, cx: &Context, var: &ast::Variant, _gen: &ast::Generics) {
        let ref map = cx.tcx.map;
        if map.expect_item(map.get_parent(var.node.id)).attrs.iter().all(|a| !a.check_name("must_root")) {
            match var.node.kind {
                ast::TupleVariantKind(ref vec) => {
                    for ty in vec.iter() {
                        lint_unrooted_ty(cx, &*ty.ty,
                                         "Type must be rooted, use #[must_root] on the enum definition to propagate")
                    }
                }
                _ => () // Struct variants already caught by check_struct_def
            }
        }
    }
    /// Function arguments that are #[must_root] types are not allowed
    fn check_fn(&mut self, cx: &Context, kind: visit::FnKind, decl: &ast::FnDecl,
                block: &ast::Block, _span: codemap::Span, id: ast::NodeId) {
        match kind {
            visit::FkItemFn(i, _, _, _) |
            visit::FkMethod(i, _, _) if i.as_str() == "new" || i.as_str() == "new_inherited" => {
                return;
            },
            visit::FkItemFn(_, _, style, _) => match style {
                ast::UnsafeFn => return,
                _ => ()
            },
            _ => ()
        }

        if unsafe_context(&cx.tcx.map, id) {
            return;
        }

        match block.rules {
            ast::DefaultBlock => {
                for arg in decl.inputs.iter() {
                    lint_unrooted_ty(cx, &*arg.ty,
                                     "Type must be rooted")
                }
            }
            _ => () // fn is `unsafe`
        }
    }

    // Partially copied from rustc::middle::lint::builtin
    // Catches `let` statements and assignments which store a #[must_root] value
    // Expressions which return out of blocks eventually end up in a `let` or assignment
    // statement or a function return (which will be caught when it is used elsewhere)
    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {

        match s.node {
            ast::StmtDecl(_, id) |
            ast::StmtExpr(_, id) |
            ast::StmtSemi(_, id) if unsafe_context(&cx.tcx.map, id) => {
                return
            },
            _ => ()
        };

        let expr = match s.node {
            // Catch a `let` binding
            ast::StmtDecl(ref decl, _) => match decl.node {
                ast::DeclLocal(ref loc) => match loc.init {
                    Some(ref e) => &**e,
                    _ => return
                },
                _ => return
            },
            ast::StmtExpr(ref expr, _) => match expr.node {
                // This catches deferred `let` statements
                ast::ExprAssign(_, ref e) |
                // Match statements allow you to bind onto the variable later in an arm
                // We need not check arms individually since enum/struct fields are already
                // linted in `check_struct_def` and `check_variant`
                // (so there is no way of destructuring out a `#[must_root]` field)
                ast::ExprMatch(ref e, _, _) |
                // For loops allow you to bind a return value locally
                ast::ExprForLoop(_, ref e, _, _) => &**e,
                // XXXManishearth look into `if let` once it lands in our rustc
                _ => return
            },
            _ => return
        };

        let t = expr_ty(cx.tcx, &*expr);
        match ty::get(t).sty {
            ty::ty_struct(did, _) |
            ty::ty_enum(did, _) => {
                if ty::has_attr(cx.tcx, did, "must_root") {
                    cx.span_lint(UNROOTED_MUST_ROOT, expr.span,
                                 format!("Expression of type {} must be rooted", t.repr(cx.tcx)).as_slice());
                }
            }
            _ => {}
        }
    }
}

impl LintPass for PrivatizePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(PRIVATIZE)
    }

    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef, _i: ast::Ident, _gen: &ast::Generics, id: ast::NodeId) {
        if ty::has_attr(cx.tcx, ast_util::local_def(id), "privatize") {
            for field in def.fields.iter() {
                match field.node {
                    ast::StructField_ { kind: ast::NamedField(ident, visibility), .. } if visibility == Public => {
                        cx.span_lint(PRIVATIZE, field.span,
                                     format!("Field {} is public where only private fields are allowed", ident.name).as_slice());
                    }
                    _ => {}
                }
            }
        }
    }
}
<commit_msg>plugins: Fix transmute lint message<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use syntax::{ast, ast_map, ast_util, codemap, visit};
use syntax::ast::Public;
use syntax::attr::AttrMetaMethods;
use rustc::lint::{Context, LintPass, LintArray};
use rustc::middle::ty::expr_ty;
use rustc::middle::{ty, def};
use rustc::middle::typeck::astconv::AstConv;
use rustc::util::ppaux::Repr;

declare_lint!(TRANSMUTE_TYPE_LINT, Allow,
              "Warn and report types being transmuted")
declare_lint!(UNROOTED_MUST_ROOT, Deny,
              "Warn and report usage of unrooted jsmanaged objects")
declare_lint!(PRIVATIZE, Deny,
              "Allows to enforce private fields for struct definitions")

/// Lint for auditing transmutes
///
/// This lint (off by default, enable with `-W transmute-type-lint`) warns about all the transmutes
/// being used, along with the types they transmute to/from.
pub struct TransmutePass;

/// Lint for ensuring safe usage of unrooted pointers
///
/// This lint (disable with `-A unrooted-must-root`/`#[allow(unrooted_must_root)]`) ensures that `#[must_root]` values are used correctly.
/// "Incorrect" usage includes:
///
///  - Not being used in a struct/enum field which is not `#[must_root]` itself
///  - Not being used as an argument to a function (Except onces named `new` and `new_inherited`)
///  - Not being bound locally in a `let` statement, assignment, `for` loop, or `match` statement.
///
/// This helps catch most situations where pointers like `JS<T>` are used in a way that they can be invalidated by a GC pass.
pub struct UnrootedPass;

/// Lint for keeping DOM fields private
///
/// This lint (disable with `-A privatize`/`#[allow(privatize)]`) ensures all types marked with `#[privatize]` have no private fields
pub struct PrivatizePass;

impl LintPass for TransmutePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(TRANSMUTE_TYPE_LINT)
    }

    fn check_expr(&mut self, cx: &Context, ex: &ast::Expr) {
        match ex.node {
            ast::ExprCall(ref expr, ref args) => {
                match expr.node {
                    ast::ExprPath(ref path) => {
                        if path.segments.last()
                                        .map_or(false, |ref segment| segment.identifier.name.as_str() == "transmute")
                           && args.len() == 1 {
                            let tcx = cx.tcx();
                            cx.span_lint(TRANSMUTE_TYPE_LINT, ex.span,
                                         format!("Transmute to {} from {} detected",
                                                 expr_ty(tcx, ex).repr(tcx),
                                                 expr_ty(tcx, &**args.get(0).unwrap()).repr(tcx)
                                        ).as_slice());
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

// Checks if a type has the #[must_root] annotation.
// Unwraps pointers as well
// TODO (#3874, sort of): unwrap other types like Vec/Option/HashMap/etc
fn lint_unrooted_ty(cx: &Context, ty: &ast::Ty, warning: &str) {
    match ty.node {
        ast::TyVec(ref t) | ast::TyFixedLengthVec(ref t, _) |
        ast::TyPtr(ast::MutTy { ty: ref t, ..}) | ast::TyRptr(_, ast::MutTy { ty: ref t, ..}) => lint_unrooted_ty(cx, &**t, warning),
        ast::TyPath(_, _, id) => {
                match cx.tcx.def_map.borrow()[id].clone() {
                    def::DefTy(def_id, _) => {
                        if ty::has_attr(cx.tcx, def_id, "must_root") {
                            cx.span_lint(UNROOTED_MUST_ROOT, ty.span, warning);
                        }
                    }
                    _ => (),
                }
            }
            _ => (),
    };
}

// Determines if a block is in an unsafe context so that an unhelpful
// lint can be aborted.
fn unsafe_context(map: &ast_map::Map, id: ast::NodeId) -> bool {
    match map.get(map.get_parent(id)) {
        ast_map::NodeImplItem(itm) => {
            match *itm {
                ast::MethodImplItem(ref meth) => match meth.node {
                    ast::MethDecl(_, _, _, _, style, _, _, _) => match style {
                        ast::UnsafeFn => true,
                        _ => false,
                    },
                    _ => false,
                },
                _ => false,
            }
        },
        ast_map::NodeItem(itm) => {
            match itm.node {
                ast::ItemFn(_, style, _, _, _) => match style {
                    ast::UnsafeFn => true,
                    _ => false,
                },
                _ => false,
            }
        }
        _ => false // There are probably a couple of other unsafe cases we don't care to lint, those will need to be added.
    }
}

impl LintPass for UnrootedPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNROOTED_MUST_ROOT)
    }
    /// All structs containing #[must_root] types must be #[must_root] themselves
    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef, _i: ast::Ident, _gen: &ast::Generics, id: ast::NodeId) {
        if cx.tcx.map.expect_item(id).attrs.iter().all(|a| !a.check_name("must_root")) {
            for ref field in def.fields.iter() {
                lint_unrooted_ty(cx, &*field.node.ty,
                                 "Type must be rooted, use #[must_root] on the struct definition to propagate");
            }
        }
    }
    /// All enums containing #[must_root] types must be #[must_root] themselves
    fn check_variant(&mut self, cx: &Context, var: &ast::Variant, _gen: &ast::Generics) {
        let ref map = cx.tcx.map;
        if map.expect_item(map.get_parent(var.node.id)).attrs.iter().all(|a| !a.check_name("must_root")) {
            match var.node.kind {
                ast::TupleVariantKind(ref vec) => {
                    for ty in vec.iter() {
                        lint_unrooted_ty(cx, &*ty.ty,
                                         "Type must be rooted, use #[must_root] on the enum definition to propagate")
                    }
                }
                _ => () // Struct variants already caught by check_struct_def
            }
        }
    }
    /// Function arguments that are #[must_root] types are not allowed
    fn check_fn(&mut self, cx: &Context, kind: visit::FnKind, decl: &ast::FnDecl,
                block: &ast::Block, _span: codemap::Span, id: ast::NodeId) {
        match kind {
            visit::FkItemFn(i, _, _, _) |
            visit::FkMethod(i, _, _) if i.as_str() == "new" || i.as_str() == "new_inherited" => {
                return;
            },
            visit::FkItemFn(_, _, style, _) => match style {
                ast::UnsafeFn => return,
                _ => ()
            },
            _ => ()
        }

        if unsafe_context(&cx.tcx.map, id) {
            return;
        }

        match block.rules {
            ast::DefaultBlock => {
                for arg in decl.inputs.iter() {
                    lint_unrooted_ty(cx, &*arg.ty,
                                     "Type must be rooted")
                }
            }
            _ => () // fn is `unsafe`
        }
    }

    // Partially copied from rustc::middle::lint::builtin
    // Catches `let` statements and assignments which store a #[must_root] value
    // Expressions which return out of blocks eventually end up in a `let` or assignment
    // statement or a function return (which will be caught when it is used elsewhere)
    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {

        match s.node {
            ast::StmtDecl(_, id) |
            ast::StmtExpr(_, id) |
            ast::StmtSemi(_, id) if unsafe_context(&cx.tcx.map, id) => {
                return
            },
            _ => ()
        };

        let expr = match s.node {
            // Catch a `let` binding
            ast::StmtDecl(ref decl, _) => match decl.node {
                ast::DeclLocal(ref loc) => match loc.init {
                    Some(ref e) => &**e,
                    _ => return
                },
                _ => return
            },
            ast::StmtExpr(ref expr, _) => match expr.node {
                // This catches deferred `let` statements
                ast::ExprAssign(_, ref e) |
                // Match statements allow you to bind onto the variable later in an arm
                // We need not check arms individually since enum/struct fields are already
                // linted in `check_struct_def` and `check_variant`
                // (so there is no way of destructuring out a `#[must_root]` field)
                ast::ExprMatch(ref e, _, _) |
                // For loops allow you to bind a return value locally
                ast::ExprForLoop(_, ref e, _, _) => &**e,
                // XXXManishearth look into `if let` once it lands in our rustc
                _ => return
            },
            _ => return
        };

        let t = expr_ty(cx.tcx, &*expr);
        match ty::get(t).sty {
            ty::ty_struct(did, _) |
            ty::ty_enum(did, _) => {
                if ty::has_attr(cx.tcx, did, "must_root") {
                    cx.span_lint(UNROOTED_MUST_ROOT, expr.span,
                                 format!("Expression of type {} must be rooted", t.repr(cx.tcx)).as_slice());
                }
            }
            _ => {}
        }
    }
}

impl LintPass for PrivatizePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(PRIVATIZE)
    }

    fn check_struct_def(&mut self, cx: &Context, def: &ast::StructDef, _i: ast::Ident, _gen: &ast::Generics, id: ast::NodeId) {
        if ty::has_attr(cx.tcx, ast_util::local_def(id), "privatize") {
            for field in def.fields.iter() {
                match field.node {
                    ast::StructField_ { kind: ast::NamedField(ident, visibility), .. } if visibility == Public => {
                        cx.span_lint(PRIVATIZE, field.span,
                                     format!("Field {} is public where only private fields are allowed", ident.name).as_slice());
                    }
                    _ => {}
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use cocoa::base::id;

pub struct RenderPipelineState(id);
<commit_msg>Add from/into/as raw impls for RenderPipelineState<commit_after>use cocoa::base::id;

pub struct RenderPipelineState(id);

impl_from_into_raw!(RenderPipelineState, of protocol "MTLRenderPipelineState");
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use std::error::Error;
use std::ffi::OsString;
use std::io::{Write, stderr};
use std::path::Path;
use std::process::Command;
use walkdir::DirEntry;

use find::matchers::{Matcher, MatcherIO};

enum Arg {
    Filename,
    LiteralArg(OsString),
}

pub struct SingleExecMatcher {
    executable: String,
    args: Vec<Arg>,
    exec_in_parent_dir: bool,
}

impl SingleExecMatcher {
    pub fn new(executable: &str,
               args: &[&str],
               exec_in_parent_dir: bool)
               -> Result<SingleExecMatcher, Box<Error>> {

        let transformed_args = args.iter()
            .map(|&a| match a {
                "{}" => Arg::Filename,
                _ => Arg::LiteralArg(OsString::from(a)),
            })
            .collect();

        Ok(SingleExecMatcher {
            executable: executable.to_string(),
            args: transformed_args,
            exec_in_parent_dir: exec_in_parent_dir,
        })
    }

    pub fn new_box(executable: &str,
                   args: &[&str],
                   exec_in_parent_dir: bool)
                   -> Result<Box<Matcher>, Box<Error>> {
        Ok(Box::new(SingleExecMatcher::new(executable, args, exec_in_parent_dir)?))
    }
}

impl Matcher for SingleExecMatcher {
    fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
        let mut command = Command::new(&self.executable);
        let path_to_file = if self.exec_in_parent_dir {
            if let Some(f) = file_info.path().file_name() {
                Path::new(".").join(f)
            } else {
                Path::new(".").join(file_info.path())
            }
        } else {
            file_info.path().to_path_buf()
        };

        for arg in &self.args {
            command.arg(match arg {
                &Arg::LiteralArg(ref a) => a.as_os_str(),
                &Arg::Filename => path_to_file.as_os_str(),
            });
        }
        if self.exec_in_parent_dir {

            if file_info.path() == Path::new(".") {
                command.current_dir(file_info.path());
            } else if let Some(parent) = file_info.path().parent() {
                command.current_dir(parent);
            }
        }
        match command.status() {
            Ok(status) => return status.success(),
            Err(e) => {
                writeln!(&mut stderr(), "Failed to run {}: {}", self.executable, e).unwrap();
                return false;
            }
        }
    }

    fn has_side_effects(&self) -> bool {
        return true;
    }
}

#[cfg(test)]
/// No tests here, because we need to call out to an external executable. See
/// tests/exec_unit_tests.rs instead.
mod tests {}
<commit_msg>Second attempt at fixing #23<commit_after>// Copyright 2017 Google Inc.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

use std::error::Error;
use std::ffi::OsString;
use std::io::{Write, stderr};
use std::path::Path;
use std::process::Command;
use walkdir::DirEntry;

use find::matchers::{Matcher, MatcherIO};

enum Arg {
    Filename,
    LiteralArg(OsString),
}

pub struct SingleExecMatcher {
    executable: String,
    args: Vec<Arg>,
    exec_in_parent_dir: bool,
}

impl SingleExecMatcher {
    pub fn new(executable: &str,
               args: &[&str],
               exec_in_parent_dir: bool)
               -> Result<SingleExecMatcher, Box<Error>> {

        let transformed_args = args.iter()
            .map(|&a| match a {
                "{}" => Arg::Filename,
                _ => Arg::LiteralArg(OsString::from(a)),
            })
            .collect();

        Ok(SingleExecMatcher {
            executable: executable.to_string(),
            args: transformed_args,
            exec_in_parent_dir: exec_in_parent_dir,
        })
    }

    pub fn new_box(executable: &str,
                   args: &[&str],
                   exec_in_parent_dir: bool)
                   -> Result<Box<Matcher>, Box<Error>> {
        Ok(Box::new(SingleExecMatcher::new(executable, args, exec_in_parent_dir)?))
    }
}

impl Matcher for SingleExecMatcher {
    fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
        let mut command = Command::new(&self.executable);
        let path_to_file = if self.exec_in_parent_dir {
            if let Some(f) = file_info.path().file_name() {
                Path::new(".").join(f)
            } else {
                Path::new(".").join(file_info.path())
            }
        } else {
            file_info.path().to_path_buf()
        };

        for arg in &self.args {
            command.arg(match arg {
                &Arg::LiteralArg(ref a) => a.as_os_str(),
                &Arg::Filename => path_to_file.as_os_str(),
            });
        }
        if self.exec_in_parent_dir {

            if let Some(parent) = file_info.path().parent() {
                if parent == Path::new("") {
                    command.current_dir(Path::new("."));
                } else {
                    command.current_dir(parent);
                }
            } else {
                command.current_dir(Path::new("."));

            }
        }
        match command.status() {
            Ok(status) => return status.success(),
            Err(e) => {
                writeln!(&mut stderr(), "Failed to run {}: {}", self.executable, e).unwrap();
                return false;
            }
        }
    }

    fn has_side_effects(&self) -> bool {
        return true;
    }
}

#[cfg(test)]
/// No tests here, because we need to call out to an external executable. See
/// tests/exec_unit_tests.rs instead.
mod tests {}
<|endoftext|>