<commit_before>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Debug, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if <Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone, Debug)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}
<commit_msg>docs(node): add docs to lazy fields<commit_after>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Debug, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if <Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone, Debug)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}
<|endoftext|>


<commit_before>mod pic;

use x86;
use drivers;
use vga_buffer;

use kernel::kget;
use schedule::task::TaskContext;

use x86_64::structures::idt::{Idt, ExceptionStackFrame, PageFaultErrorCode};

lazy_static! {
    static ref IDT: Idt = {
        let mut idt = Idt::new();

        // Set all the handlers. Set default handler if a specific is not defined
        // to help debugging
        idt.divide_by_zero.set_handler_fn(except_00);
        idt.page_fault.set_handler_fn(except_14);

        // Interrupts
        idt.interrupts[0].set_handler_fn(irq0_handler); // IRQ 1
        idt.interrupts[1].set_handler_fn(irq1_handler); // IRQ 2

        idt
    };
}

static PIC: pic::Pic = pic::Pic::new();

pub fn init() {
    PIC.init();

    // Enable some pic interrupts
    PIC.clear_mask(0);
    PIC.clear_mask(1);
    // PIC.clear_mask(2);
    // PIC.clear_mask(3);
    // PIC.clear_mask(4);
    // PIC.clear_mask(5);

    IDT.load();

    // Enable interrupts
    unsafe {
        x86::irq::enable();
    }
}

// Some handlers...

// Divide by zero
extern "x86-interrupt" fn except_00(_: &mut ExceptionStackFrame) {
    unsafe {
        vga_buffer::print_error(format_args!("EXCEPTION: Divide By Zero\n"));
    };

    hang!();
}

// Page fault
extern "x86-interrupt" fn except_14(stack_frame: &mut ExceptionStackFrame,
                                    error_code: PageFaultErrorCode) {
    unsafe {
        vga_buffer::print_error(
            format_args!(
                "EXCEPTION: Page Fault accessing {:#x} \nerror code: {:?}\n{:#?}",
                x86::controlregs::cr2(),
                error_code,
                stack_frame.instruction_pointer
            )
        );
    };

    hang!();
}

// IRQ Handlers...

// Handler for IRQ0 - the PIT interrupt
extern "x86-interrupt" fn irq0_handler(_: &mut ExceptionStackFrame) {
    unsafe {
        asm!("push rbp
              push r15
              push r14
              push r13
              push r12
              push r11
              push r10
              push r9
              push r8
              push rsi
              push rdi
              push rdx
              push rcx
              push rbx
              push rax
              mov rdi, rsp

              call $0

              pop rax
              pop rbx
              pop rcx
              pop rdx
              pop rdi
              pop rsi
              pop r8
              pop r9
              pop r10
              pop r11
              pop r12
              pop r13
              pop r14
              pop r15
              pop rbp" :: "s"(irq0_handler_impl as fn(_)) :: "volatile", "intel");
      }
}

fn irq0_handler_impl(context: *mut TaskContext) {
    let context_ref = unsafe { &mut *context };
    let scheduler = unsafe { &mut *kget().scheduler.get() };

    scheduler.tick(context_ref);

    PIC.send_end_of_interrupt(0);
}

// Handler for IRQ1 - the keyboard interrupt
extern "x86-interrupt" fn irq1_handler(_: &mut ExceptionStackFrame) {
    unsafe {
        drivers::KEYBOARD.handle_keypress();
        PIC.send_end_of_interrupt(1);
    }
}
<commit_msg>Added some docs to interrupts module<commit_after>mod pic;

use x86;
use drivers;
use vga_buffer;

use kernel::kget;
use schedule::task::TaskContext;

use x86_64::structures::idt::{Idt, ExceptionStackFrame, PageFaultErrorCode};

lazy_static! {
    static ref IDT: Idt = {
        let mut idt = Idt::new();

        // Set all the handlers. Set default handler if a specific is not defined
        // to help debugging
        idt.divide_by_zero.set_handler_fn(except_00);
        idt.page_fault.set_handler_fn(except_14);

        // Interrupts
        idt.interrupts[0].set_handler_fn(irq0_handler); // IRQ 1
        idt.interrupts[1].set_handler_fn(irq1_handler); // IRQ 2

        idt
    };
}

static PIC: pic::Pic = pic::Pic::new();

/// Initialise kernel interrupt handling
///
/// Initialises the PIC and IDT. Enables CPU interrupts.
pub fn init() {
    PIC.init();

    // Enable some pic interrupts
    PIC.clear_mask(0);
    PIC.clear_mask(1);
    // PIC.clear_mask(2);
    // PIC.clear_mask(3);
    // PIC.clear_mask(4);
    // PIC.clear_mask(5);

    IDT.load();

    // Enable interrupts
    unsafe {
        x86::irq::enable();
    }
}

// Exception Handlers

/// Divide by zero handler
///
/// Prints out details of the exception then sleeps the CPU forever.
extern "x86-interrupt" fn except_00(_: &mut ExceptionStackFrame) {
    unsafe {
        vga_buffer::print_error(format_args!("EXCEPTION: Divide By Zero\n"));
    };

    hang!();
}

/// Page fault handler
///
/// Prints out details of the exception then sleeps the CPU forever.
extern "x86-interrupt" fn except_14(stack_frame: &mut ExceptionStackFrame,
                                    error_code: PageFaultErrorCode) {
    unsafe {
        vga_buffer::print_error(
            format_args!(
                "EXCEPTION: Page Fault accessing {:#x} \nerror code: {:?}\n{:#?}",
                x86::controlregs::cr2(),
                error_code,
                stack_frame.instruction_pointer
            )
        );
    };

    hang!();
}

// IRQ Handlers...

/// Handler for IRQ0 - The PIT interrupt
///
/// Pushes all registers to the stack before calling irq0_handler_impl with the value of the stack
/// pointer passed in rdi (see System V ABI). Finally, restores all registers from the stack.
extern "x86-interrupt" fn irq0_handler(_: &mut ExceptionStackFrame) {
    unsafe {
        asm!("push rbp
              push r15
              push r14
              push r13
              push r12
              push r11
              push r10
              push r9
              push r8
              push rsi
              push rdi
              push rdx
              push rcx
              push rbx
              push rax
              mov rdi, rsp

              call $0

              pop rax
              pop rbx
              pop rcx
              pop rdx
              pop rdi
              pop rsi
              pop r8
              pop r9
              pop r10
              pop r11
              pop r12
              pop r13
              pop r14
              pop r15
              pop rbp" :: "s"(irq0_handler_impl as fn(_)) :: "volatile", "intel");
      }
}

/// Ticks the system scheduler once.
///
/// Calls the system scheduler, passing a reference to the task context. Sets EOI before returning.
fn irq0_handler_impl(context: *mut TaskContext) {
    let context_ref = unsafe { &mut *context };
    let scheduler = unsafe { &mut *kget().scheduler.get() };

    scheduler.tick(context_ref);

    PIC.send_end_of_interrupt(0);
}

/// Handler for IRQ1 - The keyboard interrupt
///
/// Delegates handling to `drivers::KEYBOARD`. Sets EOI before returning.
extern "x86-interrupt" fn irq1_handler(_: &mut ExceptionStackFrame) {
    unsafe {
        drivers::KEYBOARD.handle_keypress();
        PIC.send_end_of_interrupt(1);
    }
}
<|endoftext|>


<commit_before>//! Building blocks for meta rules.

pub use self::lines::Lines;
pub use self::node::Node;
pub use self::number::Number;
pub use self::optional::Optional;
pub use self::repeat::Repeat;
pub use self::rule::Rule;
pub use self::select::Select;
pub use self::separate_by::SeparateBy;
pub use self::sequence::Sequence;
pub use self::text::Text;
pub use self::token::Token;
pub use self::until_any::UntilAny;
pub use self::until_any_or_whitespace::UntilAnyOrWhitespace;
pub use self::whitespace::Whitespace;

use std::rc::Rc;
use range::Range;
use {
    MetaData,
    ParseError,
    Tokenizer,
    TokenizerState,
};

mod lines;
mod node;
mod number;
mod optional;
mod repeat;
mod rule;
mod select;
mod separate_by;
mod sequence;
mod text;
mod token;
mod until_any;
mod until_any_or_whitespace;
mod whitespace;

/// Parses text with rules.
pub fn parse(
    rules: &[(Rc<String>, Rule)],
    text: &str
) -> Result<Vec<(Range, MetaData)>, (Range, ParseError)> {
    let chars: Vec<char> = text.chars().collect();
    let mut tokenizer = Tokenizer::new();
    let s = TokenizerState::new();
    let n = match rules.len() {
        0 => { return Err((Range::empty(0), ParseError::NoRules)); }
        x => x
    };
    let res = rules[n - 1].1.parse(&mut tokenizer, &s, &chars, 0, rules);
    match res {
        Ok((range, s, opt_error)) => {
            // Report error if did not reach the end of text.
            if range.next_offset() < text.len() {
                Err(ret_err(
                    (Range::empty(range.next_offset()),
                        ParseError::ExpectedEnd),
                    opt_error
                ))
            } else {
                tokenizer.tokens.truncate(s.0);
                Ok(tokenizer.tokens)
            }
        }
        Err((err_range, err)) => {
            Err((err_range, err))
        }
    }
}

/// Updates the references such that they point to each other.
pub fn update_refs(rules: &[(Rc<String>, Rule)]) {
    for r in rules {
        r.1.update_refs(rules);
    }
}

/// A parse result succeeds with a new state,
/// plus an optional error to replace other errors if it is deeper.
/// The deepest error is likely the most useful.
pub type ParseResult<S> = Result<(Range, S, Option<(Range, ParseError)>),
    (Range, ParseError)>;

/// Updates the parser state.
/// Used by rules that have multiple sub rules.
#[inline(always)]
fn update<'a>(
    range: Range,
    err: Option<(Range, ParseError)>,
    chars: &mut &'a [char],
    offset: &mut usize,
    opt_error: &mut Option<(Range, ParseError)>
) {
    let next_offset = range.next_offset();
    *chars = &chars[next_offset - *offset..];
    *offset = next_offset;
    err_update(err, opt_error);
}

/// Picks deepest error, overwriting with the newest one if they are
/// equally deep.
#[inline(always)]
fn err_update(
    err: Option<(Range, ParseError)>,
    opt_error: &mut Option<(Range, ParseError)>
) {
    if let &mut Some(ref mut opt_error) = opt_error {
        if let Some(err) = err {
            if opt_error.0.next_offset() <= err.0.next_offset() {
                *opt_error = err;
            }
        }
    } else {
        *opt_error = err;
    };
}

/// This is used to pick the deepest error or two alternatives,
/// one from a rule that fails certainly and another that could be optional.
#[inline(always)]
fn ret_err(a: (Range, ParseError), b: Option<(Range, ParseError)>) ->
    (Range, ParseError) {
    if let Some(b) = b {
        if b.0.next_offset() > a.0.next_offset() {
            b
        } else {
            a
        }
    } else {
        a
    }
}

#[cfg(test)]
mod tests{
    use range::Range;
    use all::*;

    #[test]
    fn no_rules() {
        assert_eq!(parse(&[], ""),
            Err((Range::empty(0), ParseError::NoRules)));
    }
}
<commit_msg>Fixed bug<commit_after>//! Building blocks for meta rules.

pub use self::lines::Lines;
pub use self::node::Node;
pub use self::number::Number;
pub use self::optional::Optional;
pub use self::repeat::Repeat;
pub use self::rule::Rule;
pub use self::select::Select;
pub use self::separate_by::SeparateBy;
pub use self::sequence::Sequence;
pub use self::text::Text;
pub use self::token::Token;
pub use self::until_any::UntilAny;
pub use self::until_any_or_whitespace::UntilAnyOrWhitespace;
pub use self::whitespace::Whitespace;

use std::rc::Rc;
use range::Range;
use {
    MetaData,
    ParseError,
    Tokenizer,
    TokenizerState,
};

mod lines;
mod node;
mod number;
mod optional;
mod repeat;
mod rule;
mod select;
mod separate_by;
mod sequence;
mod text;
mod token;
mod until_any;
mod until_any_or_whitespace;
mod whitespace;

/// Parses text with rules.
pub fn parse(
    rules: &[(Rc<String>, Rule)],
    text: &str
) -> Result<Vec<(Range, MetaData)>, (Range, ParseError)> {
    let chars: Vec<char> = text.chars().collect();
    let mut tokenizer = Tokenizer::new();
    let s = TokenizerState::new();
    let n = match rules.len() {
        0 => { return Err((Range::empty(0), ParseError::NoRules)); }
        x => x
    };
    let res = rules[n - 1].1.parse(&mut tokenizer, &s, &chars, 0, rules);
    match res {
        Ok((range, s, opt_error)) => {
            // Report error if did not reach the end of text.
            if range.next_offset() < text.chars().count() {
                Err(ret_err(
                    (Range::empty(range.next_offset()),
                        ParseError::ExpectedEnd),
                    opt_error
                ))
            } else {
                tokenizer.tokens.truncate(s.0);
                Ok(tokenizer.tokens)
            }
        }
        Err((err_range, err)) => {
            Err((err_range, err))
        }
    }
}

/// Updates the references such that they point to each other.
pub fn update_refs(rules: &[(Rc<String>, Rule)]) {
    for r in rules {
        r.1.update_refs(rules);
    }
}

/// A parse result succeeds with a new state,
/// plus an optional error to replace other errors if it is deeper.
/// The deepest error is likely the most useful.
pub type ParseResult<S> = Result<(Range, S, Option<(Range, ParseError)>),
    (Range, ParseError)>;

/// Updates the parser state.
/// Used by rules that have multiple sub rules.
#[inline(always)]
fn update<'a>(
    range: Range,
    err: Option<(Range, ParseError)>,
    chars: &mut &'a [char],
    offset: &mut usize,
    opt_error: &mut Option<(Range, ParseError)>
) {
    let next_offset = range.next_offset();
    *chars = &chars[next_offset - *offset..];
    *offset = next_offset;
    err_update(err, opt_error);
}

