<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>;
}

/// 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()
    }

    /// Creates subtree parser for the current node.
    pub fn subtree_parser(&mut self) -> SubtreeParser<R> {
        SubtreeParser::new(self)
    }

    /// 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)
        }
    }
}

/// 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 let Some(err) = self.root_parser.error() {
            return Err(err.clone());
        }
        if self.root_parser.num_open_nodes() < self.initial_depth {
            return Err(Error::Finished);
        }
        Ok(())
    }
}

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()
    }
}
<commit_msg>Implement `Parser` for `&mut P where P: Parser`<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>;
}

/// 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()
    }

    /// Creates subtree parser for the current node.
    pub fn subtree_parser(&mut self) -> SubtreeParser<R> {
        SubtreeParser::new(self)
    }

    /// 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)
        }
    }
}

/// 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 let Some(err) = self.root_parser.error() {
            return Err(err.clone());
        }
        if self.root_parser.num_open_nodes() < self.initial_depth {
            return Err(Error::Finished);
        }
        Ok(())
    }
}

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()
    }
}

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()
    }
}
<|endoftext|>


<commit_before>use std::ops::Index;
use slab::Slab;

use na::{self, Real};

use math::Point;
use partitioning::BVTVisitor;
use bounding_volume::BoundingVolume;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
/// The unique identifier of a DBVT leaf.
pub struct DBVTLeafId(usize);

impl DBVTLeafId {
    /// Creates an invalid identifier.
    #[inline]
    pub fn new_invalid() -> Self {
        DBVTLeafId(usize::max_value())
    }

    /// Checkis if this identifier is invalid.
    #[inline]
    pub fn is_invalid(&self) -> bool {
        let DBVTLeafId(val) = *self;
        val == usize::max_value()
    }
}

#[derive(Copy, Clone, Debug)]
enum UpdateStatus {
    NeedsShrink,
    UpToDate,
}

#[derive(Copy, Clone, Debug, Hash)]
enum DBVTInternalId {
    RightChildOf(usize),
    LeftChildOf(usize),
    Root,
}

#[derive(Copy, Clone, Debug, Hash)]
enum DBVTNodeId {
    Leaf(usize),
    Internal(usize),
}

/// A boundin volume hierarchy on which objects can be added or removed after construction.
pub struct DBVT<N: Real, B, BV> {
    root: DBVTNodeId,
    leaves: Slab<DBVTLeaf<N, B, BV>>,
    internals: Slab<DBVTInternal<N, BV>>,
}

/// Leaf of a Dynamic Bounding Volume Tree.
#[derive(Clone)]
pub struct DBVTLeaf<N: Real, B, BV> {
    /// The bounding volume of this node.
    pub bounding_volume: BV,
    /// The center of this node bounding volume.
    pub center: Point<N>,
    /// An user-defined data.
    pub data: B,
    /// This node parent.
    parent: DBVTInternalId,
}

/// Internal node of a DBVT. An internal node always has two children.
struct DBVTInternal<N: Real, BV> {
    /// The bounding volume of this node. It always encloses both its children bounding volumes.
    bounding_volume: BV,
    /// The center of this node bounding volume.
    center: Point<N>,
    /// This node left child.
    left: DBVTNodeId,
    /// This node right child.
    right: DBVTNodeId,
    /// This node parent.
    parent: DBVTInternalId,

    state: UpdateStatus,
}

impl<N: Real, B, BV: BoundingVolume<N>> DBVTLeaf<N, B, BV> {
    /// Creates a new DBVT leaf from its bounding volume and contained data.
    pub fn new(bounding_volume: BV, data: B) -> DBVTLeaf<N, B, BV> {
        DBVTLeaf {
            center: bounding_volume.center(),
            bounding_volume: bounding_volume,
            data: data,
            parent: DBVTInternalId::Root,
        }
    }

    /// Returns `true` if this leaf is the root of the tree, or if it detached from any tree.
    pub fn is_root(&self) -> bool {
        match self.parent {
            DBVTInternalId::Root => true,
            _ => false,
        }
    }
}

impl<N: Real, BV: BoundingVolume<N>> DBVTInternal<N, BV> {
    /// Creates a new internal node.
    fn new(
        bounding_volume: BV,
        parent: DBVTInternalId,
        left: DBVTNodeId,
        right: DBVTNodeId,
    ) -> DBVTInternal<N, BV> {
        DBVTInternal {
            center: bounding_volume.center(),
            bounding_volume: bounding_volume,
            left: left,
            right: right,
            parent: parent,
            state: UpdateStatus::UpToDate,
        }
    }
}

impl<N: Real, B, BV: BoundingVolume<N>> DBVT<N, B, BV> {
    /// Creates a new empty dynamic bonding volume hierarchy.
    pub fn new() -> DBVT<N, B, BV> {
        DBVT {
            root: DBVTNodeId::Leaf(0),
            leaves: Slab::new(),
            internals: Slab::new(),
        }
    }

    /// Indicates whether this DBVT empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.leaves.is_empty()
    }

    /// Inserts a leaf into this DBVT.
    pub fn insert(&mut self, leaf: DBVTLeaf<N, B, BV>) -> DBVTLeafId {
        if self.is_empty() {
            let new_id = self.leaves.insert(leaf);
            self.leaves[new_id].parent = DBVTInternalId::Root;
            self.root = DBVTNodeId::Leaf(new_id);

            return DBVTLeafId(new_id);
        }

        match self.root {
            DBVTNodeId::Internal(_) => {
                let mut curr = self.root;

                loop {
                    match curr {
                        DBVTNodeId::Internal(id) => {
                            // FIXME: we could avoid the systematic merge
                            let (left, right) = {
                                let node = &mut self.internals[id];
                                node.bounding_volume.merge(&leaf.bounding_volume);
                                (node.left, node.right)
                            };

                            let dist1 = match left {
                                DBVTNodeId::Leaf(l) => {
                                    na::distance_squared(&self.leaves[l].center, &leaf.center)
                                }
                                DBVTNodeId::Internal(i) => {
                                    na::distance_squared(&self.internals[i].center, &leaf.center)
                                }
                            };

                            let dist2 = match right {
                                DBVTNodeId::Leaf(l) => {
                                    na::distance_squared(&self.leaves[l].center, &leaf.center)
                                }
                                DBVTNodeId::Internal(i) => {
                                    na::distance_squared(&self.internals[i].center, &leaf.center)
                                }
                            };

                            curr = if dist1 < dist2 { left } else { right };
                        }
                        DBVTNodeId::Leaf(id) => {
                            let parent_bv = self.leaves[id]
                                .bounding_volume
                                .merged(&leaf.bounding_volume);
                            let grand_parent = self.leaves[id].parent;

                            let new_id = self.leaves.insert(leaf);
                            let parent = DBVTInternal::new(
                                parent_bv,
                                grand_parent,
                                curr,
                                DBVTNodeId::Leaf(new_id),
                            );
                            let parent_id = self.internals.insert(parent);
                            self.leaves[id].parent = DBVTInternalId::LeftChildOf(parent_id);
                            self.leaves[new_id].parent = DBVTInternalId::RightChildOf(parent_id);

                            match grand_parent {
                                DBVTInternalId::LeftChildOf(pp) => {
                                    self.internals[pp].left = DBVTNodeId::Internal(parent_id)
                                }
                                DBVTInternalId::RightChildOf(pp) => {
                                    self.internals[pp].right = DBVTNodeId::Internal(parent_id)
                                }
                                _ => unreachable!(),
                            }

                            break DBVTLeafId(new_id);
                        }
                    }
                }
            }
            DBVTNodeId::Leaf(id) => {
                let new_id = self.leaves.insert(leaf);

                // Create a common parent which is the new root.
                let root_bv = self.leaves[id]
                    .bounding_volume
                    .merged(&self.leaves[new_id].bounding_volume);
                let root = DBVTInternal::new(
                    root_bv,
                    DBVTInternalId::Root,
                    DBVTNodeId::Leaf(id),
                    DBVTNodeId::Leaf(new_id),
                );

                let root_id = self.internals.insert(root);
                self.leaves[id].parent = DBVTInternalId::LeftChildOf(root_id);
                self.leaves[new_id].parent = DBVTInternalId::RightChildOf(root_id);
                self.root = DBVTNodeId::Internal(root_id);

                DBVTLeafId(new_id)
            }
        }
    }

    /// Removes a leaf from this DBVT.
    ///
    /// Panics if the provided leaf is not attached to this DBVT.
    pub fn remove(&mut self, leaf_id: DBVTLeafId) -> DBVTLeaf<N, B, BV> {
        let DBVTLeafId(leaf_id) = leaf_id;
        let leaf = self.leaves.remove(leaf_id);

        if !leaf.is_root() {
            let p;
            let other;

            match leaf.parent {
                DBVTInternalId::RightChildOf(parent) => {
                    other = self.internals[parent].left;
                    p = parent;
                }
                DBVTInternalId::LeftChildOf(parent) => {
                    other = self.internals[parent].right;
                    p = parent;
                }
                DBVTInternalId::Root => unreachable!(),
            }

            match self.internals[p].parent {
                DBVTInternalId::RightChildOf(pp) => {
                    match other {
                        DBVTNodeId::Internal(id) => {
                            self.internals[id].parent = DBVTInternalId::RightChildOf(pp)
                        }
                        DBVTNodeId::Leaf(id) => {
                            self.leaves[id].parent = DBVTInternalId::RightChildOf(pp)
                        }
                    }

                    self.internals[pp].right = other;
                    self.internals[pp].state = UpdateStatus::NeedsShrink;
                }
                DBVTInternalId::LeftChildOf(pp) => {
                    match other {
                        DBVTNodeId::Internal(id) => {
                            self.internals[id].parent = DBVTInternalId::LeftChildOf(pp)
                        }
                        DBVTNodeId::Leaf(id) => {
                            self.leaves[id].parent = DBVTInternalId::LeftChildOf(pp)
                        }
                    }

                    self.internals[pp].left = other;
                    self.internals[pp].state = UpdateStatus::NeedsShrink;
                }
                DBVTInternalId::Root => {
                    // The root changes to the other child.
                    match other {
                        DBVTNodeId::Leaf(id) => self.leaves[id].parent = DBVTInternalId::Root,
                        DBVTNodeId::Internal(id) => {
                            self.internals[id].parent = DBVTInternalId::Root
                        }
                    }

                    self.root = other;
                }
            }
        } else {
            // The tree is now empty.
            self.leaves.clear();
            self.internals.clear();
        }

        leaf
    }

    /// Traverses this tree using an object implementing the `BVTVisitor`trait.
    ///
    /// This will traverse the whole tree and call the visitor `.visit_internal(...)` (resp.
    /// `.visit_leaf(...)`) method on each internal (resp. leaf) node.
    pub fn visit<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis) {
        if !self.is_empty() {
            self.visit_node(visitor, self.root);
        }
    }

    fn visit_node<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis, node: DBVTNodeId) {
        match node {
            DBVTNodeId::Internal(i) => {
                let internal = &self.internals[i];
                if visitor.visit_internal(&internal.bounding_volume) {
                    self.visit_node(visitor, internal.left);
                    self.visit_node(visitor, internal.right);
                }
            }
            DBVTNodeId::Leaf(i) => {
                let leaf = &self.leaves[i];
                visitor.visit_leaf(&leaf.data, &leaf.bounding_volume);
            }
        }
    }
}