/// Picks deepest error, overwriting with the newest one if they are
/// equally deep.
#[inline(always)]
fn err_update(
    err: Option<(Range, ParseError)>,
    opt_error: &mut Option<(Range, ParseError)>
) {
    if let &mut Some(ref mut opt_error) = opt_error {
        if let Some(err) = err {
            if opt_error.0.next_offset() <= err.0.next_offset() {
                *opt_error = err;
            }
        }
    } else {
        *opt_error = err;
    };
}

/// This is used to pick the deepest error or two alternatives,
/// one from a rule that fails certainly and another that could be optional.
#[inline(always)]
fn ret_err(a: (Range, ParseError), b: Option<(Range, ParseError)>) ->
    (Range, ParseError) {
    if let Some(b) = b {
        if b.0.next_offset() > a.0.next_offset() {
            b
        } else {
            a
        }
    } else {
        a
    }
}

#[cfg(test)]
mod tests{
    use range::Range;
    use all::*;

    #[test]
    fn no_rules() {
        assert_eq!(parse(&[], ""),
            Err((Range::empty(0), ParseError::NoRules)));
    }
}
<|endoftext|>


<commit_before>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

use std::collections::HashMap;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Block {
  /// Marks whether the current metadata block is the last.
  pub is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  pub length: u32,
  /// Block data containing on of the eight different types of metadata.
  pub data: BlockData,
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  pub vendor_string: String,
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  pub media_catalog_number: String,
  pub lead_in: u64,
  pub is_cd: bool,
  pub tracks: Vec<CueSheetTrack>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  pub offset: u64,
  pub number: u8,
  pub isrc: String,
  pub is_audio: bool,
  pub is_pre_emphasis: bool,
  pub indices: Vec<CueSheetTrackIndex>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  pub offset: u64,
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  pub picture_type: PictureType,
  pub mime_type: String,
  pub description: String,
  pub width: u32,
  pub height: u32,
  pub depth: u32,
  pub colors: u32,
  pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  Other,
  FileIconStandard,
  FileIcon,
  FrontCover,
  BackCover,
  LeafletPage,
  Media,
  LeadArtist,
  Artist,
  Conductor,
  Band,
  Composer,
  Lyricist,
  RecordingLocation,
  DuringRecording,
  DuringPerformace,
  VideoScreenCapture,
  Fish,
  Illustration,
  BandLogo,
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<commit_msg>Add documentation for the `VorbisComment` struct<commit_after>use nom::{IResult, Consumer, ConsumerState};
use metadata::parser::{header, block_data};

use std::collections::HashMap;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Block {
  /// Marks whether the current metadata block is the last.
  pub is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  pub length: u32,
  /// Block data containing on of the eight different types of metadata.
  pub data: BlockData,
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum BlockData {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream
#[derive(Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  pub media_catalog_number: String,
  pub lead_in: u64,
  pub is_cd: bool,
  pub tracks: Vec<CueSheetTrack>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  pub offset: u64,
  pub number: u8,
  pub isrc: String,
  pub is_audio: bool,
  pub is_pre_emphasis: bool,
  pub indices: Vec<CueSheetTrackIndex>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  pub offset: u64,
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  pub picture_type: PictureType,
  pub mime_type: String,
  pub description: String,
  pub width: u32,
  pub height: u32,
  pub depth: u32,
  pub colors: u32,
  pub data: Vec<u8>,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  Other,
  FileIconStandard,
  FileIcon,
  FrontCover,
  BackCover,
  LeafletPage,
  Media,
  LeadArtist,
  Artist,
  Conductor,
  Band,
  Composer,
  Lyricist,
  RecordingLocation,
  DuringRecording,
  DuringPerformace,
  VideoScreenCapture,
  Fish,
  Illustration,
  BandLogo,
  PublisherLogo,
}

enum ParserState {
  FLAC,
  Header,
  MetaData,
}

pub struct MetaDataConsumer {
  state: ParserState,
  is_last: bool,
  block_type: u8,
  length: u32,
  pub data: Vec<Block>
}

impl MetaDataConsumer {
  pub fn new() -> MetaDataConsumer {
    MetaDataConsumer {
      state: ParserState::FLAC,
      is_last: false,
      block_type: 127,
      length: 0,
      data: Vec::new(),
    }
  }
}

impl Consumer for MetaDataConsumer {
  fn consume(&mut self, input: &[u8]) -> ConsumerState {
    match self.state {
      ParserState::FLAC     => {
        match tag!(input, "fLaC") {
          IResult::Done(_, _) => {
            self.state = ParserState::Header;
            ConsumerState::Await(4, 4)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      }
      ParserState::Header   => {
        match header(input) {
          IResult::Done(_, data) => {
            let (is_last, block_type, length) = data;

            self.state      = ParserState::MetaData;
            self.is_last    = is_last;
            self.block_type = block_type;
            self.length     = length;

            ConsumerState::Await(4, length as usize)
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, 4),
        }
      },
      ParserState::MetaData => {
        let length = self.length as usize;

        match block_data(input, self.block_type, self.length) {
          IResult::Done(_, data) => {
            self.data.push(Block {
              is_last: self.is_last,
              length: self.length,
              data: data,
            });

            if self.is_last {
              ConsumerState::ConsumerDone
            } else {
              self.state = ParserState::Header;

              ConsumerState::Await(length, 4)
            }
          }
          IResult::Error(_)      => ConsumerState::ConsumerError(0),
          IResult::Incomplete(_) => ConsumerState::Await(0, length),
        }
      }
    }
  }

  fn failed(&mut self, error_code: u32) {
    println!("Failed with error code: {}", error_code);
  }

  fn end(&mut self) {}
}
<|endoftext|>


<commit_before>use crate::net::{TcpStream, TcpListener};
use crate::sys;

use std::io;
use std::mem;
use std::net::SocketAddr;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};

/// A non-blocking TCP socket used to configure a stream or listener.
///
/// The `TcpSocket` type wraps the operating-system's socket handle. This type
/// is used to configure the socket before establishing a connection or start
/// listening for inbound connections.
///
/// The socket will be closed when the value is dropped.
#[derive(Debug)]
pub struct TcpSocket {
    sys: sys::tcp::TcpSocket,
}

impl TcpSocket {
    /// Create a new IPv4 TCP socket.
    ///
    /// This calls `socket(2)`.
    pub fn new_v4() -> io::Result<TcpSocket> {
        sys::tcp::new_v4_socket().map(|sys| TcpSocket {
            sys
        })
    }

    /// Create a new IPv6 TCP socket.
    ///
    /// This calls `socket(2)`.
    pub fn new_v6() -> io::Result<TcpSocket> {
        sys::tcp::new_v6_socket().map(|sys| TcpSocket {
            sys
        })
    }

    pub(crate) fn new_for_addr(addr: SocketAddr) -> io::Result<TcpSocket> {
        if addr.is_ipv4() {
            TcpSocket::new_v4()
        } else {
            TcpSocket::new_v6()
        }
    }

    /// Bind `addr` to the TCP socket.
    pub fn bind(&self, addr: SocketAddr) -> io::Result<()> {
        sys::tcp::bind(self.sys, addr)
    }

    /// Connect the socket to `addr`.
    ///
    /// This consumes the socket and performs the connect operation. Once the
    /// connection completes, the socket is now a non-blocking `TcpStream` and
    /// can be used as such.
    pub fn connect(self, addr: SocketAddr) -> io::Result<TcpStream> {
        let stream = sys::tcp::connect(self.sys, addr)?;

        // Don't close the socket
        mem::forget(self);
        Ok(TcpStream::from_std(stream))
    }

    /// Listen for inbound connections, converting the socket to a
    /// `TcpListener`.
    pub fn listen(self, backlog: u32) -> io::Result<TcpListener> {
        let listener = sys::tcp::listen(self.sys, backlog)?;

        // Don't close the socket
        mem::forget(self);
        Ok(TcpListener::from_std(listener))
    }

    /// Sets the value of `SO_REUSEADDR` on this socket.
    pub fn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> {
        sys::tcp::set_reuseaddr(self.sys, reuseaddr)
    }
}

impl Drop for TcpSocket {
    fn drop(&mut self) {
        sys::tcp::close(self.sys);
    }
}

#[cfg(unix)]
impl AsRawFd for TcpSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.sys
    }
}

#[cfg(unix)]
impl FromRawFd for TcpSocket {
    /// Converts a `RawFd` to a `TcpStream`.
    ///
    /// # Notes
    ///
    /// The caller is responsible for ensuring that the socket is in
    /// non-blocking mode.
    unsafe fn from_raw_fd(fd: RawFd) -> TcpSocket {
        TcpSocket { sys: fd }
    }
}<commit_msg>Add windows RawSocket conversions for TcpSocket (#1359)<commit_after>use crate::net::{TcpStream, TcpListener};
use crate::sys;

use std::io;
use std::mem;
use std::net::SocketAddr;
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, RawFd, FromRawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};

/// A non-blocking TCP socket used to configure a stream or listener.
///
/// The `TcpSocket` type wraps the operating-system's socket handle. This type
/// is used to configure the socket before establishing a connection or start
/// listening for inbound connections.
///
/// The socket will be closed when the value is dropped.
#[derive(Debug)]
pub struct TcpSocket {
    sys: sys::tcp::TcpSocket,
}

impl TcpSocket {
    /// Create a new IPv4 TCP socket.
    ///
    /// This calls `socket(2)`.
    pub fn new_v4() -> io::Result<TcpSocket> {
        sys::tcp::new_v4_socket().map(|sys| TcpSocket {
            sys
        })
    }

    /// Create a new IPv6 TCP socket.
    ///
    /// This calls `socket(2)`.
    pub fn new_v6() -> io::Result<TcpSocket> {
        sys::tcp::new_v6_socket().map(|sys| TcpSocket {
            sys
        })
    }

    pub(crate) fn new_for_addr(addr: SocketAddr) -> io::Result<TcpSocket> {
        if addr.is_ipv4() {
            TcpSocket::new_v4()
        } else {
            TcpSocket::new_v6()
        }
    }

    /// Bind `addr` to the TCP socket.
    pub fn bind(&self, addr: SocketAddr) -> io::Result<()> {
        sys::tcp::bind(self.sys, addr)
    }

    /// Connect the socket to `addr`.
    ///
    /// This consumes the socket and performs the connect operation. Once the
    /// connection completes, the socket is now a non-blocking `TcpStream` and
    /// can be used as such.
    pub fn connect(self, addr: SocketAddr) -> io::Result<TcpStream> {
        let stream = sys::tcp::connect(self.sys, addr)?;

        // Don't close the socket
        mem::forget(self);
        Ok(TcpStream::from_std(stream))
    }

    /// Listen for inbound connections, converting the socket to a
    /// `TcpListener`.
    pub fn listen(self, backlog: u32) -> io::Result<TcpListener> {
        let listener = sys::tcp::listen(self.sys, backlog)?;

        // Don't close the socket
        mem::forget(self);
        Ok(TcpListener::from_std(listener))
    }

    /// Sets the value of `SO_REUSEADDR` on this socket.
    pub fn set_reuseaddr(&self, reuseaddr: bool) -> io::Result<()> {
        sys::tcp::set_reuseaddr(self.sys, reuseaddr)
    }
}

impl Drop for TcpSocket {
    fn drop(&mut self) {
        sys::tcp::close(self.sys);
    }
}

#[cfg(unix)]
impl AsRawFd for TcpSocket {
    fn as_raw_fd(&self) -> RawFd {
        self.sys
    }
}

#[cfg(unix)]
impl FromRawFd for TcpSocket {
    /// Converts a `RawFd` to a `TcpSocket`.
    ///
    /// # Notes
    ///
    /// The caller is responsible for ensuring that the socket is in
    /// non-blocking mode.
    unsafe fn from_raw_fd(fd: RawFd) -> TcpSocket {
        TcpSocket { sys: fd }
    }
}

#[cfg(windows)]
impl IntoRawSocket for TcpSocket {
    fn into_raw_socket(self) -> RawSocket {
        // The winapi crate defines `SOCKET` as `usize`. The Rust std
        // conditionally defines `RawSocket` as a fixed size unsigned integer
        // matching the pointer width. These end up being the same type but we
        // must cast between them.
        let ret = self.sys as RawSocket;

        // Avoid closing the socket
        mem::forget(self);

        ret
    }
}

#[cfg(windows)]
impl AsRawSocket for TcpSocket {
    fn as_raw_socket(&self) -> RawSocket {
        self.sys as RawSocket
    }
}

#[cfg(windows)]
impl FromRawSocket for TcpSocket {
    /// Converts a `RawSocket` to a `TcpSocket`.
    ///
    /// # Notes
    ///
    /// The caller is responsible for ensuring that the socket is in
    /// non-blocking mode.
    unsafe fn from_raw_socket(socket: RawSocket) -> TcpSocket {
        TcpSocket { sys: socket as sys::tcp::TcpSocket }
    }
}
<|endoftext|>


<commit_before>#[cfg(windows)]
extern crate winapi;

extern crate libloading;
use libloading::{Library, Symbol};

const TARGET_DIR: Option<&'static str> = option_env!("CARGO_TARGET_DIR");
const TARGET_TMPDIR: Option<&'static str> = option_env!("CARGO_TARGET_TMPDIR");

fn lib_path() -> &'static str {
    format!(
        "{}/libtest_helpers.module",
        TARGET_TMPDIR.unwrap_or(TARGET_DIR.unwrap_or("target"))
    )
}

fn make_helpers() {
    static ONCE: ::std::sync::Once = ::std::sync::Once::new();
    ONCE.call_once(|| {
        let rustc = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
        let mut cmd = ::std::process::Command::new(rustc);
        cmd.arg("src/test_helpers.rs").arg("-o").arg(lib_path());
        if let Some(target) = std::env::var_os("TARGET") {
            cmd.arg("--target").arg(target);
        } else {
            eprintln!("WARNING: $TARGET NOT SPECIFIED! BUILDING HELPER MODULE FOR NATIVE TARGET.");
        }
        assert!(cmd
            .status()
            .expect("could not compile the test helpers!")
            .success());
    });
}

#[test]
fn test_id_u32() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let f: Symbol<unsafe extern "C" fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap();
        assert_eq!(42, f(42));
    }
}

#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
struct S {
    a: u64,
    b: u32,
    c: u16,
    d: u8,
}

#[test]
fn test_id_struct() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
        assert_eq!(
            S {
                a: 1,
                b: 2,
                c: 3,
                d: 4
            },
            f(S {
                a: 1,
                b: 2,
                c: 3,
                d: 4
            })
        );
    }
}

#[test]
fn test_0_no_0() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
        let f2: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
        assert_eq!(*f, *f2);
    }
}

#[test]
fn wrong_name_fails() {
    unsafe {
        Library::new("target/this_location_is_definitely_non existent:^~")
            .err()
            .unwrap();
    }
}