impl<N: Real, B, BV> Index<DBVTLeafId> for DBVT<N, B, BV> {
    type Output = DBVTLeaf<N, B, BV>;

    #[inline]
    fn index(&self, DBVTLeafId(id): DBVTLeafId) -> &Self::Output {
        &self.leaves[id]
    }
}
<commit_msg>Properly remove internal DBVT nodes to save memory.<commit_after>use slab::Slab;
use std::ops::Index;

use na::{self, Real};

use bounding_volume::BoundingVolume;
use math::Point;
use partitioning::BVTVisitor;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
/// The unique identifier of a DBVT leaf.
pub struct DBVTLeafId(usize);

impl DBVTLeafId {
    /// Creates an invalid identifier.
    #[inline]
    pub fn new_invalid() -> Self {
        DBVTLeafId(usize::max_value())
    }

    /// Checkis if this identifier is invalid.
    #[inline]
    pub fn is_invalid(&self) -> bool {
        let DBVTLeafId(val) = *self;
        val == usize::max_value()
    }
}

#[derive(Copy, Clone, Debug)]
enum UpdateStatus {
    NeedsShrink,
    UpToDate,
}

#[derive(Copy, Clone, Debug, Hash)]
enum DBVTInternalId {
    RightChildOf(usize),
    LeftChildOf(usize),
    Root,
}

#[derive(Copy, Clone, Debug, Hash)]
enum DBVTNodeId {
    Leaf(usize),
    Internal(usize),
}

/// A boundin volume hierarchy on which objects can be added or removed after construction.
pub struct DBVT<N: Real, B, BV> {
    root: DBVTNodeId,
    leaves: Slab<DBVTLeaf<N, B, BV>>,
    internals: Slab<DBVTInternal<N, BV>>,
}

/// Leaf of a Dynamic Bounding Volume Tree.
#[derive(Clone)]
pub struct DBVTLeaf<N: Real, B, BV> {
    /// The bounding volume of this node.
    pub bounding_volume: BV,
    /// The center of this node bounding volume.
    pub center: Point<N>,
    /// An user-defined data.
    pub data: B,
    /// This node parent.
    parent: DBVTInternalId,
}

/// Internal node of a DBVT. An internal node always has two children.
struct DBVTInternal<N: Real, BV> {
    /// The bounding volume of this node. It always encloses both its children bounding volumes.
    bounding_volume: BV,
    /// The center of this node bounding volume.
    center: Point<N>,
    /// This node left child.
    left: DBVTNodeId,
    /// This node right child.
    right: DBVTNodeId,
    /// This node parent.
    parent: DBVTInternalId,

    state: UpdateStatus,
}

impl<N: Real, B, BV: BoundingVolume<N>> DBVTLeaf<N, B, BV> {
    /// Creates a new DBVT leaf from its bounding volume and contained data.
    pub fn new(bounding_volume: BV, data: B) -> DBVTLeaf<N, B, BV> {
        DBVTLeaf {
            center: bounding_volume.center(),
            bounding_volume: bounding_volume,
            data: data,
            parent: DBVTInternalId::Root,
        }
    }

    /// Returns `true` if this leaf is the root of the tree, or if it detached from any tree.
    pub fn is_root(&self) -> bool {
        match self.parent {
            DBVTInternalId::Root => true,
            _ => false,
        }
    }
}

impl<N: Real, BV: BoundingVolume<N>> DBVTInternal<N, BV> {
    /// Creates a new internal node.
    fn new(
        bounding_volume: BV,
        parent: DBVTInternalId,
        left: DBVTNodeId,
        right: DBVTNodeId,
    ) -> DBVTInternal<N, BV> {
        DBVTInternal {
            center: bounding_volume.center(),
            bounding_volume: bounding_volume,
            left: left,
            right: right,
            parent: parent,
            state: UpdateStatus::UpToDate,
        }
    }
}

impl<N: Real, B, BV: BoundingVolume<N>> DBVT<N, B, BV> {
    /// Creates a new empty dynamic bonding volume hierarchy.
    pub fn new() -> DBVT<N, B, BV> {
        DBVT {
            root: DBVTNodeId::Leaf(0),
            leaves: Slab::new(),
            internals: Slab::new(),
        }
    }