#[test]
fn missing_symbol_fails() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap();
        lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap();
    }
}

#[test]
fn interior_null_fails() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
        lib.get::<*mut ()>(b"test\0_does_not_exist\0")
            .err()
            .unwrap();
    }
}

#[test]
fn test_incompatible_type() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        assert!(match lib.get::<()>(b"test_identity_u32\0") {
            Err(libloading::Error::IncompatibleSize) => true,
            _ => false,
        })
    }
}

#[test]
fn test_incompatible_type_named_fn() {
    make_helpers();
    unsafe fn get<'a, T>(l: &'a Library, _: T) -> Result<Symbol<'a, T>, libloading::Error> {
        l.get::<T>(b"test_identity_u32\0")
    }
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        assert!(match get(&lib, test_incompatible_type_named_fn) {
            Err(libloading::Error::IncompatibleSize) => true,
            _ => false,
        })
    }
}

#[test]
fn test_static_u32() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
        **var = 42;
        let help: Symbol<unsafe extern "C" fn() -> u32> =
            lib.get(b"test_get_static_u32\0").unwrap();
        assert_eq!(42, help());
    }
}

#[test]
fn test_static_ptr() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
        **var = *var as *mut _;
        let works: Symbol<unsafe extern "C" fn() -> bool> =
            lib.get(b"test_check_static_ptr\0").unwrap();
        assert!(works());
    }
}

#[test]
// Something about i686-pc-windows-gnu, makes dll initialisation code call abort when it is loaded
// and unloaded many times. So far it seems like an issue with mingw, not libloading, so ignoring
// the target. Especially since it is very unlikely to be fixed given the state of support its
// support.
#[cfg(not(all(target_arch = "x86", target_os = "windows", target_env = "gnu")))]
fn manual_close_many_times() {
    make_helpers();
    let join_handles: Vec<_> = (0..16)
        .map(|_| {
            std::thread::spawn(|| unsafe {
                for _ in 0..10000 {
                    let lib = Library::new(lib_path()).expect("open library");
                    let _: Symbol<unsafe extern "C" fn(u32) -> u32> =
                        lib.get(b"test_identity_u32").expect("get fn");
                    lib.close().expect("close is successful");
                }
            })
        })
        .collect();
    for handle in join_handles {
        handle.join().expect("thread should succeed");
    }
}

#[cfg(unix)]
#[test]
fn library_this_get() {
    use libloading::os::unix::Library;
    make_helpers();
    // SAFE: functions are never called
    unsafe {
        let _lib = Library::new(lib_path()).unwrap();
        let this = Library::this();
        // Library we loaded in `_lib` (should be RTLD_LOCAL).
        assert!(this
            .get::<unsafe extern "C" fn()>(b"test_identity_u32")
            .is_err());
        // Something obscure from libc...
        assert!(this.get::<unsafe extern "C" fn()>(b"freopen").is_ok());
    }
}

#[cfg(windows)]
#[test]
fn library_this() {
    use libloading::os::windows::Library;
    make_helpers();
    unsafe {
        // SAFE: well-known library without initialisers is loaded.
        let _lib = Library::new(lib_path()).unwrap();
        let this = Library::this().expect("this library");
        // SAFE: functions are never called.
        // Library we loaded in `_lib`.
        assert!(this
            .get::<unsafe extern "C" fn()>(b"test_identity_u32")
            .is_err());
        // Something "obscure" from kernel32...
        assert!(this.get::<unsafe extern "C" fn()>(b"GetLastError").is_err());
    }
}

#[cfg(windows)]
#[test]
fn works_getlasterror() {
    use libloading::os::windows::{Library, Symbol};
    use winapi::shared::minwindef::DWORD;
    use winapi::um::errhandlingapi;

    unsafe {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError").unwrap();
        errhandlingapi::SetLastError(42);
        assert_eq!(errhandlingapi::GetLastError(), gle())
    }
}

#[cfg(windows)]
#[test]
fn works_getlasterror0() {
    use libloading::os::windows::{Library, Symbol};
    use winapi::shared::minwindef::DWORD;
    use winapi::um::errhandlingapi;

    unsafe {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError\0").unwrap();
        errhandlingapi::SetLastError(42);
        assert_eq!(errhandlingapi::GetLastError(), gle())
    }
}

#[cfg(windows)]
#[test]
fn library_open_already_loaded() {
    use libloading::os::windows::Library;

    // Present on Windows systems and NOT used by any other tests to prevent races.
    const LIBPATH: &str = "Msftedit.dll";

    // Not loaded yet.
    assert!(match Library::open_already_loaded(LIBPATH) {
        Err(libloading::Error::GetModuleHandleExW { .. }) => true,
        _ => false,
    });

    unsafe {
        let _lib = Library::new(LIBPATH).unwrap();
        // Loaded now.
        assert!(Library::open_already_loaded(LIBPATH).is_ok());
    }
}
<commit_msg>Construct a PathBuf<commit_after>#[cfg(windows)]
extern crate winapi;

extern crate libloading;
use libloading::{Library, Symbol};

const TARGET_DIR: Option<&'static str> = option_env!("CARGO_TARGET_DIR");
const TARGET_TMPDIR: Option<&'static str> = option_env!("CARGO_TARGET_TMPDIR");

fn lib_path() -> std::path::PathBuf {
    [
        TARGET_TMPDIR.unwrap_or(TARGET_DIR.unwrap_or("target")),
        "libtest_helpers.module",
    ]
    .iter()
    .collect()
}

fn make_helpers() {
    static ONCE: ::std::sync::Once = ::std::sync::Once::new();
    ONCE.call_once(|| {
        let rustc = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
        let mut cmd = ::std::process::Command::new(rustc);
        cmd.arg("src/test_helpers.rs").arg("-o").arg(lib_path());
        if let Some(target) = std::env::var_os("TARGET") {
            cmd.arg("--target").arg(target);
        } else {
            eprintln!("WARNING: $TARGET NOT SPECIFIED! BUILDING HELPER MODULE FOR NATIVE TARGET.");
        }
        assert!(cmd
            .status()
            .expect("could not compile the test helpers!")
            .success());
    });
}

#[test]
fn test_id_u32() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let f: Symbol<unsafe extern "C" fn(u32) -> u32> = lib.get(b"test_identity_u32\0").unwrap();
        assert_eq!(42, f(42));
    }
}

#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
struct S {
    a: u64,
    b: u32,
    c: u16,
    d: u8,
}

#[test]
fn test_id_struct() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
        assert_eq!(
            S {
                a: 1,
                b: 2,
                c: 3,
                d: 4
            },
            f(S {
                a: 1,
                b: 2,
                c: 3,
                d: 4
            })
        );
    }
}

#[test]
fn test_0_no_0() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let f: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct\0").unwrap();
        let f2: Symbol<unsafe extern "C" fn(S) -> S> = lib.get(b"test_identity_struct").unwrap();
        assert_eq!(*f, *f2);
    }
}

#[test]
fn wrong_name_fails() {
    unsafe {
        Library::new("target/this_location_is_definitely_non existent:^~")
            .err()
            .unwrap();
    }
}

#[test]
fn missing_symbol_fails() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        lib.get::<*mut ()>(b"test_does_not_exist").err().unwrap();
        lib.get::<*mut ()>(b"test_does_not_exist\0").err().unwrap();
    }
}

#[test]
fn interior_null_fails() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        lib.get::<*mut ()>(b"test_does\0_not_exist").err().unwrap();
        lib.get::<*mut ()>(b"test\0_does_not_exist\0")
            .err()
            .unwrap();
    }
}

#[test]
fn test_incompatible_type() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        assert!(match lib.get::<()>(b"test_identity_u32\0") {
            Err(libloading::Error::IncompatibleSize) => true,
            _ => false,
        })
    }
}

#[test]
fn test_incompatible_type_named_fn() {
    make_helpers();
    unsafe fn get<'a, T>(l: &'a Library, _: T) -> Result<Symbol<'a, T>, libloading::Error> {
        l.get::<T>(b"test_identity_u32\0")
    }
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        assert!(match get(&lib, test_incompatible_type_named_fn) {
            Err(libloading::Error::IncompatibleSize) => true,
            _ => false,
        })
    }
}

#[test]
fn test_static_u32() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let var: Symbol<*mut u32> = lib.get(b"TEST_STATIC_U32\0").unwrap();
        **var = 42;
        let help: Symbol<unsafe extern "C" fn() -> u32> =
            lib.get(b"test_get_static_u32\0").unwrap();
        assert_eq!(42, help());
    }
}

#[test]
fn test_static_ptr() {
    make_helpers();
    unsafe {
        let lib = Library::new(lib_path()).unwrap();
        let var: Symbol<*mut *mut ()> = lib.get(b"TEST_STATIC_PTR\0").unwrap();
        **var = *var as *mut _;
        let works: Symbol<unsafe extern "C" fn() -> bool> =
            lib.get(b"test_check_static_ptr\0").unwrap();
        assert!(works());
    }
}

#[test]
// Something about i686-pc-windows-gnu, makes dll initialisation code call abort when it is loaded
// and unloaded many times. So far it seems like an issue with mingw, not libloading, so ignoring
// the target. Especially since it is very unlikely to be fixed given the state of support its
// support.
#[cfg(not(all(target_arch = "x86", target_os = "windows", target_env = "gnu")))]
fn manual_close_many_times() {
    make_helpers();
    let join_handles: Vec<_> = (0..16)
        .map(|_| {
            std::thread::spawn(|| unsafe {
                for _ in 0..10000 {
                    let lib = Library::new(lib_path()).expect("open library");
                    let _: Symbol<unsafe extern "C" fn(u32) -> u32> =
                        lib.get(b"test_identity_u32").expect("get fn");
                    lib.close().expect("close is successful");
                }
            })
        })
        .collect();
    for handle in join_handles {
        handle.join().expect("thread should succeed");
    }
}

#[cfg(unix)]
#[test]
fn library_this_get() {
    use libloading::os::unix::Library;
    make_helpers();
    // SAFE: functions are never called
    unsafe {
        let _lib = Library::new(lib_path()).unwrap();
        let this = Library::this();
        // Library we loaded in `_lib` (should be RTLD_LOCAL).
        assert!(this
            .get::<unsafe extern "C" fn()>(b"test_identity_u32")
            .is_err());
        // Something obscure from libc...
        assert!(this.get::<unsafe extern "C" fn()>(b"freopen").is_ok());
    }
}

#[cfg(windows)]
#[test]
fn library_this() {
    use libloading::os::windows::Library;
    make_helpers();
    unsafe {
        // SAFE: well-known library without initialisers is loaded.
        let _lib = Library::new(lib_path()).unwrap();
        let this = Library::this().expect("this library");
        // SAFE: functions are never called.
        // Library we loaded in `_lib`.
        assert!(this
            .get::<unsafe extern "C" fn()>(b"test_identity_u32")
            .is_err());
        // Something "obscure" from kernel32...
        assert!(this.get::<unsafe extern "C" fn()>(b"GetLastError").is_err());
    }
}

#[cfg(windows)]
#[test]
fn works_getlasterror() {
    use libloading::os::windows::{Library, Symbol};
    use winapi::shared::minwindef::DWORD;
    use winapi::um::errhandlingapi;

    unsafe {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError").unwrap();
        errhandlingapi::SetLastError(42);
        assert_eq!(errhandlingapi::GetLastError(), gle())
    }
}

#[cfg(windows)]
#[test]
fn works_getlasterror0() {
    use libloading::os::windows::{Library, Symbol};
    use winapi::shared::minwindef::DWORD;
    use winapi::um::errhandlingapi;

    unsafe {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = lib.get(b"GetLastError\0").unwrap();
        errhandlingapi::SetLastError(42);
        assert_eq!(errhandlingapi::GetLastError(), gle())
    }
}

#[cfg(windows)]
#[test]
fn library_open_already_loaded() {
    use libloading::os::windows::Library;

    // Present on Windows systems and NOT used by any other tests to prevent races.
    const LIBPATH: &str = "Msftedit.dll";

    // Not loaded yet.
    assert!(match Library::open_already_loaded(LIBPATH) {
        Err(libloading::Error::GetModuleHandleExW { .. }) => true,
        _ => false,
    });

    unsafe {
        let _lib = Library::new(LIBPATH).unwrap();
        // Loaded now.
        assert!(Library::open_already_loaded(LIBPATH).is_ok());
    }
}
<|endoftext|>


<commit_before>use super::{Hashes, Index, Mapper, Record, Records, Result, TransactionRecord};
use mysql;
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockWriteGuard};

pub struct TransactionMapper {
  counter: Mutex<u64>,
  records: RwLock<Records<TransactionRecord>>,
  hashes: RwLock<Hashes>,
  indices: [RwLock<Records<Index>>; 2],
}

type FetchManyResult = Result<
  Vec<(u64, String, Arc<Mutex<TransactionRecord>>)>,
>;

impl Mapper for TransactionMapper {
  type Record = TransactionRecord;

  fn new(conn: &mut mysql::Conn, retry_interval: u64) -> Result<Self> {
    let counter = Self::init_counter(
      conn,
      retry_interval,
      r"SELECT id_tx FROM tx ORDER BY id_tx DESC LIMIT 1",
    )?;
    let records = RwLock::new(BTreeMap::new());
    let hashes = RwLock::new(HashMap::new());
    let indices = [RwLock::new(BTreeMap::new()), RwLock::new(BTreeMap::new())];
    Ok(Self {
      counter,
      records,
      hashes,
      indices,
    })
  }

  fn counter(&self) -> &Mutex<u64> {
    &self.counter
  }

  fn records(&self) -> &RwLock<Records<TransactionRecord>> {
    &self.records
  }

  fn hashes(&self) -> &RwLock<Hashes> {
    &self.hashes
  }

  fn indices(&self) -> &[RwLock<Records<Index>>] {
    &self.indices
  }

  fn fill_indices(
    indices: &mut [RwLockWriteGuard<Records<Index>>],
    record: &TransactionRecord,
  ) {
    let inner = if record.is_persisted() {
      None
    } else {
      Some(Vec::new())
    };
    indices[0].insert(record.id(), Arc::new(Mutex::new(inner.clone())));
    indices[1].insert(record.id(), Arc::new(Mutex::new(inner)));
    if let Some(id_trunk) = record.id_trunk() {
      if let Some(index) = indices[0].get(&id_trunk) {
        debug!("Mutex check at line {}", line!());
        let mut index = index.lock().unwrap();
        debug!("Mutex check at line {}", line!());
        record.fill_index(&mut index);
      }
    }
    if let Some(id_branch) = record.id_branch() {
      if let Some(index) = indices[1].get(&id_branch) {
        debug!("Mutex check at line {}", line!());
        let mut index = index.lock().unwrap();
        debug!("Mutex check at line {}", line!());
        record.fill_index(&mut index);
      }
    }
  }
}

impl TransactionMapper {
  pub fn fetch_many(
    &self,
    conn: &mut mysql::Conn,
    mut input: Vec<&str>,
  ) -> FetchManyResult {
    input.dedup();
    let cached = {
      debug!("Mutex check at line {}", line!());
      let records = self.records.read().unwrap();
      debug!("Mutex check at line {}", line!());
      let hashes = self.hashes.read().unwrap();
      debug!("Mutex check at line {}", line!());
      input
        .iter()
        .filter_map(|&hash| {
          hashes
            .get(hash)
            .and_then(|&id| records.get(&id).map(|x| (hash, (id, x.clone()))))
        })
        .collect::<HashMap<_, _>>()
    };
    let missing = input
      .iter()
      .filter(|&hash| !cached.contains_key(hash))
      .cloned()
      .collect::<Vec<_>>();
    let found = TransactionRecord::find_by_hashes(conn, missing)?;
    debug!("Mutex check at line {}", line!());
    let mut records = self.records.write().unwrap();
    debug!("Mutex check at line {}", line!());
    let mut hashes = self.hashes.write().unwrap();
    debug!("Mutex check at line {}", line!());
    let mut indices = self.lock_indices();
    debug!("Mutex check at line {}", line!());
    let mut output = input
      .into_iter()
      .map(|hash| {
        cached
          .get(hash)
          .map(|&(id_tx, ref record)| {
            (id_tx, hash.to_owned(), record.clone())
          })
          .unwrap_or_else(|| {
            hashes
              .get(hash)
              .and_then(|&id_tx| {
                records
                  .get(&id_tx)
                  .map(|record| (id_tx, hash.to_owned(), record.clone()))
              })
              .unwrap_or_else(|| {
                let record = found
                  .iter()
                  .find(|record| record.hash() == hash)
                  .cloned()
                  .unwrap_or_else(|| {
                    TransactionRecord::placeholder(
                      hash.to_owned(),
                      self.next_id(),
                    )
                  });
                let id_tx = record.id();
                hashes.insert(hash.to_owned(), id_tx);
                Self::fill_indices(&mut indices, &record);
                let wrapper = Arc::new(Mutex::new(record));
                records.insert(id_tx, wrapper.clone());
                (id_tx, hash.to_owned(), wrapper)
              })
          })
      })
      .collect::<Vec<_>>();
    output.sort_unstable_by_key(|&(id_tx, _, _)| id_tx);
    Ok(output)
  }

  pub fn trunk_index(&self, id: u64) -> Option<Arc<Mutex<Index>>> {
    debug!("Mutex check at line {}", line!());
    let trunks = self.indices[0].read().unwrap();
    debug!("Mutex check at line {}", line!());
    trunks.get(&id).cloned()
  }