    /// Indicates whether this DBVT empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.leaves.is_empty()
    }

    /// Inserts a leaf into this DBVT.
    pub fn insert(&mut self, leaf: DBVTLeaf<N, B, BV>) -> DBVTLeafId {
        if self.is_empty() {
            let new_id = self.leaves.insert(leaf);
            self.leaves[new_id].parent = DBVTInternalId::Root;
            self.root = DBVTNodeId::Leaf(new_id);

            return DBVTLeafId(new_id);
        }

        match self.root {
            DBVTNodeId::Internal(_) => {
                let mut curr = self.root;

                loop {
                    match curr {
                        DBVTNodeId::Internal(id) => {
                            // FIXME: we could avoid the systematic merge
                            let (left, right) = {
                                let node = &mut self.internals[id];
                                node.bounding_volume.merge(&leaf.bounding_volume);
                                (node.left, node.right)
                            };

                            let dist1 = match left {
                                DBVTNodeId::Leaf(l) => {
                                    na::distance_squared(&self.leaves[l].center, &leaf.center)
                                }
                                DBVTNodeId::Internal(i) => {
                                    na::distance_squared(&self.internals[i].center, &leaf.center)
                                }
                            };

                            let dist2 = match right {
                                DBVTNodeId::Leaf(l) => {
                                    na::distance_squared(&self.leaves[l].center, &leaf.center)
                                }
                                DBVTNodeId::Internal(i) => {
                                    na::distance_squared(&self.internals[i].center, &leaf.center)
                                }
                            };

                            curr = if dist1 < dist2 { left } else { right };
                        }
                        DBVTNodeId::Leaf(id) => {
                            let parent_bv = self.leaves[id]
                                .bounding_volume
                                .merged(&leaf.bounding_volume);
                            let grand_parent = self.leaves[id].parent;

                            let new_id = self.leaves.insert(leaf);
                            let parent = DBVTInternal::new(
                                parent_bv,
                                grand_parent,
                                curr,
                                DBVTNodeId::Leaf(new_id),
                            );
                            let parent_id = self.internals.insert(parent);
                            self.leaves[id].parent = DBVTInternalId::LeftChildOf(parent_id);
                            self.leaves[new_id].parent = DBVTInternalId::RightChildOf(parent_id);

                            match grand_parent {
                                DBVTInternalId::LeftChildOf(pp) => {
                                    self.internals[pp].left = DBVTNodeId::Internal(parent_id)
                                }
                                DBVTInternalId::RightChildOf(pp) => {
                                    self.internals[pp].right = DBVTNodeId::Internal(parent_id)
                                }
                                _ => unreachable!(),
                            }

                            break DBVTLeafId(new_id);
                        }
                    }
                }
            }
            DBVTNodeId::Leaf(id) => {
                let new_id = self.leaves.insert(leaf);

                // Create a common parent which is the new root.
                let root_bv = self.leaves[id]
                    .bounding_volume
                    .merged(&self.leaves[new_id].bounding_volume);
                let root = DBVTInternal::new(
                    root_bv,
                    DBVTInternalId::Root,
                    DBVTNodeId::Leaf(id),
                    DBVTNodeId::Leaf(new_id),
                );

                let root_id = self.internals.insert(root);
                self.leaves[id].parent = DBVTInternalId::LeftChildOf(root_id);
                self.leaves[new_id].parent = DBVTInternalId::RightChildOf(root_id);
                self.root = DBVTNodeId::Internal(root_id);

                DBVTLeafId(new_id)
            }
        }
    }

    /// Removes a leaf from this DBVT.
    ///
    /// Panics if the provided leaf is not attached to this DBVT.
    pub fn remove(&mut self, leaf_id: DBVTLeafId) -> DBVTLeaf<N, B, BV> {
        let DBVTLeafId(leaf_id) = leaf_id;
        let leaf = self.leaves.remove(leaf_id);

        if !leaf.is_root() {
            let p;
            let other;

            match leaf.parent {
                DBVTInternalId::RightChildOf(parent) => {
                    other = self.internals[parent].left;
                    p = parent;
                }
                DBVTInternalId::LeftChildOf(parent) => {
                    other = self.internals[parent].right;
                    p = parent;
                }
                DBVTInternalId::Root => unreachable!(),
            }

            match self.internals[p].parent {
                DBVTInternalId::RightChildOf(pp) => {
                    match other {
                        DBVTNodeId::Internal(id) => {
                            self.internals[id].parent = DBVTInternalId::RightChildOf(pp)
                        }
                        DBVTNodeId::Leaf(id) => {
                            self.leaves[id].parent = DBVTInternalId::RightChildOf(pp)
                        }
                    }

                    self.internals[pp].right = other;
                    self.internals[pp].state = UpdateStatus::NeedsShrink;
                }
                DBVTInternalId::LeftChildOf(pp) => {
                    match other {
                        DBVTNodeId::Internal(id) => {
                            self.internals[id].parent = DBVTInternalId::LeftChildOf(pp)
                        }
                        DBVTNodeId::Leaf(id) => {
                            self.leaves[id].parent = DBVTInternalId::LeftChildOf(pp)
                        }
                    }

                    self.internals[pp].left = other;
                    self.internals[pp].state = UpdateStatus::NeedsShrink;
                }
                DBVTInternalId::Root => {
                    // The root changes to the other child.
                    match other {
                        DBVTNodeId::Leaf(id) => self.leaves[id].parent = DBVTInternalId::Root,
                        DBVTNodeId::Internal(id) => {
                            self.internals[id].parent = DBVTInternalId::Root
                        }
                    }

                    self.root = other;
                }
            }

            let _ = self.internals.remove(p);
        } else {
            // The tree is now empty.
            self.leaves.clear();
            self.internals.clear();
        }

        leaf
    }

    /// Traverses this tree using an object implementing the `BVTVisitor`trait.
    ///
    /// This will traverse the whole tree and call the visitor `.visit_internal(...)` (resp.
    /// `.visit_leaf(...)`) method on each internal (resp. leaf) node.
    pub fn visit<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis) {
        if !self.is_empty() {
            self.visit_node(visitor, self.root);
        }
    }

    fn visit_node<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis, node: DBVTNodeId) {
        match node {
            DBVTNodeId::Internal(i) => {
                let internal = &self.internals[i];
                if visitor.visit_internal(&internal.bounding_volume) {
                    self.visit_node(visitor, internal.left);
                    self.visit_node(visitor, internal.right);
                }
            }
            DBVTNodeId::Leaf(i) => {
                let leaf = &self.leaves[i];
                visitor.visit_leaf(&leaf.data, &leaf.bounding_volume);
            }
        }
    }
}

impl<N: Real, B, BV> Index<DBVTLeafId> for DBVT<N, B, BV> {
    type Output = DBVTLeaf<N, B, BV>;

    #[inline]
    fn index(&self, DBVTLeafId(id): DBVTLeafId) -> &Self::Output {
        &self.leaves[id]
    }
}
<|endoftext|>


<commit_before>use board;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Coordinate {
    pub row: usize,
    pub col: usize,
}

impl Coordinate {
    pub fn move_in(&self, dir: Direction, delta: usize) -> Option<Coordinate> {
        match dir {
            Direction::Up => if self.row >= delta { Some(Coordinate{row: self.row - delta, col: self.col}) } else { None },
            Direction::Down => if self.row + delta < board::NUM_ROWS { Some(Coordinate{row: self.row + delta, col: self.col}) } else { None },
            Direction::Left => if self.col >= delta { Some(Coordinate{row: self.row, col: self.col - delta}) } else { None },
            Direction::Right => if self.col + delta < board::NUM_COLS { Some(Coordinate{row: self.row, col: self.col + delta}) } else { None },
        }
    }

    pub fn induces_board_type(&self) -> bool {
        // The lower left corner of the board.
        self.col < 2 && self.row >= 1
    }
}

#[derive(Copy, Clone)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}
pub const POSSIBLE_DIRECTIONS: [Direction; 4] = [
    Direction::Up,
    Direction::Down,
    Direction::Left,
    Direction::Right,
];

#[derive(Copy, Clone, Debug)]
pub enum MoveType {
    Single,
    OneUp,
    OneDown,
    OneLeft,
    OneRight,
    TwoUp,
    TwoDown,
    TwoLeft,
    TwoRight,
    UpAndDown,
    LeftAndRight,
}
pub const POSSIBLE_MOVE_TYPES: [MoveType; 11] = [
    MoveType::Single,
    MoveType::OneUp,
    MoveType::OneDown,
    MoveType::OneLeft,
    MoveType::OneRight,
    MoveType::TwoUp,
    MoveType::TwoDown,
    MoveType::TwoLeft,
    MoveType::TwoRight,
    MoveType::UpAndDown,
    MoveType::LeftAndRight,
];

#[derive(Copy, Clone, Debug)]
pub struct Move {
    pub coord: Coordinate,
    move_type: MoveType,
    pub old_board_type: Option<board::BoardType>,
    pub new_board_type: Option<board::BoardType>,
}

impl Move {
    pub fn new(coord: Coordinate, move_type: MoveType, old_board_type: Option<board::BoardType>) -> Option<Move> {
        let c = Move{coord: coord, move_type: move_type, old_board_type: old_board_type, new_board_type: None};
        if c.in_bounds() { Some(c) } else { None }
    }

    pub fn with_board_type(&self, new_board_type: board::BoardType) -> Move {
        Move{new_board_type: Some(new_board_type), .. *self}
    }

    pub fn in_bounds(&self) -> bool {
        match self.move_type {
            MoveType::Single => true,
            MoveType::OneUp => self.coord.row >= 1,
            MoveType::OneDown => self.coord.row < board::NUM_ROWS - 1,
            MoveType::OneLeft => self.coord.col >= 1,
            MoveType::OneRight => self.coord.col < board::NUM_COLS - 1,
            MoveType::TwoUp => self.coord.row >= 2,
            MoveType::TwoDown => self.coord.row < board::NUM_ROWS - 2,
            MoveType::TwoLeft => self.coord.col >= 2,
            MoveType::TwoRight => self.coord.col < board::NUM_COLS - 2,
            MoveType::UpAndDown => self.coord.row >= 1 && self.coord.row < board::NUM_ROWS - 1,
            MoveType::LeftAndRight => self.coord.col >= 1 && self.coord.col < board::NUM_COLS - 1,
        }
    }

    pub fn extensions(&self) -> Vec<Coordinate> {
        match self.move_type {
            MoveType::Single => vec![],
            MoveType::OneUp => vec![self.coord.move_in(Direction::Up, 1).unwrap()],
            MoveType::OneDown => vec![self.coord.move_in(Direction::Down, 1).unwrap()],
            MoveType::OneLeft => vec![self.coord.move_in(Direction::Left, 1).unwrap()],
            MoveType::OneRight => vec![self.coord.move_in(Direction::Right, 1).unwrap()],
            MoveType::TwoUp => vec![self.coord.move_in(Direction::Up, 1).unwrap(), self.coord.move_in(Direction::Up, 2).unwrap()],
            MoveType::TwoDown => vec![self.coord.move_in(Direction::Down, 1).unwrap(), self.coord.move_in(Direction::Down, 2).unwrap()],
            MoveType::TwoLeft => vec![self.coord.move_in(Direction::Left, 1).unwrap(), self.coord.move_in(Direction::Left, 2).unwrap()],
            MoveType::TwoRight => vec![self.coord.move_in(Direction::Right, 1).unwrap(), self.coord.move_in(Direction::Right, 2).unwrap()],
            MoveType::UpAndDown => vec![self.coord.move_in(Direction::Up, 1).unwrap(), self.coord.move_in(Direction::Down, 1).unwrap()],
            MoveType::LeftAndRight => vec![self.coord.move_in(Direction::Left, 1).unwrap(), self.coord.move_in(Direction::Right, 1).unwrap()],
        }
    }
}
<commit_msg>Move: create unchecked coordinates<commit_after>use board;

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct Coordinate {
    pub row: usize,
    pub col: usize,
}

impl Coordinate {
    pub fn move_in(&self, dir: Direction, delta: usize) -> Option<Coordinate> {
        match dir {
            Direction::Up => if self.row >= delta { Some(Coordinate{row: self.row - delta, col: self.col}) } else { None },
            Direction::Down => if self.row + delta < board::NUM_ROWS { Some(Coordinate{row: self.row + delta, col: self.col}) } else { None },
            Direction::Left => if self.col >= delta { Some(Coordinate{row: self.row, col: self.col - delta}) } else { None },
            Direction::Right => if self.col + delta < board::NUM_COLS { Some(Coordinate{row: self.row, col: self.col + delta}) } else { None },
        }
    }

    fn unchecked_move_in(&self, dir: Direction, delta: usize) -> Coordinate {
        match dir {
            Direction::Up => Coordinate{row: self.row - delta, col: self.col},
            Direction::Down => Coordinate{row: self.row + delta, col: self.col},
            Direction::Left => Coordinate{row: self.row, col: self.col - delta},
            Direction::Right => Coordinate{row: self.row, col: self.col + delta},
        }
    }

    pub fn induces_board_type(&self) -> bool {
        // The lower left corner of the board.
        self.col < 2 && self.row >= 1
    }
}

#[derive(Copy, Clone)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}
pub const POSSIBLE_DIRECTIONS: [Direction; 4] = [
    Direction::Up,
    Direction::Down,
    Direction::Left,
    Direction::Right,
];

#[derive(Copy, Clone, Debug)]
pub enum MoveType {
    Single,
    OneUp,
    OneDown,
    OneLeft,
    OneRight,
    TwoUp,
    TwoDown,
    TwoLeft,
    TwoRight,
    UpAndDown,
    LeftAndRight,
}
pub const POSSIBLE_MOVE_TYPES: [MoveType; 11] = [
    MoveType::Single,
    MoveType::OneUp,
    MoveType::OneDown,
    MoveType::OneLeft,
    MoveType::OneRight,
    MoveType::TwoUp,
    MoveType::TwoDown,
    MoveType::TwoLeft,
    MoveType::TwoRight,
    MoveType::UpAndDown,
    MoveType::LeftAndRight,
];

#[derive(Copy, Clone, Debug)]
pub struct Move {
    pub coord: Coordinate,
    move_type: MoveType,
    pub old_board_type: Option<board::BoardType>,
    pub new_board_type: Option<board::BoardType>,
}

impl Move {
    pub fn new(coord: Coordinate, move_type: MoveType, old_board_type: Option<board::BoardType>) -> Option<Move> {
        let c = Move{coord: coord, move_type: move_type, old_board_type: old_board_type, new_board_type: None};
        if c.in_bounds() { Some(c) } else { None }
    }

    pub fn with_board_type(&self, new_board_type: board::BoardType) -> Move {
        Move{new_board_type: Some(new_board_type), .. *self}
    }

    pub fn in_bounds(&self) -> bool {
        match self.move_type {
            MoveType::Single => true,
            MoveType::OneUp => self.coord.row >= 1,
            MoveType::OneDown => self.coord.row < board::NUM_ROWS - 1,
            MoveType::OneLeft => self.coord.col >= 1,
            MoveType::OneRight => self.coord.col < board::NUM_COLS - 1,
            MoveType::TwoUp => self.coord.row >= 2,
            MoveType::TwoDown => self.coord.row < board::NUM_ROWS - 2,
            MoveType::TwoLeft => self.coord.col >= 2,
            MoveType::TwoRight => self.coord.col < board::NUM_COLS - 2,
            MoveType::UpAndDown => self.coord.row >= 1 && self.coord.row < board::NUM_ROWS - 1,
            MoveType::LeftAndRight => self.coord.col >= 1 && self.coord.col < board::NUM_COLS - 1,
        }
    }

    pub fn extensions(&self) -> Vec<Coordinate> {
        match self.move_type {
            MoveType::Single => vec![],
            MoveType::OneUp => vec![self.coord.unchecked_move_in(Direction::Up, 1)],
            MoveType::OneDown => vec![self.coord.unchecked_move_in(Direction::Down, 1)],
            MoveType::OneLeft => vec![self.coord.unchecked_move_in(Direction::Left, 1)],
            MoveType::OneRight => vec![self.coord.unchecked_move_in(Direction::Right, 1)],
            MoveType::TwoUp => vec![self.coord.unchecked_move_in(Direction::Up, 1), self.coord.unchecked_move_in(Direction::Up, 2)],
            MoveType::TwoDown => vec![self.coord.unchecked_move_in(Direction::Down, 1), self.coord.unchecked_move_in(Direction::Down, 2)],
            MoveType::TwoLeft => vec![self.coord.unchecked_move_in(Direction::Left, 1), self.coord.unchecked_move_in(Direction::Left, 2)],
            MoveType::TwoRight => vec![self.coord.unchecked_move_in(Direction::Right, 1), self.coord.unchecked_move_in(Direction::Right, 2)],
            MoveType::UpAndDown => vec![self.coord.unchecked_move_in(Direction::Up, 1), self.coord.unchecked_move_in(Direction::Down, 1)],
            MoveType::LeftAndRight => vec![self.coord.unchecked_move_in(Direction::Left, 1), self.coord.unchecked_move_in(Direction::Right, 1)],
        }
    }
}
<|endoftext|>