  pub fn branch_index(&self, id: u64) -> Option<Arc<Mutex<Index>>> {
    debug!("Mutex check at line {}", line!());
    let branches = self.indices[1].read().unwrap();
    debug!("Mutex check at line {}", line!());
    branches.get(&id).cloned()
  }

  pub fn fetch_trunk<'a>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
  ) -> Result<MutexGuard<'a, Index>> {
    self.fetch_index(conn, id, index, TransactionRecord::find_trunk)
  }

  pub fn fetch_branch<'a>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
  ) -> Result<MutexGuard<'a, Index>> {
    self.fetch_index(conn, id, index, TransactionRecord::find_branch)
  }

  pub fn fetch_bundle<'a>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
  ) -> Result<MutexGuard<'a, Index>> {
    self.fetch_index(conn, id, index, TransactionRecord::find_bundle)
  }

  fn fetch_index<'a, F>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
    f: F,
  ) -> Result<MutexGuard<'a, Index>>
  where
    F: FnOnce(&mut mysql::Conn, u64)
      -> Result<Vec<TransactionRecord>>,
  {
    {
      debug!("Mutex check at line {}", line!());
      let guard = index.lock().unwrap();
      debug!("Mutex check at line {}", line!());
      if guard.is_some() {
        return Ok(guard);
      }
    }
    f(conn, id).map(|found| {
      debug!("Mutex check at line {}", line!());
      let mut records = self.records.write().unwrap();
      debug!("Mutex check at line {}", line!());
      let mut hashes = self.hashes.write().unwrap();
      debug!("Mutex check at line {}", line!());
      let mut index = index.lock().unwrap();
      debug!("Mutex check at line {}", line!());
      match *index {
        Some(_) => index,
        None => {
          let mut ids = found
            .into_iter()
            .map(|record| {
              let id_tx = record.id();
              records.entry(id_tx).or_insert_with(|| {
                hashes.insert(record.hash().to_owned(), id_tx);
                Arc::new(Mutex::new(record))
              });
              id_tx
            })
            .collect::<Vec<_>>();
          ids.sort_unstable();
          ids.dedup();
          *index = Some(ids);
          index
        }
      }
    })
  }
}
<commit_msg>Index loading fix<commit_after>use super::{Hashes, Index, Mapper, Record, Records, Result, TransactionRecord};
use mysql;
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockWriteGuard};

pub struct TransactionMapper {
  counter: Mutex<u64>,
  records: RwLock<Records<TransactionRecord>>,
  hashes: RwLock<Hashes>,
  indices: [RwLock<Records<Index>>; 2],
}

type FetchManyResult = Result<
  Vec<(u64, String, Arc<Mutex<TransactionRecord>>)>,
>;

impl Mapper for TransactionMapper {
  type Record = TransactionRecord;

  fn new(conn: &mut mysql::Conn, retry_interval: u64) -> Result<Self> {
    let counter = Self::init_counter(
      conn,
      retry_interval,
      r"SELECT id_tx FROM tx ORDER BY id_tx DESC LIMIT 1",
    )?;
    let records = RwLock::new(BTreeMap::new());
    let hashes = RwLock::new(HashMap::new());
    let indices = [RwLock::new(BTreeMap::new()), RwLock::new(BTreeMap::new())];
    Ok(Self {
      counter,
      records,
      hashes,
      indices,
    })
  }

  fn counter(&self) -> &Mutex<u64> {
    &self.counter
  }

  fn records(&self) -> &RwLock<Records<TransactionRecord>> {
    &self.records
  }

  fn hashes(&self) -> &RwLock<Hashes> {
    &self.hashes
  }

  fn indices(&self) -> &[RwLock<Records<Index>>] {
    &self.indices
  }

  fn fill_indices(
    indices: &mut [RwLockWriteGuard<Records<Index>>],
    record: &TransactionRecord,
  ) {
    let inner = if record.is_persisted() {
      None
    } else {
      Some(Vec::new())
    };
    indices[0].insert(record.id(), Arc::new(Mutex::new(inner.clone())));
    indices[1].insert(record.id(), Arc::new(Mutex::new(inner)));
    if let Some(id_trunk) = record.id_trunk() {
      if let Some(index) = indices[0].get(&id_trunk) {
        debug!("Mutex check at line {}", line!());
        let mut index = index.lock().unwrap();
        debug!("Mutex check at line {}", line!());
        record.fill_index(&mut index);
      }
    }
    if let Some(id_branch) = record.id_branch() {
      if let Some(index) = indices[1].get(&id_branch) {
        debug!("Mutex check at line {}", line!());
        let mut index = index.lock().unwrap();
        debug!("Mutex check at line {}", line!());
        record.fill_index(&mut index);
      }
    }
  }
}

impl TransactionMapper {
  pub fn fetch_many(
    &self,
    conn: &mut mysql::Conn,
    mut input: Vec<&str>,
  ) -> FetchManyResult {
    input.dedup();
    let cached = {
      debug!("Mutex check at line {}", line!());
      let records = self.records.read().unwrap();
      debug!("Mutex check at line {}", line!());
      let hashes = self.hashes.read().unwrap();
      debug!("Mutex check at line {}", line!());
      input
        .iter()
        .filter_map(|&hash| {
          hashes
            .get(hash)
            .and_then(|&id| records.get(&id).map(|x| (hash, (id, x.clone()))))
        })
        .collect::<HashMap<_, _>>()
    };
    let missing = input
      .iter()
      .filter(|&hash| !cached.contains_key(hash))
      .cloned()
      .collect::<Vec<_>>();
    let found = TransactionRecord::find_by_hashes(conn, missing)?;
    debug!("Mutex check at line {}", line!());
    let mut records = self.records.write().unwrap();
    debug!("Mutex check at line {}", line!());
    let mut hashes = self.hashes.write().unwrap();
    debug!("Mutex check at line {}", line!());
    let mut indices = self.lock_indices();
    debug!("Mutex check at line {}", line!());
    let mut output = input
      .into_iter()
      .map(|hash| {
        cached
          .get(hash)
          .map(|&(id_tx, ref record)| {
            (id_tx, hash.to_owned(), record.clone())
          })
          .unwrap_or_else(|| {
            hashes
              .get(hash)
              .and_then(|&id_tx| {
                records
                  .get(&id_tx)
                  .map(|record| (id_tx, hash.to_owned(), record.clone()))
              })
              .unwrap_or_else(|| {
                let record = found
                  .iter()
                  .find(|record| record.hash() == hash)
                  .cloned()
                  .unwrap_or_else(|| {
                    TransactionRecord::placeholder(
                      hash.to_owned(),
                      self.next_id(),
                    )
                  });
                let id_tx = record.id();
                hashes.insert(hash.to_owned(), id_tx);
                Self::fill_indices(&mut indices, &record);
                let wrapper = Arc::new(Mutex::new(record));
                records.insert(id_tx, wrapper.clone());
                (id_tx, hash.to_owned(), wrapper)
              })
          })
      })
      .collect::<Vec<_>>();
    output.sort_unstable_by_key(|&(id_tx, _, _)| id_tx);
    Ok(output)
  }

  pub fn trunk_index(&self, id: u64) -> Option<Arc<Mutex<Index>>> {
    debug!("Mutex check at line {}", line!());
    let trunks = self.indices[0].read().unwrap();
    debug!("Mutex check at line {}", line!());
    trunks.get(&id).cloned()
  }

  pub fn branch_index(&self, id: u64) -> Option<Arc<Mutex<Index>>> {
    debug!("Mutex check at line {}", line!());
    let branches = self.indices[1].read().unwrap();
    debug!("Mutex check at line {}", line!());
    branches.get(&id).cloned()
  }

  pub fn fetch_trunk<'a>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
  ) -> Result<MutexGuard<'a, Index>> {
    self.fetch_index(conn, id, index, TransactionRecord::find_trunk)
  }

  pub fn fetch_branch<'a>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
  ) -> Result<MutexGuard<'a, Index>> {
    self.fetch_index(conn, id, index, TransactionRecord::find_branch)
  }

  pub fn fetch_bundle<'a>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
  ) -> Result<MutexGuard<'a, Index>> {
    self.fetch_index(conn, id, index, TransactionRecord::find_bundle)
  }

  fn fetch_index<'a, F>(
    &self,
    conn: &mut mysql::Conn,
    id: u64,
    index: &'a Mutex<Index>,
    f: F,
  ) -> Result<MutexGuard<'a, Index>>
  where
    F: FnOnce(&mut mysql::Conn, u64)
      -> Result<Vec<TransactionRecord>>,
  {
    {
      debug!("Mutex check at line {}", line!());
      let guard = index.lock().unwrap();
      debug!("Mutex check at line {}", line!());
      if guard.is_some() {
        return Ok(guard);
      }
    }
    f(conn, id).map(|found| {
      debug!("Mutex check at line {}", line!());
      let mut index = index.lock().unwrap();
      debug!("Mutex check at line {}", line!());
      match *index {
        Some(_) => index,
        None => {
          debug!("Mutex check at line {}", line!());
          let mut records = self.records.write().unwrap();
          debug!("Mutex check at line {}", line!());
          let mut hashes = self.hashes.write().unwrap();
          debug!("Mutex check at line {}", line!());
          let mut indices = self.lock_indices();
          debug!("Mutex check at line {}", line!());
          let mut ids = found
            .into_iter()
            .map(|record| {
              let id_tx = record.id();
              records.entry(id_tx).or_insert_with(|| {
                hashes.insert(record.hash().to_owned(), id_tx);
                Self::fill_indices(&mut indices, &record);
                Arc::new(Mutex::new(record))
              });
              id_tx
            })
            .collect::<Vec<_>>();
          ids.sort_unstable();
          ids.dedup();
          *index = Some(ids);
          index
        }
      }
    })
  }
}
<|endoftext|>