<commit_before>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn (needle: str, haystack: str, nn: uint) -> [uint] {

   let results = [];

   // empty haystack
   if str::len(haystack) == 0u {
      ret results;
   }

   // empty needle
   if str::len(needle) == 0u {
      vec::push(results, 0u);
      ret results;
   }

   // needle too large
   if str::len(haystack) < str::len(needle) {
      ret results;
   }

   // generate the tables
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   // simplify the table referencing
   let getShift = fn@(pos: uint) -> uint {
      let charShift, prefShift; // also: ct, pt, needle

      assert needle != "";
      assert pos >= 0u;
      assert pos < str::len(needle);

      alt ct.find(needle[pos] as uint) {
         option::none    { charShift = str::len(needle);}
         option::some(x) { charShift = x;}
      }

      let offset = str::len(needle) - pos;

      assert offset >= 0u;
      assert offset < str::len(needle);

      alt pt.find(offset) {
         option::none { fail "something is out of range" }
         option::some(x) { prefShift = x;}
      }

      std::io::println(#fmt("<charShift: %u, prefShift: %u>", charShift, prefShift));
      ret greaterOf(charShift, prefShift);
   };

   let outerLim  = str::len(haystack);
   let windowLim = str::len(needle);

   // step up through the haystack
   let outerii = 0u;
   while outerii < outerLim - windowLim + 1u {

      // step back through needle
      let windowii = windowLim;
      while 0u < windowii
            && (outerii + (windowii - 1u)) < outerLim  // don't exceed haystack
      {
         windowii -= 1u;

         //std::io::println(#fmt("%c@%u =? %c@%u",
         std::io::println(#fmt("%02x.@%u =? %02x.@%u",
                          needle[windowii] as uint,
                          windowii,
                          haystack[outerii+windowii] as uint,
                          outerii + windowii));

         // if still matching
         if needle[windowii] == haystack[outerii+windowii] {

            // if full match
            if windowii == 0u {
               std::io::println(#fmt("[pushing %u]", outerii));
               vec::push(results, outerii);

               if vec::len(results) >= nn {
                  ret results;
               } else {
                  outerii += windowLim;
               }
            }
         } else {
            outerii +=
               if windowii == windowLim - 1u {
                  // not matching yet
                  1u
               } else {
                  // partial match
                  getShift(windowLim - windowii)
               };

            break;
         }
      }
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len(needle);

   let jj = len - 1u; // drop the last byte

   assert jj >= 0u;
   assert jj < str::len(needle);

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> unsafe {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   // WAIT, HOW IS THIS ALLOWED TO MUTATE mm?
   let fill = fn@(kk: uint, vv: uint) {
      if ! mm.contains_key(kk) {
         mm.insert(kk, vv);
         std::io::println(#fmt("%u => %u", kk, vv));
      }
   };

   let lim   = str::len(needle);
   assert 0u < lim;

   // step to larger suffixes
   let sii = 0u;
   while sii < lim {

      // tail of the needle we seek
      let suffix      = str::unsafe::slice_bytes(needle, lim - sii,      lim);
      let suffix_plus = str::unsafe::slice_bytes(needle, lim - sii - 1u, lim);
      let slen = str::len(suffix);

      // step to smaller prefixes
      let pii = lim - 1u;
      while pii > 0u {

         // a prefix of the needle that might be matched by
         // a partial match of a suffix
         // (which we might want to jump to)
         let prefix = str::unsafe::slice_bytes(needle, 0u, pii);

         //let msg  = "<"+suffix+"("+#fmt("%u",sii)+")";
         //let msg2 = prefix+"("+#fmt("%u",pii)+")>";
         let msg  = "<suf("+#fmt("%u",sii)+")";
         let msg2 = "pref("+#fmt("%u",pii)+")>";
         std::io::println(msg + " × " + msg2);

         // suffix might be fully matched
         let is_suffix_matched =
            str::ends_with(prefix, suffix)
            && !str::ends_with(prefix, suffix_plus)
            &&  slen < str::len(prefix);

         // prefix is bigger than suffix, only tail can match
         let is_suffix_partially_matched =
            str::len(prefix) <= str::len(suffix)
            && str::ends_with(suffix, prefix);

         if is_suffix_matched || is_suffix_partially_matched {
            fill(sii, lim-pii);
         }

         pii -= 1u;
      }

      // no matching prefix
      fill(sii, lim-pii);

      sii += 1u;
   }

   ret mm;
}

#[test]
fn test_prefix_table_ascii() {
   let pt = prefix_table("ANPANMAN");
                            //      ... 8

   assert 1u == pt.get(0u); //        (n)
   assert 8u == pt.get(1u); //       (a)n
   assert 3u == pt.get(2u); //      (m)an
   assert 6u == pt.get(3u); //     (n)man
   assert 6u == pt.get(4u); //    (a)nman
   assert 6u == pt.get(5u); //   (p)anman
   assert 6u == pt.get(6u); //  (n)panman
   assert 6u == pt.get(7u); // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

#[test]
fn test_prefix_table_utf8() {
   let pt = prefix_table("ประเ");

   assert  1u == pt.get(0u);
   assert 12u == pt.get(3u);
   assert 12u == pt.get(6u);
   assert 12u == pt.get(9u);
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];

   vec::push(vv, "");
   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, 0u, ii+1u));
   }

   ret vv;
}

#[test]
fn test_prefs() {
   assert ["", "a", "ab", "abc", "abcd"] == prefixes("abcd");
   assert [""] == prefixes("");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let lim = str::len(ss);

   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, ii, lim));
   }
   vec::push(vv, "");

   ret vv;
}

#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d", ""] == suffixes("abcd");
   assert [""] == suffixes("");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_(needle: str, haystack: str) -> option<uint> {
   let found = findn(needle, haystack, 1u);

   alt vec::len(found) {
      0u { option::none }
      xx { option::some(found[0u]) }
   }
}

#[test]
fn test_findn() {
   assert [] == findn("banana", "apple pie", 1u);
   assert (findn("abc", "abcxxxxxx", 1u) == [0u]);
   assert (findn("abc", "xxxabcxxx", 1u) == [3u]);
   assert (findn("abc", "xxxxxxabc", 1u) == [6u]);
   assert (findn("abc", "xxxabcabc", 1u) == [3u]);
   assert (findn("abc", "xxxabcabc", 5u) == [3u, 6u]);
   assert (findn("abc", "xxxabcxabc", 5u) == [3u, 7u]);
   assert (findn("abc", "xxxabcxxabc", 5u) == [3u, 8u]);
}

#[test]
fn test_find_ascii() {
  assert (find_("banana", "apple pie") == option::none);
  assert (find_("", "") == option::none);
  assert (find_("abc", "abcxxxxxx") == option::some(0u));
  assert (find_("abc", "xxxabcxxx") == option::some(3u));
  assert (find_("abc", "xxxxxxabc") == option::some(6u));
}

#[test]
fn test_find_utf8() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_("ไท华", data) == option::none);
  assert (find_("", data)     == option::some( 0u));
  assert (find_("ประเ", data) == option::some( 0u));
  assert (find_("ะเ", data)   == option::some( 6u));
  assert (find_("ระ", data) == option::some(3u));
  assert (find_("ศไทย中华", data) == option::some(15u));
  assert (find_("ไทย中华", data) == option::some(18u));
  assert (find_("ย中华", data) == option::some(24u));
  assert (find_("中华", data) == option::some(27u));
}

<commit_msg>working fully?<commit_after>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn (needle: str, haystack: str, nn: uint) -> [uint] {

   let results = [];

   // empty haystack
   if str::len(haystack) == 0u {
      ret results;
   }

   // empty needle
   if str::len(needle) == 0u {
      vec::push(results, 0u);
      ret results;
   }

   // needle too large
   if str::len(haystack) < str::len(needle) {
      ret results;
   }

   // generate the tables
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   // simplify the table referencing
   let getShift = fn@(pos: uint) -> uint {
      let charShift, prefShift; // also: ct, pt, needle

      assert needle != "";
      assert pos >= 0u;
      assert pos < str::len(needle);

      alt ct.find(needle[pos] as uint) {
         option::none    { charShift = str::len(needle);}
         option::some(x) { charShift = x;}
      }

      let offset = str::len(needle) - pos;

      assert offset >= 0u;
      assert offset < str::len(needle);

      alt pt.find(offset) {
         option::none { fail "something is out of range" }
         option::some(x) { prefShift = x;}
      }

      std::io::println(#fmt("<charShift: %u, prefShift: %u>", charShift, prefShift));
      ret greaterOf(charShift, prefShift);
   };

   let outerLim  = str::len(haystack);
   let windowLim = str::len(needle);

   // step up through the haystack
   let outerii = 0u;
   while outerii < outerLim - windowLim + 1u {

      // step back through needle
      let windowii = windowLim;
      while 0u < windowii
            && (outerii + (windowii - 1u)) < outerLim  // don't exceed haystack
      {
         windowii -= 1u;

         //std::io::println(#fmt("%c@%u =? %c@%u",
         std::io::println(#fmt("%02x.@%u =? %02x.@%u",
                          needle[windowii] as uint,
                          windowii,
                          haystack[outerii+windowii] as uint,
                          outerii + windowii));

         // if still matching
         if needle[windowii] == haystack[outerii+windowii] {

            // if full match
            if windowii == 0u {
               std::io::println(#fmt("[pushing %u]", outerii));
               vec::push(results, outerii);

               if vec::len(results) >= nn {
                  ret results;
               } else {
                  outerii += windowLim;
               }
            }
         } else {
            outerii +=
               if windowii == windowLim - 1u {
                  // not matching yet
                  1u
               } else {
                  // partial match
                  getShift(windowLim - windowii)
               };

            break;
         }
      }
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len(needle);

   let jj = len - 1u; // drop the last byte

   assert jj >= 0u;
   assert jj < str::len(needle);

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

// FIXME: generalize this beyond strings
fn prefix_table (needle: str) -> std::map::map<uint, uint> unsafe {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   // WAIT, HOW IS THIS ALLOWED TO MUTATE mm?
   let fill = fn@(kk: uint, vv: uint) {
      if ! mm.contains_key(kk) {
         mm.insert(kk, vv);
         std::io::println(#fmt("%u => %u", kk, vv));
      }
   };

   let lim   = str::len(needle);
   assert 0u < lim;

   // step to larger suffixes
   let sii = 0u;
   while sii < lim {

      // tail of the needle we seek
      let suffix      = str::unsafe::slice_bytes(needle, lim - sii,      lim);
      let suffix_plus = str::unsafe::slice_bytes(needle, lim - sii - 1u, lim);
      let slen = str::len(suffix);

      // step to smaller prefixes
      let pii = lim - 1u;
      while pii > 0u {

         // a prefix of the needle that might be matched by
         // a partial match of a suffix
         // (which we might want to jump to)
         let prefix = str::unsafe::slice_bytes(needle, 0u, pii);

         //let msg  = "<"+suffix+"("+#fmt("%u",sii)+")";
         //let msg2 = prefix+"("+#fmt("%u",pii)+")>";
         let msg  = "<suf("+#fmt("%u",sii)+")";
         let msg2 = "pref("+#fmt("%u",pii)+")>";
         std::io::println(msg + " × " + msg2);

         // suffix might be fully matched
         let is_suffix_matched =
            str::ends_with(prefix, suffix)
            && !str::ends_with(prefix, suffix_plus)
            &&  slen < str::len(prefix);

         // prefix is bigger than suffix, only tail can match
         let is_suffix_partially_matched =
            str::len(prefix) <= str::len(suffix)
            && str::ends_with(suffix, prefix);

         if is_suffix_matched || is_suffix_partially_matched {
            fill(sii, lim-pii);
         }

         pii -= 1u;
      }

      // no matching prefix
      fill(sii, lim-pii);

      sii += 1u;
   }

   ret mm;
}

#[test]
fn test_prefix_table_ascii() {
   let pt = prefix_table("ANPANMAN");
                            //      ... 8

   assert 1u == pt.get(0u); //        (n)
   assert 8u == pt.get(1u); //       (a)n
   assert 3u == pt.get(2u); //      (m)an
   assert 6u == pt.get(3u); //     (n)man
   assert 6u == pt.get(4u); //    (a)nman
   assert 6u == pt.get(5u); //   (p)anman
   assert 6u == pt.get(6u); //  (n)panman
   assert 6u == pt.get(7u); // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

#[test]
fn test_prefix_table_utf8() {
   let pt = prefix_table("ประเ");

   assert  1u == pt.get(0u);
   assert 12u == pt.get(3u);
   assert 12u == pt.get(6u);
   assert 12u == pt.get(9u);
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];

   vec::push(vv, "");
   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, 0u, ii+1u));
   }

   ret vv;
}

#[test]
fn test_prefs() {
   assert ["", "a", "ab", "abc", "abcd"] == prefixes("abcd");
   assert [""] == prefixes("");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let lim = str::len(ss);

   str::chars_iteri(ss) {|ii, _bb|
      vec::push(vv, str::slice(ss, ii, lim));
   }
   vec::push(vv, "");

   ret vv;
}

#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d", ""] == suffixes("abcd");
   assert [""] == suffixes("");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_(needle: str, haystack: str) -> option<uint> {
   let found = findn(needle, haystack, 1u);

   alt vec::len(found) {
      0u { option::none }
      xx { option::some(found[0u]) }
   }
}

#[test]
fn test_findn() {
   assert [] == findn("banana", "apple pie", 1u);
   assert (findn("abc", "abcxxxxxx", 1u) == [0u]);
   assert (findn("abc", "xxxabcxxx", 1u) == [3u]);
   assert (findn("abc", "xxxxxxabc", 1u) == [6u]);
   assert (findn("abc", "xxxabcabc", 1u) == [3u]);
   assert (findn("abc", "xxxabcabc", 5u) == [3u, 6u]);
   assert (findn("abc", "xxxabcxabc", 5u) == [3u, 7u]);
   assert (findn("abc", "xxxabcxxabc", 5u) == [3u, 8u]);
}

#[test]
fn test_find_ascii() {
  assert (find_("banana", "apple pie") == option::none);
  assert (find_("", "") == option::none);
  assert (find_("abc", "abcxxxxxx") == option::some(0u));
  assert (find_("abc", "xxxabcxxx") == option::some(3u));
  assert (find_("abc", "xxxxxxabc") == option::some(6u));
}

#[test]
fn test_find_utf8() {
  let data = "ประเทศไทย中华Việt Nam";
  assert (find_("ไท华", data) == option::none);
  assert (find_("", data)     == option::some( 0u));
  assert (find_("ประเ", data) == option::some( 0u));
  assert (find_("ะเ", data)   == option::some( 6u));
  assert (find_("ระ", data) == option::some(3u));
  assert (find_("ศไทย中华", data) == option::some(15u));
  assert (find_("ไทย中华", data) == option::some(18u));
  assert (find_("ย中华", data) == option::some(24u));
  assert (find_("中华", data) == option::some(27u));
}

<|endoftext|>


<commit_before>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Core/threads/sleep_object.rs
//! Sleep object
use _common::*;
use super::thread::{Thread, RunState};

/// An object on which a thread can sleep, woken by various event sources
pub struct SleepObject
{
	name: &'static str,
	thread: Option<Box<Thread>>,
}

/// Referece to an active sleep object
pub struct SleepObjectRef
{
	obj: *const SleepObject,
}

//pub const SLEEPOBJECT_INIT: SleepObject = SleepObject { name: "", thread: None };

impl SleepObject
{
	/// Create a new sleep object
	pub fn new(name: &'static str) -> SleepObject
	{
		SleepObject {
			name: name,
			thread: None,
		}
	}

	/// Wait the current thread on this object
	pub fn wait(&mut self)
	{
		log_trace!("SleepObject::wait '{}'", self.name);
		let mut cur = super::get_cur_thread();
		cur.run_state = RunState::Sleep(self as *mut _ as *const _);
		self.thread = Some(cur);
		super::reschedule();

		let cur = self.thread.take().unwrap();
		assert!( !is!(cur.run_state, RunState::Sleep(_)) );
		assert!( is!(cur.run_state, RunState::Runnable) );
		super::rel_cur_thread(cur);
	}

	/// Signal this sleep object (waking threads)
	pub fn signal(&self)
	{
		todo!("SleepObject::signal '{}'", self.name);
	}

	/// Obtain a reference to the sleep object
	pub fn get_ref(&self) -> SleepObjectRef {
		SleepObjectRef {
			obj: self as *const _,
		}
	}
}

unsafe impl ::core::marker::Send for SleepObjectRef {}

impl ::core::ops::Deref for SleepObjectRef
{
	type Target = SleepObject;

	fn deref(&self) -> &SleepObject {
		unsafe { &*self.obj }
	}
}

<commit_msg>Kernel/threads - Implement signal in SleepObject<commit_after>// "Tifflin" Kernel
// - By John Hodge (thePowersGang)
//
// Core/threads/sleep_object.rs
//! Sleep object
use _common::*;
use super::thread::{Thread, RunState};
use super::s_runnable_threads;

/// An object on which a thread can sleep, woken by various event sources
pub struct SleepObject
{
	name: &'static str,
	inner: ::sync::Spinlock< SleepObjectInner >,
}
#[derive(Default)]
struct SleepObjectInner
{
	flag: bool,
	thread: Option<Box<Thread>>,
}

/// Referece to an active sleep object
pub struct SleepObjectRef
{
	obj: *const SleepObject,
}

impl SleepObject
{
	/// Create a new sleep object
	pub fn new(name: &'static str) -> SleepObject
	{
		SleepObject {
			name: name,
			inner: Default::default(),
		}
	}

	/// Wait the current thread on this object
	pub fn wait(&self)
	{
		log_trace!("SleepObject::wait '{}'", self.name);

		let irql = ::sync::hold_interrupts();
		let mut lh = self.inner.lock();
		assert!( lh.thread.is_none(), "A thread is already sleeping on object {:p} '{}'", self, self.name );

		if lh.flag == false
		{
			let mut cur = super::get_cur_thread();
			cur.run_state = RunState::Sleep(self as *const _);
			lh.thread = Some(cur);

			::core::mem::drop(lh);
			::core::mem::drop(irql);

			super::reschedule();

			let cur = super::get_cur_thread();
			assert!( !is!(cur.run_state, RunState::Sleep(_)) );
			assert!( is!(cur.run_state, RunState::Runnable) );
			super::rel_cur_thread(cur);
		}
		else
		{
			lh.flag = false;
		}
	}

	/// Signal this sleep object (waking threads)
	pub fn signal(&self)
	{
		let mut lh = self.inner.lock();
		// 1. Check for a waiter
		if let Some(mut t) = lh.thread.take()
		{
			t.set_state( RunState::Runnable );
                        let _irq_lock = ::sync::hold_interrupts();
			s_runnable_threads.lock().push(t);
		}
		else
		{
			lh.flag = true;
		}
	}

	/// Obtain a reference to the sleep object
	pub fn get_ref(&self) -> SleepObjectRef {
		SleepObjectRef {
			obj: self as *const _,
		}
	}
}

unsafe impl ::core::marker::Send for SleepObjectRef {}

impl ::core::ops::Deref for SleepObjectRef
{
	type Target = SleepObject;

	fn deref(&self) -> &SleepObject {
		unsafe { &*self.obj }
	}
}

<|endoftext|>


<commit_before>#![feature(globs)]
#![feature(macro_rules)]

extern crate deuterium;
extern crate time;

use deuterium::*;

#[macro_export]
macro_rules! assert_sql(
    ($query:expr, $s:expr) => (
        assert_eq!($query.to_final_sql().as_slice(), $s)
    )
)

mod select;
mod where_;

#[test]
fn select_1_first() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.select_1(&name).where_(
        name.is("Luke".to_string()).exclude()
    ).first().offset(10);

    assert_sql!(query, "SELECT name FROM jedi WHERE name != 'Luke' LIMIT 1 OFFSET 10;");

}

#[test]
fn select_order() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query: SelectQuery<(String), LimitOne, ()> = jedi_table.select_1(&name)
        .first().order_by(&name);

    assert_sql!(query, "SELECT name FROM jedi ORDER BY name ASC LIMIT 1;");

}

#[test]
fn select_within() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.select_all().where_(name.in_(vec!["Luke".to_string()]));
    assert_sql!(query, "SELECT * FROM jedi WHERE name IN ('Luke');");

}