<commit_before>//! Extension trait and implementation for observing and action on streamed data.

use Data;
use dataflow::channels::pact::Pipeline;
use dataflow::{Stream, Scope};
use dataflow::operators::generic::unary::Unary;

/// Methods to inspect records and batches of records on a stream.
pub trait Inspect<G: Scope, D: Data> {
    /// Runs a supplied closure on each observed data element.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect(|x| println!("seen: {:?}", x));
    /// });
    /// ```
    fn inspect<F: FnMut(&D)+'static>(&self, func: F) -> Self;
    /// Runs a supplied closure on each observed data batch (time and data slice).
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_batch(|t,xs| println!("seen at: {:?}\t{:?} records", t, xs.len()));
    /// });
    /// ```
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, func: F) -> Self;
}

impl<G: Scope, D: Data> Inspect<G, D> for Stream<G, D> {

    fn inspect<F: FnMut(&D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            input.for_each(|time, data| {
                for datum in data.iter() { func(datum); }
                output.session(&time).give_content(data);
            });
        })
    }

    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "InspectBatch", move |input, output| {
            input.for_each(|time, data| {
                func(&time, &data[..]);
                output.session(&time).give_content(data);
            });
        })
    }
}
<commit_msg>Inspect tuples and associated times<commit_after>//! Extension trait and implementation for observing and action on streamed data.

use Data;
use dataflow::channels::pact::Pipeline;
use dataflow::{Stream, Scope};
use dataflow::operators::generic::unary::Unary;

/// Methods to inspect records and batches of records on a stream.
pub trait Inspect<G: Scope, D: Data> {
    /// Runs a supplied closure on each observed data element.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect(|x| println!("seen: {:?}", x));
    /// });
    /// ```
    fn inspect<F: FnMut(&D)+'static>(&self, func: F) -> Self;

    /// Runs a supplied closure on each observed data element and associated time.
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_time(|t, x| println!("seen at: {:?}\t{:?}", t, x));
    /// });
    /// ```
    fn inspect_time<F: FnMut(&G::Timestamp, &D)+'static>(&self, func: F) -> Self;

    /// Runs a supplied closure on each observed data batch (time and data slice).
    ///
    /// #Examples
    /// ```
    /// use timely::dataflow::operators::{ToStream, Map, Inspect};
    ///
    /// timely::example(|scope| {
    ///     (0..10).to_stream(scope)
    ///            .inspect_batch(|t,xs| println!("seen at: {:?}\t{:?} records", t, xs.len()));
    /// });
    /// ```
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, func: F) -> Self;
}

impl<G: Scope, D: Data> Inspect<G, D> for Stream<G, D> {

    fn inspect<F: FnMut(&D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            input.for_each(|time, data| {
                for datum in data.iter() { func(datum); }
                output.session(&time).give_content(data);
            });
        })
    }

    fn inspect_time<F: FnMut(&G::Timestamp, &D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.inspect_batch(move |time, data| {
            for datum in data.iter() {
                func(&time, &datum);
            }
        })
    }

    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "InspectBatch", move |input, output| {
            input.for_each(|time, data| {
                func(&time, &data[..]);
                output.session(&time).give_content(data);
            });
        })
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate yenc;

use rand::random;
use std::env::temp_dir;
use std::fs::{create_dir, remove_file, File};
use std::io::{Read, Write};
use std::path::Path;

fn encode(input_filename: &str) {
    let parts = 1;

    println!("{}", input_filename);
    let input_file = File::open(&input_filename).expect("Cannot open file");

    let path = Path::new(&input_filename);
    let total_size = input_file.metadata().unwrap().len();
    let part_size: u64 = total_size / u64::from(parts);

    for part in 1..parts + 1 {
        let output_filename = format!("{}.{:03}", input_filename, part);
        let mut output_file = File::create(&output_filename).expect("Cannot create file");
        println!("{}", output_filename);

        let begin = (u64::from(part) - 1) * part_size + 1;
        let end = if begin + part_size < total_size {
            begin + part_size - 1
        } else {
            total_size
        };

        let encode_options = yenc::EncodeOptions::default()
            .parts(parts)
            .part(part)
            .begin(begin)
            .end(end);

        match yenc::encode_file(path, &encode_options, &mut output_file) {
            Err(err) => {
                println!(
                    "Error yEncoding {} to {}: {}",
                    input_filename, output_filename, err
                );
            }
            Ok(_) => {
                println!(
                    "Successfully yEncoded {} to {}",
                    input_filename, output_filename
                );
            }
        };
    }
}

fn decode(input_filename: &str, output_directory: &str) -> u32 {
    match yenc::decode_file(&input_filename, &output_directory) {
        Err(err) => {
            println!("Error yEnc decoding {}: {}", input_filename, err);
            1
        }
        Ok(output_filename) => {
            println!(
                "Successfully yEnc decoded {} to {}",
                input_filename, output_filename
            );
            0
        }
    }
}

fn encode_decode_are_equal(data: &[u8], filename: &str) -> bool {
    // create temp dir
    let tmpdir = temp_dir();
    println!("{}", tmpdir.display());
    // created 'decoded' dir in temp dir
    let mut decoded_dir = tmpdir.clone();
    decoded_dir.push("decoded");
    let _ = create_dir(decoded_dir.clone());

    // dump data to file
    let mut filepath = tmpdir.clone();
    filepath.push(filename);
    let mut f = File::create(&filepath).unwrap();
    f.write(data).unwrap();

    // encode file
    encode(filepath.to_str().unwrap());

    let mut decoded_file = decoded_dir.clone();
    decoded_file.push(filename);

    remove_file(&decoded_file).unwrap();

    // decode file
    decode(
        &(filepath.to_str().unwrap().to_owned() + ".001"),
        decoded_dir.to_str().unwrap(),
    );

    // check that files are identical
    let mut decoded_file = decoded_dir.clone();
    decoded_file.push(filename);
    identical(filepath, decoded_file)
}

fn identical<P: AsRef<Path>>(file1: P, file2: P) -> bool {
    let mut data1 = Vec::new();
    let size1 = File::open(file1).unwrap().read_to_end(&mut data1).unwrap();
    let mut data2 = Vec::new();
    let size2 = File::open(file2).unwrap().read_to_end(&mut data2).unwrap();
    size1 == size2 && &data1 == &data2
}

#[test]
fn test_ascii() {
    let data = (0..10_000_000)
        .map(|c| (c & 0x7f) as u8)
        .collect::<Vec<u8>>();

    assert!(encode_decode_are_equal(&data, "ascii"));
}

#[test]
fn test_binary() {
    let data = (0..10_000_000)
        .map(|c| (c & 0xff) as u8)
        .collect::<Vec<u8>>();

    assert!(encode_decode_are_equal(&data, "binary"));
}

#[test]
fn test_random() {
    let data = (0..10_000_000).map(|_| random::<u8>()).collect::<Vec<u8>>();

    assert!(encode_decode_are_equal(&data, "random"));
}
<commit_msg>Reduce parallelism in roundtrip test<commit_after>extern crate rand;
extern crate yenc;

#[macro_use]
extern crate lazy_static;

use rand::random;
use std::env::temp_dir;
use std::fs::{create_dir, remove_dir, remove_file, File};
use std::io::{Read, Result, Write};
use std::path::Path;
use std::sync::Mutex;

lazy_static! {
    static ref M: Mutex<u8> = Mutex::new(0);
}

fn encode(input_filename: &str) {
    let parts = 1;

    println!("{}", input_filename);
    let input_file = File::open(&input_filename).expect("Cannot open file");

    let path = Path::new(&input_filename);
    let total_size = input_file.metadata().unwrap().len();
    let part_size: u64 = total_size / u64::from(parts);

    for part in 1..parts + 1 {
        let output_filename = format!("{}.{:03}", input_filename, part);
        let mut output_file = File::create(&output_filename).expect("Cannot create file");
        println!("{}", output_filename);

        let begin = (u64::from(part) - 1) * part_size + 1;
        let end = if begin + part_size < total_size {
            begin + part_size - 1
        } else {
            total_size
        };

        let encode_options = yenc::EncodeOptions::default()
            .parts(parts)
            .part(part)
            .begin(begin)
            .end(end);

        match yenc::encode_file(path, &encode_options, &mut output_file) {
            Err(err) => {
                println!(
                    "Error yEncoding {} to {}: {}",
                    input_filename, output_filename, err
                );
            }
            Ok(_) => {
                println!(
                    "Successfully yEncoded {} to {}",
                    input_filename, output_filename
                );
            }
        };
    }
}

fn decode(input_filename: &str, output_directory: &str) -> u32 {
    match yenc::decode_file(&input_filename, &output_directory) {
        Err(err) => {
            println!("Error yEnc decoding {}: {}", input_filename, err);
            1
        }
        Ok(output_filename) => {
            println!(
                "Successfully yEnc decoded {} to {}",
                input_filename, output_filename
            );
            0
        }
    }
}