#[test]
fn select_within_select() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.alias("j").select_all().where_(name.in_(
        jedi_table.select_1(&name)
    ));

    assert_sql!(query, "SELECT * FROM jedi AS j WHERE name IN (SELECT name FROM jedi);");

}

#[test]
fn select_from_select() {

    let jedi_table = TableDef::new("jedi");

    let query = jedi_table.select_all().alias("jedi_list").select_all();
    assert_sql!(query, "SELECT * FROM (SELECT * FROM jedi) as jedi_list;");

}

#[test]
fn select_left_join() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.select_all().left_join(&jedi_table.alias("j"), name.is(name.clone()));
    assert_sql!(query, "SELECT * FROM jedi LEFT JOIN jedi AS j ON name = name;");

}

#[test]
fn aliases() {

    let jedi_table = TableDef::new("jedi");
    let jedi_a = jedi_table.alias("a");
    let jedi_b = jedi_table.alias("b");
    let name_a = NamedField::<String>::field_of("name", &jedi_a);
    let name_b = NamedField::<String>::field_of("name", &jedi_b);

    let query = jedi_a.select_all().inner_join(&jedi_b, name_a.is(name_b));
    assert_sql!(query, "SELECT * FROM jedi AS a INNER JOIN jedi AS b ON a.name = b.name;");

}<commit_msg>refactor: remove obsolete specs<commit_after>#![feature(globs)]
#![feature(macro_rules)]

extern crate deuterium;
extern crate time;

use deuterium::*;

#[macro_export]
macro_rules! assert_sql(
    ($query:expr, $s:expr) => (
        assert_eq!($query.to_final_sql().as_slice(), $s)
    )
)

mod select;
mod where_;

#[test]
fn select_order() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query: SelectQuery<(String), LimitOne, ()> = jedi_table.select_1(&name)
        .first().order_by(&name);

    assert_sql!(query, "SELECT name FROM jedi ORDER BY name ASC LIMIT 1;");

}

#[test]
fn select_left_join() {

    let jedi_table = TableDef::new("jedi");
    let name = NamedField::<String>::field_of("name", &jedi_table);

    let query = jedi_table.select_all().left_join(&jedi_table.alias("j"), name.is(name.clone()));
    assert_sql!(query, "SELECT * FROM jedi LEFT JOIN jedi AS j ON name = name;");

}<|endoftext|>


<commit_before>extern crate rayon;
use self::rayon::prelude::*;

pub mod gofloat;
pub mod demosaic;
pub mod level;
pub mod colorspaces;
pub mod curves;
pub mod gamma;
pub mod transform;

use decoders::RawImage;

extern crate time;
extern crate toml;
extern crate serde;
extern crate serde_yaml;
use self::serde::Serialize;

use std::hash::{Hash, Hasher};
extern crate metrohash;
use self::metrohash::MetroHash;

use std::fmt::Debug;

extern crate multicache;
use self::multicache::MultiCache;
use std::sync::Arc;

#[derive(Debug, Clone, PartialEq)]
pub struct OpBuffer {
  pub width: usize,
  pub height: usize,
  pub colors: usize,
  pub data: Vec<f32>,
}

impl OpBuffer {
  pub fn new(width: usize, height: usize, colors: usize) -> OpBuffer {
    OpBuffer {
      width: width,
      height: height,
      colors: colors,
      data: vec![0.0; width*height*(colors as usize)],
    }
  }

  pub fn mutate_lines<F>(&mut self, closure: &F)
    where F : Fn(&mut [f32], usize)+Sync {

    self.data.par_chunks_mut(self.width*self.colors).enumerate().for_each(|(row, line)| {
      closure(line, row);
    });
  }

  pub fn process_into_new<F>(&self, colors: usize, closure: &F) -> OpBuffer
    where F : Fn(&mut [f32], &[f32])+Sync {

    let mut out = OpBuffer::new(self.width, self.height, colors);
    out.data.par_chunks_mut(out.width*out.colors).enumerate().for_each(|(row, line)| {
      closure(line, &self.data[self.width*self.colors*row..]);
    });
    out
  }

  /// Helper function to allow human readable creation of `OpBuffer` instances
  pub fn from_rgb_str_vec(data: Vec<&str>) -> OpBuffer {
    let width = data.first().expect("Invalid data for rgb helper function").len();
    let height = data.len();
    let colors = 3;

    let mut pixel_data: Vec<f32> = Vec::with_capacity(width * height * colors);
    for row in data {
      for col in row.chars() {
        let (r, g, b) = match col {
            'R' => (1.0, 0.0, 0.0),
            'G' => (0.0, 1.0, 0.0),
            'B' => (0.0, 0.0, 1.0),
            'O' => (1.0, 1.0, 1.0),
            ' ' => (0.0, 0.0, 0.0),
            c @ _ => panic!(format!(
              "Invalid color '{}' sent to rgb expected any of 'RGBO '", c)),
        };

        pixel_data.push(r);
        pixel_data.push(g);
        pixel_data.push(b);
      }
    }

    OpBuffer {
      width: width,
      height: height,
      colors: colors,
      data: pixel_data,
    }
  }
}

fn do_timing<O, F: FnMut() -> O>(name: &str, mut closure: F) -> O {
  let from_time = time::precise_time_ns();
  let ret = closure();
  let to_time = time::precise_time_ns();
  println!("{} ms for '{}'", (to_time - from_time)/1000000, name);

  ret
}

pub trait ImageOp<'a>: Debug+Hash+Serialize {
  fn name(&self) -> &str;
  fn run(&self, pipeline: &mut PipelineGlobals, inid: u64, outid: u64);
  fn to_settings(&self) -> String {
    serde_yaml::to_string(self).unwrap()
  }
}

#[derive(Debug)]
pub struct PipelineGlobals<'a> {
  cache: MultiCache<u64, OpBuffer>,
  maxwidth: usize,
  maxheight: usize,
  linear: bool,
  image: &'a RawImage,
}

#[derive(Debug)]
pub struct PipelineOps {
  gofloat: gofloat::OpGoFloat,
  demosaic: demosaic::OpDemosaic,
  level: level::OpLevel,
  tolab: colorspaces::OpToLab,
  basecurve: curves::OpBaseCurve,
  fromlab: colorspaces::OpFromLab,
  gamma: gamma::OpGamma,
  transform: transform::OpTransform,
}

macro_rules! for_vals {
  ([$($val:expr),*] |$x:pat| $body:expr) => {
    $({
      let $x = $val;
      $body
    })*
  }
}

macro_rules! all_ops {
  ($ops:expr, |$x:pat| $body:expr) => {
    for_vals!([
      $ops.gofloat,
      $ops.demosaic,
      $ops.level,
      $ops.tolab,
      $ops.basecurve,
      $ops.fromlab,
      $ops.gamma,
      $ops.transform
    ] |$x| {
      $body
    });
  }
}

#[derive(Debug)]
pub struct Pipeline<'a> {
  globals: PipelineGlobals<'a>,
  ops: PipelineOps,
}

impl<'a> Pipeline<'a> {
  pub fn new(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool) -> Pipeline {
    // Check if the image's orientation results in a rotation that
    // swaps the maximum width with the maximum height
    let (transpose, ..) = img.orientation.to_flips();
    let (maxwidth, maxheight) = if transpose {
      (maxheight, maxwidth)
    } else {
      (maxwidth, maxheight)
    };

    Pipeline {
      globals: PipelineGlobals {
        cache: MultiCache::new(1),
        maxwidth,
        maxheight,
        linear,
        image: img,
      },
      ops: PipelineOps {
        gofloat: gofloat::OpGoFloat::new(img),
        demosaic: demosaic::OpDemosaic::new(img),
        level: level::OpLevel::new(img),
        tolab: colorspaces::OpToLab::new(img),
        basecurve: curves::OpBaseCurve::new(img),
        fromlab: colorspaces::OpFromLab::new(img),
        gamma: gamma::OpGamma::new(img),
        transform: transform::OpTransform::new(img),
      },
    }
  }