fn encode_decode_are_equal(data: &[u8], filename: &str) -> Result<bool> {
    // synchronize, to prevent test cases run in parallel and mess up directories
    let _x = M.lock().unwrap();

    // create temp dir
    let tmpdir = temp_dir();
    println!("{}", tmpdir.display());

    // created 'decoded' dir in temp dir
    let mut decoded_dir = tmpdir.clone();
    decoded_dir.push("decoded");
    create_dir(decoded_dir.clone())?;

    // dump data to file
    let mut filepath = tmpdir.clone();
    filepath.push(filename);
    let mut f = File::create(&filepath)?;
    f.write(data).unwrap();

    // encode file
    encode(filepath.to_str().unwrap());

    let mut decoded_file = decoded_dir.clone();
    decoded_file.push(filename);

    // decode file
    decode(
        &(filepath.to_str().unwrap().to_owned() + ".001"),
        decoded_dir.to_str().unwrap(),
    );

    // check that files are identical
    let mut decoded_file = decoded_dir.clone();
    decoded_file.push(filename);
    let result = identical(filepath.clone(), decoded_file.clone());

    //clean up
    remove_file(filepath)?;
    remove_file(decoded_file)?;
    remove_dir(decoded_dir)?;

    Ok(result)
}

fn identical<P: AsRef<Path>>(file1: P, file2: P) -> bool {
    let mut data1 = Vec::new();
    let size1 = File::open(file1).unwrap().read_to_end(&mut data1).unwrap();
    let mut data2 = Vec::new();
    let size2 = File::open(file2).unwrap().read_to_end(&mut data2).unwrap();
    size1 == size2 && &data1 == &data2
}

#[test]
fn test_ascii() {
    let data = (0..10_000_000)
        .map(|c| (c & 0x7f) as u8)
        .collect::<Vec<u8>>();

    assert!(encode_decode_are_equal(&data, "ascii").unwrap());
}

#[test]
fn test_binary() {
    let data = (0..10_000_000)
        .map(|c| (c & 0xff) as u8)
        .collect::<Vec<u8>>();

    assert!(encode_decode_are_equal(&data, "binary").unwrap());
}

#[test]
fn test_random() {
    let data = (0..10_000_000).map(|_| random::<u8>()).collect::<Vec<u8>>();

    assert!(encode_decode_are_equal(&data, "random").unwrap());
}
<|endoftext|>


<commit_before>use crate::bounding_volume::AABB;
use crate::math::{Isometry, Point};
use crate::partitioning::{BestFirstVisitStatus, BestFirstVisitor};
use crate::query::{
    visitors::CompositePointContainmentTest, PointProjection, PointQuery, PointQueryWithLocation,
};
use crate::shape::{CompositeShape, FeatureId, TriMesh, TrianglePointLocation};
use na::{self, RealField};

impl<N: RealField> PointQuery<N> for TriMesh<N> {
    #[inline]
    fn project_point(&self, m: &Isometry<N>, point: &Point<N>, solid: bool) -> PointProjection<N> {
        let (projection, _) = self.project_point_with_location(m, point, solid);
        projection
    }

    #[inline]
    fn project_point_with_feature(
        &self,
        _: &Isometry<N>,
        _: &Point<N>,
    ) -> (PointProjection<N>, FeatureId) {
        unimplemented!()
    }

    // FIXME: implement distance_to_point too?

    #[inline]
    fn contains_point(&self, m: &Isometry<N>, point: &Point<N>) -> bool {
        let ls_pt = m.inverse_transform_point(point);
        let mut visitor = CompositePointContainmentTest {
            shape: self,
            point: &ls_pt,
            found: false,
        };

        self.bvh().visit(&mut visitor);

        visitor.found
    }
}

impl<N: RealField> PointQueryWithLocation<N> for TriMesh<N> {
    type Location = (usize, TrianglePointLocation<N>);

    #[inline]
    fn project_point_with_location(
        &self,
        m: &Isometry<N>,
        point: &Point<N>,
        _: bool,
    ) -> (PointProjection<N>, Self::Location) {
        let ls_pt = m.inverse_transform_point(point);
        let mut visitor = TriMeshPointProjVisitor {
            polyline: self,
            point: &ls_pt,
        };

        let (mut proj, extra_info) = self.bvh().best_first_search(&mut visitor).unwrap().1;
        proj.point = m * proj.point;

        (proj, extra_info)
    }
}

/*
 * Visitors
 */
struct TriMeshPointProjVisitor<'a, N: 'a + RealField> {
    polyline: &'a TriMesh<N>,
    point: &'a Point<N>,
}

impl<'a, N: RealField> BestFirstVisitor<N, usize, AABB<N>> for TriMeshPointProjVisitor<'a, N> {
    type Result = (PointProjection<N>, (usize, TrianglePointLocation<N>));

    #[inline]
    fn visit(
        &mut self,
        best: N,
        aabb: &AABB<N>,
        data: Option<&usize>,
    ) -> BestFirstVisitStatus<N, Self::Result> {
        let dist = aabb.distance_to_point(&Isometry::identity(), self.point, true);

        let mut res = BestFirstVisitStatus::Continue {
            cost: dist,
            result: None,
        };

        if let Some(b) = data {
            if dist < best {
                let (proj, extra_info) = self.polyline.triangle_at(*b).project_point_with_location(
                    &Isometry::identity(),
                    self.point,
                    true,
                );

                let extra_info = (*b, extra_info);
                res = BestFirstVisitStatus::Continue {
                    cost: na::distance(self.point, &proj.point),
                    result: Some((proj, extra_info)),
                };
            }
        }

        res
    }
}
<commit_msg>Implement TriMesh::project_point_with_feature<commit_after>use crate::bounding_volume::AABB;
use crate::math::{Isometry, Point};
use crate::partitioning::{BestFirstVisitStatus, BestFirstVisitor};
use crate::query::{
    visitors::CompositePointContainmentTest, PointProjection, PointQuery, PointQueryWithLocation,
};
use crate::shape::{CompositeShape, FeatureId, TriMesh, TrianglePointLocation};
use na::{self, RealField};

impl<N: RealField> PointQuery<N> for TriMesh<N> {
    #[inline]
    fn project_point(&self, m: &Isometry<N>, point: &Point<N>, solid: bool) -> PointProjection<N> {
        let (projection, _) = self.project_point_with_location(m, point, solid);
        projection
    }

    #[inline]
    fn project_point_with_feature(
        &self,
        m: &Isometry<N>,
        point: &Point<N>,
    ) -> (PointProjection<N>, FeatureId) {
        let (projection, (triangle_id, location)) =
            self.project_point_with_location(m, point, false);
        let face = &self.faces()[triangle_id];
        let feature_id = match location {
            TrianglePointLocation::OnVertex(triangle_local_id) => {
                FeatureId::Vertex(face.indices[triangle_local_id])
            }
            TrianglePointLocation::OnEdge(triangle_local_id, _) => {
                FeatureId::Edge(face.edges[triangle_local_id])
            }
            TrianglePointLocation::OnFace(_, _) => FeatureId::Face(triangle_id),
            TrianglePointLocation::OnSolid => FeatureId::Unknown,
        };
        (projection, feature_id)
    }

    // FIXME: implement distance_to_point too?

    #[inline]
    fn contains_point(&self, m: &Isometry<N>, point: &Point<N>) -> bool {
        let ls_pt = m.inverse_transform_point(point);
        let mut visitor = CompositePointContainmentTest {
            shape: self,
            point: &ls_pt,
            found: false,
        };

        self.bvh().visit(&mut visitor);

        visitor.found
    }
}

impl<N: RealField> PointQueryWithLocation<N> for TriMesh<N> {
    type Location = (usize, TrianglePointLocation<N>);

    #[inline]
    fn project_point_with_location(
        &self,
        m: &Isometry<N>,
        point: &Point<N>,
        _: bool,
    ) -> (PointProjection<N>, Self::Location) {
        let ls_pt = m.inverse_transform_point(point);
        let mut visitor = TriMeshPointProjVisitor {
            polyline: self,
            point: &ls_pt,
        };

        let (mut proj, extra_info) = self.bvh().best_first_search(&mut visitor).unwrap().1;
        proj.point = m * proj.point;

        (proj, extra_info)
    }
}

/*
 * Visitors
 */
struct TriMeshPointProjVisitor<'a, N: 'a + RealField> {
    polyline: &'a TriMesh<N>,
    point: &'a Point<N>,
}

impl<'a, N: RealField> BestFirstVisitor<N, usize, AABB<N>> for TriMeshPointProjVisitor<'a, N> {
    type Result = (PointProjection<N>, (usize, TrianglePointLocation<N>));

    #[inline]
    fn visit(
        &mut self,
        best: N,
        aabb: &AABB<N>,
        data: Option<&usize>,
    ) -> BestFirstVisitStatus<N, Self::Result> {
        let dist = aabb.distance_to_point(&Isometry::identity(), self.point, true);

        let mut res = BestFirstVisitStatus::Continue {
            cost: dist,
            result: None,
        };

        if let Some(b) = data {
            if dist < best {
                let (proj, extra_info) = self.polyline.triangle_at(*b).project_point_with_location(
                    &Isometry::identity(),
                    self.point,
                    true,
                );

                let extra_info = (*b, extra_info);
                res = BestFirstVisitStatus::Continue {
                    cost: na::distance(self.point, &proj.point),
                    result: Some((proj, extra_info)),
                };
            }
        }

        res
    }
}
<|endoftext|>