  pub fn run(&mut self) -> Arc<OpBuffer> {
    // Generate all the hashes for the operations
    let mut hasher = MetroHash::new();
    let mut ophashes = Vec::new();
    all_ops!(self.ops, |ref op| {
      // Hash the name first as a zero sized struct doesn't actually do any hashing
      op.name().hash(&mut hasher);
      op.hash(&mut hasher);
      ophashes.push(hasher.finish());
    });

    // Do the operations, starting with a dummy buffer id as gofloat doesn't use it
    let mut bufin: u64 = 0;
    let mut pos = 0;
    all_ops!(self.ops, |ref op| {
      let globals = &mut self.globals;
      pos +=1;
      let hash = ophashes[pos-1];
      do_timing(op.name(), ||op.run(globals, bufin, hash));
      bufin = hash;
    });
    self.globals.cache.get(bufin).unwrap()
  }
}

fn simple_decode_full(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool) -> OpBuffer {
  let buf = {
    let mut pipeline = Pipeline::new(img, maxwidth, maxheight, linear);
    pipeline.run()
  };

  // Since we've kept the pipeline to ourselves unwraping always works
  Arc::try_unwrap(buf).unwrap()
}

pub fn simple_decode(img: &RawImage, maxwidth: usize, maxheight: usize) -> OpBuffer {
  simple_decode_full(img, maxwidth, maxheight, false)
}

pub fn simple_decode_linear(img: &RawImage, maxwidth: usize, maxheight: usize) -> OpBuffer {
  simple_decode_full(img, maxwidth, maxheight, true)
}
<commit_msg>imageops: slight cleanup of all_ops!<commit_after>extern crate rayon;
use self::rayon::prelude::*;

pub mod gofloat;
pub mod demosaic;
pub mod level;
pub mod colorspaces;
pub mod curves;
pub mod gamma;
pub mod transform;

use decoders::RawImage;

extern crate time;
extern crate toml;
extern crate serde;
extern crate serde_yaml;
use self::serde::Serialize;

use std::hash::{Hash, Hasher};
extern crate metrohash;
use self::metrohash::MetroHash;

use std::fmt::Debug;

extern crate multicache;
use self::multicache::MultiCache;
use std::sync::Arc;

#[derive(Debug, Clone, PartialEq)]
pub struct OpBuffer {
  pub width: usize,
  pub height: usize,
  pub colors: usize,
  pub data: Vec<f32>,
}

impl OpBuffer {
  pub fn new(width: usize, height: usize, colors: usize) -> OpBuffer {
    OpBuffer {
      width: width,
      height: height,
      colors: colors,
      data: vec![0.0; width*height*(colors as usize)],
    }
  }

  pub fn mutate_lines<F>(&mut self, closure: &F)
    where F : Fn(&mut [f32], usize)+Sync {

    self.data.par_chunks_mut(self.width*self.colors).enumerate().for_each(|(row, line)| {
      closure(line, row);
    });
  }

  pub fn process_into_new<F>(&self, colors: usize, closure: &F) -> OpBuffer
    where F : Fn(&mut [f32], &[f32])+Sync {

    let mut out = OpBuffer::new(self.width, self.height, colors);
    out.data.par_chunks_mut(out.width*out.colors).enumerate().for_each(|(row, line)| {
      closure(line, &self.data[self.width*self.colors*row..]);
    });
    out
  }

  /// Helper function to allow human readable creation of `OpBuffer` instances
  pub fn from_rgb_str_vec(data: Vec<&str>) -> OpBuffer {
    let width = data.first().expect("Invalid data for rgb helper function").len();
    let height = data.len();
    let colors = 3;

    let mut pixel_data: Vec<f32> = Vec::with_capacity(width * height * colors);
    for row in data {
      for col in row.chars() {
        let (r, g, b) = match col {
            'R' => (1.0, 0.0, 0.0),
            'G' => (0.0, 1.0, 0.0),
            'B' => (0.0, 0.0, 1.0),
            'O' => (1.0, 1.0, 1.0),
            ' ' => (0.0, 0.0, 0.0),
            c @ _ => panic!(format!(
              "Invalid color '{}' sent to rgb expected any of 'RGBO '", c)),
        };

        pixel_data.push(r);
        pixel_data.push(g);
        pixel_data.push(b);
      }
    }

    OpBuffer {
      width: width,
      height: height,
      colors: colors,
      data: pixel_data,
    }
  }
}

fn do_timing<O, F: FnMut() -> O>(name: &str, mut closure: F) -> O {
  let from_time = time::precise_time_ns();
  let ret = closure();
  let to_time = time::precise_time_ns();
  println!("{} ms for '{}'", (to_time - from_time)/1000000, name);

  ret
}

pub trait ImageOp<'a>: Debug+Hash+Serialize {
  fn name(&self) -> &str;
  fn run(&self, pipeline: &mut PipelineGlobals, inid: u64, outid: u64);
  fn to_settings(&self) -> String {
    serde_yaml::to_string(self).unwrap()
  }
}

#[derive(Debug)]
pub struct PipelineGlobals<'a> {
  cache: MultiCache<u64, OpBuffer>,
  maxwidth: usize,
  maxheight: usize,
  linear: bool,
  image: &'a RawImage,
}

#[derive(Debug)]
pub struct PipelineOps {
  gofloat: gofloat::OpGoFloat,
  demosaic: demosaic::OpDemosaic,
  level: level::OpLevel,
  tolab: colorspaces::OpToLab,
  basecurve: curves::OpBaseCurve,
  fromlab: colorspaces::OpFromLab,
  gamma: gamma::OpGamma,
  transform: transform::OpTransform,
}

macro_rules! for_vals {
  ([$($val:expr),*] |$x:pat, $i:ident| $body:expr) => {
    let mut pos = 0;
    $({
      let $x = $val;
      pos += 1;
      let $i = pos-1;
      $body
    })*
  }
}

macro_rules! all_ops {
  ($ops:expr, |$x:pat, $i:ident| $body:expr) => {
    for_vals!([
      $ops.gofloat,
      $ops.demosaic,
      $ops.level,
      $ops.tolab,
      $ops.basecurve,
      $ops.fromlab,
      $ops.gamma,
      $ops.transform
    ] |$x, $i| {
      $body
    });
  }
}

#[derive(Debug)]
pub struct Pipeline<'a> {
  globals: PipelineGlobals<'a>,
  ops: PipelineOps,
}

impl<'a> Pipeline<'a> {
  pub fn new(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool) -> Pipeline {
    // Check if the image's orientation results in a rotation that
    // swaps the maximum width with the maximum height
    let (transpose, ..) = img.orientation.to_flips();
    let (maxwidth, maxheight) = if transpose {
      (maxheight, maxwidth)
    } else {
      (maxwidth, maxheight)
    };

    Pipeline {
      globals: PipelineGlobals {
        cache: MultiCache::new(1),
        maxwidth,
        maxheight,
        linear,
        image: img,
      },
      ops: PipelineOps {
        gofloat: gofloat::OpGoFloat::new(img),
        demosaic: demosaic::OpDemosaic::new(img),
        level: level::OpLevel::new(img),
        tolab: colorspaces::OpToLab::new(img),
        basecurve: curves::OpBaseCurve::new(img),
        fromlab: colorspaces::OpFromLab::new(img),
        gamma: gamma::OpGamma::new(img),
        transform: transform::OpTransform::new(img),
      },
    }
  }

  pub fn run(&mut self) -> Arc<OpBuffer> {
    // Generate all the hashes for the operations
    let mut hasher = MetroHash::new();
    let mut ophashes = Vec::new();
    all_ops!(self.ops, |ref op, _i| {
      // Hash the name first as a zero sized struct doesn't actually do any hashing
      op.name().hash(&mut hasher);
      op.hash(&mut hasher);
      ophashes.push(hasher.finish());
    });

    // Do the operations, starting with a dummy buffer id as gofloat doesn't use it
    let mut bufin: u64 = 0;
    all_ops!(self.ops, |ref op, i| {
      let globals = &mut self.globals;
      let hash = ophashes[i];
      do_timing(op.name(), ||op.run(globals, bufin, hash));
      bufin = hash;
    });
    self.globals.cache.get(bufin).unwrap()
  }
}

fn simple_decode_full(img: &RawImage, maxwidth: usize, maxheight: usize, linear: bool) -> OpBuffer {
  let buf = {
    let mut pipeline = Pipeline::new(img, maxwidth, maxheight, linear);
    pipeline.run()
  };

  // Since we've kept the pipeline to ourselves unwraping always works
  Arc::try_unwrap(buf).unwrap()
}

pub fn simple_decode(img: &RawImage, maxwidth: usize, maxheight: usize) -> OpBuffer {
  simple_decode_full(img, maxwidth, maxheight, false)
}

pub fn simple_decode_linear(img: &RawImage, maxwidth: usize, maxheight: usize) -> OpBuffer {
  simple_decode_full(img, maxwidth, maxheight, true)
}
<|endoftext|>