<commit_before>//! Fluent test assertions in Rust
//!
//! Spectral is a testing framework designed to make your assertions read like plain English.
//! This allows you to more easily expose the intent of your test, rather than having it shrouded by
//! assertions which work, but are opaque on their meaning.
//!
//! Methods available to assert with are dependent upon the type of the subject under test.
//! Assertions are available for some basic types, but there is still a great deal missing from the
//! standard library.
//!
//! ## Usage
//!
//! Add the dependency to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! spectral = "0.2.0"
//! ```
//!
//! Then add this to your crate:
//!
//! ```rust
//! extern crate spectral;
//! ```
//!
//! If you want macro support, include `#[macro_use]` to the declaration:
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate spectral;
//! ```
//!
//! To quickly start using assertions, `use` the prelude module:
//!
//! ```rust
//! use spectral::prelude::*;
//! ```
//!
//! ## Example
//!
//! We're going to make a few assertions on a `String` we create. Normally you would
//! want to assert on the output of something, but we'll just pretend that something created it.
//!
//! First, we'll create a new test with our `String`.
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "Hello World!";
//! }
//! ```
//!
//! Note that it is good practice to make sure that you name your test in a way that actually
//! explains what it is trying to test. When you have a number of tests, and one of them fails,
//! something like this is easier to understand:
//!
//! ```rust,ignore
//! #[test]
//! pub fn should_return_false_if_condition_does_not_hold() {
//!     ...
//! }
//! ```
//!
//! Rather than if you have a test like this:
//!
//! ```rust,ignore
//! #[test]
//! pub fn should_work() {
//!     ...
//! }
//! ```
//!
//! Unfortunately, our test isn't named very well at the moment, but given the lack of context,
//! it'll have to do for now.
//!
//! Now that we have something to test, we need to actually start asserting on it. The first part
//! to that is to provide it to the `assert_that` function. Note that we need to provide it as a
//! reference.
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "Hello World!";
//!     assert_that(&subject);
//! }
//! ```
//!
//! If we run that with `cargo test`, we'll see the following output:
//!
//! ```bash
//! running 1 test
//! test should_be_the_correct_string ... ok
//! ```
//!
//! Our test compiles and passes, but we still haven't made any assertions. Let's make a simple one
//! to start with. We'll check to see that it starts with the letter 'H'.
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "Hello World!";
//!     assert_that(&subject).starts_with(&"H");
//! }
//! ```
//!
//! Once you run this, you'll notice that the test still passes. That's because we've just proven
//! something that was already true. Usually you'll want to start with a failing test, and then
//! change your code to make it pass, rather than writing the test after the implementation.
//!
//! But for the purpose of exploration, let's break the actual value. We'll change "Hello World!"
//! to be "ello World!".
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "ello World!";
//!     assert_that(&subject).starts_with(&"H");
//! }
//! ```
//!
//! This time, we see that the test fails, and we also get some output from our assertion to tell
//! us what it was, and what it was expected to be:
//!
//! ```bash
//! running 1 test
//! test should_be_the_correct_string ... FAILED
//!
//! failures:
//!
//! ---- should_be_the_correct_string stdout ----
//!     thread 'should_be_the_correct_string' panicked at 'expected string starting with <"H"> but
//!     was <"ello World!">', src/lib.rs:204
//! ```
//!
//! Great! So we've just encountered a failing test. This particular case is quite easy to fix up
//! (just add the letter 'H' back to the start of the `String`), but we can also see that the panic
//! message tells us enough information to work that out as well.
//!
//! Now, this was just a simple example, and there's a number of features not demonstrated, but
//! hopefully it's enough to start you off with writing assertions in your tests using Spectral.

use std::cmp::PartialEq;
use std::fmt::Debug;

use colours::{TERM_RED, TERM_BOLD, TERM_RESET};

pub mod numeric;
pub mod option;
pub mod path;
pub mod prelude;
pub mod result;
pub mod string;
pub mod vec;
pub mod iter;

// Disable colours during tests, otherwise trying to assert on the panic message becomes
// significantly more annoying.
#[cfg(not(test))]
mod colours {
    pub const TERM_RED: &'static str = "\x1B[31m";
    pub const TERM_BOLD: &'static str = "\x1B[1m";
    pub const TERM_RESET: &'static str = "\x1B[0m";
}

#[cfg(test)]
mod colours {
    pub const TERM_RED: &'static str = "";
    pub const TERM_BOLD: &'static str = "";
    pub const TERM_RESET: &'static str = "";
}

#[macro_export]
macro_rules! assert_that {
    (&$subject:ident$(.$additional_subject:ident)*) => {
        assert_that!($subject$(.$additional_subject)*)
    };
    ($subject:ident$(.$additional_subject:ident)*) => {
        assert_that(&$subject$(.$additional_subject)*)
    };
}

/// A description for an assertion.
///
/// This is created by the `asserting` function.
#[derive(Debug)]
pub struct SpecDescription<'r> {
    value: &'r str,
}

/// An assertion.
///
/// This is created by either the `assert_that` function, or by calling `that` on a
/// `SpecDescription`.
#[derive(Debug)]
pub struct Spec<'s, S: 's> {
    pub subject: &'s S,
    description: Option<&'s str>,
    expected: Option<String>,
    actual: Option<String>,
}

/// Wraps a subject in a `Spec` to provide assertions against it.
///
/// The subject must be a reference.
pub fn assert_that<'s, S>(subject: &'s S) -> Spec<'s, S> {
    Spec {
        subject: subject,
        description: None,
        expected: None,
        actual: None,
    }
}

/// Describes an assertion.
pub fn asserting<'r>(description: &'r str) -> SpecDescription {
    SpecDescription { value: description }
}

impl<'r> SpecDescription<'r> {
    /// Creates a new assertion, passing through its description.
    pub fn that<S>(self, subject: &'r S) -> Spec<'r, S> {
        Spec {
            subject: subject,
            description: Some(self.value),
            expected: None,
            actual: None,
        }
    }
}

impl<'s, S> Spec<'s, S> {
    /// Builder method to add the expected value for the panic message.
    pub fn with_expected(&mut self, expected: String) -> &mut Self {
        let mut spec = self;
        spec.expected = Some(expected);
        spec
    }

    /// Builder method to add the actual value for the panic message.
    pub fn with_actual(&mut self, actual: String) -> &mut Self {
        let mut spec = self;
        spec.actual = Some(actual);
        spec
    }

    /// Builds the failure message with a description (if present), the expected value,
    /// and the actual value and then calls `panic` with the created message.
    pub fn fail(&mut self) {
        if !self.expected.is_some() || !self.actual.is_some() {
            panic!("invalid assertion");
        }

        match self.description {
            Some(description) => {
                panic!(format!("\n\t{}{}:{}\n\t{}expected: {}\n\t but was: {}{}\n",
                               TERM_BOLD,
                               description,
                               TERM_RESET,
                               TERM_RED,
                               self.expected.clone().unwrap(),
                               self.actual.clone().unwrap(),
                               TERM_RESET))
            }
            None => {
                panic!(format!("\n\t{}expected: {}\n\t but was: {}{}\n",
                               TERM_RED,
                               self.expected.clone().unwrap(),
                               self.actual.clone().unwrap(),
                               TERM_RESET))
            }
        }
    }

    /// Calls `panic` with the provided message, prepending the assertion description
    /// if present.
    fn fail_with_message(&mut self, message: String) {
        match self.description {
            Some(description) => {
                panic!(format!("\n\t{}{}:{}\n\t{}{}{}\n",
                               TERM_BOLD,
                               description,
                               TERM_RESET,
                               TERM_RED,
                               message,
                               TERM_RESET))
            }
            None => panic!(format!("\n\t{}{}{}\n", TERM_RED, message, TERM_RESET)),
        }
    }
}

impl<'s, S> Spec<'s, S>
    where S: Debug + PartialEq
{
    /// Asserts that the actual value and the expected value are equal. The value type must
    /// implement `PartialEq`.
    ///
    /// ```rust,ignore
    /// assert_that(&"hello").is_equal_to(&"hello");
    /// ```
    pub fn is_equal_to(&mut self, expected: &S) -> &mut Self {
        let subject = self.subject;

        if !subject.eq(expected) {
            self.with_expected(format!("<{:?}>", expected))
                .with_actual(format!("<{:?}>", subject))
                .fail();
        }

        self
    }
}

impl<'s, S> Spec<'s, S>
    where S: Debug
{
    /// Accepts a function accepting the value type which returns a bool. Returning false will
    /// cause the assertion to fail.
    ///
    /// NOTE: The resultant panic message will only state the actual value. It's recommended that
    /// you write your own assertion rather than relying upon this.
    ///
    /// ```rust,ignore
    /// assert_that(&"hello").matches(|x| x.eq(&"hello"));
    /// ```
    pub fn matches<F>(&mut self, matching_function: F) -> &mut Self
        where F: Fn(&'s S) -> bool
    {
        let subject = self.subject;

        if !matching_function(subject) {
            self.fail_with_message(format!("expectation failed for value <{:?}>", subject));
        }

        self
    }

    /// Transforms the subject of the `Spec` by passing it through to the provided mapping
    /// function.
    ///
    /// ```rust,ignore
    /// let test_struct = TestStruct { value: 5 };
    /// assert_that(&test_struct).map(|val| &val.value).is_equal_to(&5);
    /// ```
    pub fn map<F, T>(self, mapping_function: F) -> Spec<'s, T>
        where F: Fn(&'s S) -> &'s T
    {
        Spec {
            subject: mapping_function(self.subject),
            description: self.description,
            expected: self.expected,
            actual: self.actual,
        }
    }
}

#[cfg(test)]
mod tests {

    use super::prelude::*;

    #[test]
    fn should_be_able_to_use_macro_form_with_deliberate_reference() {
        let test_vec = vec![1, 2, 3, 4, 5];

        assert_that!(&test_vec)
            .has_length(5)
            .contains(&3)
            .contains(&5)
            .mapped_contains(|val| val * 2, &6);
    }

    #[test]
    fn should_be_able_to_use_macro_form_without_deliberate_reference() {
        let test_vec = vec![1, 2, 3, 4, 5];

        assert_that!(test_vec)
            .has_length(5)
            .contains(&3)
            .contains(&5)
            .mapped_contains(|val| val * 2, &6);
    }

    #[test]
    fn should_be_able_to_chain_assertions() {
        assert_that(&vec![1, 2, 3, 4, 5])
            .has_length(5)
            .contains(&3)
            .contains(&5)
            .mapped_contains(|val| val * 2, &6);
    }

    #[test]
    #[should_panic(expected = "\n\ttest condition:\n\texpected: <2>\n\t but was: <1>")]
    fn should_contain_assertion_description_in_panic() {
        asserting(&"test condition").that(&1).is_equal_to(&2);
    }

    #[test]
    #[should_panic(expected = "\n\tclosure:\n\texpectation failed for value <\"Hello\">")]
    fn should_contain_assertion_description_if_message_is_provided() {
        let value = "Hello";
        asserting(&"closure").that(&value).matches(|val| val.eq(&"Hi"));
    }

    #[test]
    fn should_not_panic_on_equal_subjects() {
        assert_that(&1).is_equal_to(&1);
    }

    #[test]
    #[should_panic(expected = "\n\texpected: <2>\n\t but was: <1>")]
    fn should_panic_on_unequal_subjects() {
        assert_that(&1).is_equal_to(&2);
    }

    #[test]
    fn should_not_panic_if_value_matches() {
        let value = "Hello";
        assert_that(&value).matches(|val| val.eq(&"Hello"));
    }

    #[test]
    #[should_panic(expected = "\n\texpectation failed for value <\"Hello\">")]
    fn should_panic_if_value_does_not_match() {
        let value = "Hello";
        assert_that(&value).matches(|val| val.eq(&"Hi"));
    }

    #[test]
    fn should_be_able_to_map_to_inner_field_of_struct_when_matching() {
        let test_struct = TestStruct { value: 5 };
        assert_that(&test_struct).map(|val| &val.value).is_equal_to(&5);
    }

    #[derive(Debug, PartialEq)]
    struct TestStruct {
        pub value: u8,
    }

}
<commit_msg>Update version in lib.rs documentation<commit_after>//! Fluent test assertions in Rust
//!
//! Spectral is a testing framework designed to make your assertions read like plain English.
//! This allows you to more easily expose the intent of your test, rather than having it shrouded by
//! assertions which work, but are opaque on their meaning.
//!
//! Methods available to assert with are dependent upon the type of the subject under test.
//! Assertions are available for some basic types, but there is still a great deal missing from the
//! standard library.
//!
//! ## Usage
//!
//! Add the dependency to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! spectral = "0.3.0"
//! ```
//!
//! Then add this to your crate:
//!
//! ```rust
//! extern crate spectral;
//! ```
//!
//! If you want macro support, include `#[macro_use]` to the declaration:
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate spectral;
//! ```
//!
//! To quickly start using assertions, `use` the prelude module:
//!
//! ```rust
//! use spectral::prelude::*;
//! ```
//!
//! ## Example
//!
//! We're going to make a few assertions on a `String` we create. Normally you would
//! want to assert on the output of something, but we'll just pretend that something created it.
//!
//! First, we'll create a new test with our `String`.
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "Hello World!";
//! }
//! ```
//!
//! Note that it is good practice to make sure that you name your test in a way that actually
//! explains what it is trying to test. When you have a number of tests, and one of them fails,
//! something like this is easier to understand:
//!
//! ```rust,ignore
//! #[test]
//! pub fn should_return_false_if_condition_does_not_hold() {
//!     ...
//! }
//! ```
//!
//! Rather than if you have a test like this:
//!
//! ```rust,ignore
//! #[test]
//! pub fn should_work() {
//!     ...
//! }
//! ```
//!
//! Unfortunately, our test isn't named very well at the moment, but given the lack of context,
//! it'll have to do for now.
//!
//! Now that we have something to test, we need to actually start asserting on it. The first part
//! to that is to provide it to the `assert_that` function. Note that we need to provide it as a
//! reference.
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "Hello World!";
//!     assert_that(&subject);
//! }
//! ```
//!
//! If we run that with `cargo test`, we'll see the following output:
//!
//! ```bash
//! running 1 test
//! test should_be_the_correct_string ... ok
//! ```
//!
//! Our test compiles and passes, but we still haven't made any assertions. Let's make a simple one
//! to start with. We'll check to see that it starts with the letter 'H'.
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "Hello World!";
//!     assert_that(&subject).starts_with(&"H");
//! }
//! ```
//!
//! Once you run this, you'll notice that the test still passes. That's because we've just proven
//! something that was already true. Usually you'll want to start with a failing test, and then
//! change your code to make it pass, rather than writing the test after the implementation.
//!
//! But for the purpose of exploration, let's break the actual value. We'll change "Hello World!"
//! to be "ello World!".
//!
//! ```rust
//! #[test]
//! pub fn should_be_the_correct_string() {
//!     let subject = "ello World!";
//!     assert_that(&subject).starts_with(&"H");
//! }
//! ```
//!
//! This time, we see that the test fails, and we also get some output from our assertion to tell
//! us what it was, and what it was expected to be:
//!
//! ```bash
//! running 1 test
//! test should_be_the_correct_string ... FAILED
//!
//! failures:
//!
//! ---- should_be_the_correct_string stdout ----
//!     thread 'should_be_the_correct_string' panicked at 'expected string starting with <"H"> but
//!     was <"ello World!">', src/lib.rs:204
//! ```
//!
//! Great! So we've just encountered a failing test. This particular case is quite easy to fix up
//! (just add the letter 'H' back to the start of the `String`), but we can also see that the panic
//! message tells us enough information to work that out as well.
//!
//! Now, this was just a simple example, and there's a number of features not demonstrated, but
//! hopefully it's enough to start you off with writing assertions in your tests using Spectral.

use std::cmp::PartialEq;
use std::fmt::Debug;

use colours::{TERM_RED, TERM_BOLD, TERM_RESET};

pub mod numeric;
pub mod option;
pub mod path;
pub mod prelude;
pub mod result;
pub mod string;
pub mod vec;
pub mod iter;

// Disable colours during tests, otherwise trying to assert on the panic message becomes
// significantly more annoying.
#[cfg(not(test))]
mod colours {
    pub const TERM_RED: &'static str = "\x1B[31m";
    pub const TERM_BOLD: &'static str = "\x1B[1m";
    pub const TERM_RESET: &'static str = "\x1B[0m";
}

#[cfg(test)]
mod colours {
    pub const TERM_RED: &'static str = "";
    pub const TERM_BOLD: &'static str = "";
    pub const TERM_RESET: &'static str = "";
}

#[macro_export]
macro_rules! assert_that {
    (&$subject:ident$(.$additional_subject:ident)*) => {
        assert_that!($subject$(.$additional_subject)*)
    };
    ($subject:ident$(.$additional_subject:ident)*) => {
        assert_that(&$subject$(.$additional_subject)*)
    };
}

/// A description for an assertion.
///
/// This is created by the `asserting` function.
#[derive(Debug)]
pub struct SpecDescription<'r> {
    value: &'r str,
}

/// An assertion.
///
/// This is created by either the `assert_that` function, or by calling `that` on a
/// `SpecDescription`.
#[derive(Debug)]
pub struct Spec<'s, S: 's> {
    pub subject: &'s S,
    description: Option<&'s str>,
    expected: Option<String>,
    actual: Option<String>,
}

/// Wraps a subject in a `Spec` to provide assertions against it.
///
/// The subject must be a reference.
pub fn assert_that<'s, S>(subject: &'s S) -> Spec<'s, S> {
    Spec {
        subject: subject,
        description: None,
        expected: None,
        actual: None,
    }
}

/// Describes an assertion.
pub fn asserting<'r>(description: &'r str) -> SpecDescription {
    SpecDescription { value: description }
}

impl<'r> SpecDescription<'r> {
    /// Creates a new assertion, passing through its description.
    pub fn that<S>(self, subject: &'r S) -> Spec<'r, S> {
        Spec {
            subject: subject,
            description: Some(self.value),
            expected: None,
            actual: None,
        }
    }
}

impl<'s, S> Spec<'s, S> {
    /// Builder method to add the expected value for the panic message.
    pub fn with_expected(&mut self, expected: String) -> &mut Self {
        let mut spec = self;
        spec.expected = Some(expected);
        spec
    }

    /// Builder method to add the actual value for the panic message.
    pub fn with_actual(&mut self, actual: String) -> &mut Self {
        let mut spec = self;
        spec.actual = Some(actual);
        spec
    }

    /// Builds the failure message with a description (if present), the expected value,
    /// and the actual value and then calls `panic` with the created message.
    pub fn fail(&mut self) {
        if !self.expected.is_some() || !self.actual.is_some() {
            panic!("invalid assertion");
        }

        match self.description {
            Some(description) => {
                panic!(format!("\n\t{}{}:{}\n\t{}expected: {}\n\t but was: {}{}\n",
                               TERM_BOLD,
                               description,
                               TERM_RESET,
                               TERM_RED,
                               self.expected.clone().unwrap(),
                               self.actual.clone().unwrap(),
                               TERM_RESET))
            }
            None => {
                panic!(format!("\n\t{}expected: {}\n\t but was: {}{}\n",
                               TERM_RED,
                               self.expected.clone().unwrap(),
                               self.actual.clone().unwrap(),
                               TERM_RESET))
            }
        }
    }

    /// Calls `panic` with the provided message, prepending the assertion description
    /// if present.
    fn fail_with_message(&mut self, message: String) {
        match self.description {
            Some(description) => {
                panic!(format!("\n\t{}{}:{}\n\t{}{}{}\n",
                               TERM_BOLD,
                               description,
                               TERM_RESET,
                               TERM_RED,
                               message,
                               TERM_RESET))
            }
            None => panic!(format!("\n\t{}{}{}\n", TERM_RED, message, TERM_RESET)),
        }
    }
}

impl<'s, S> Spec<'s, S>
    where S: Debug + PartialEq
{
    /// Asserts that the actual value and the expected value are equal. The value type must
    /// implement `PartialEq`.
    ///
    /// ```rust,ignore
    /// assert_that(&"hello").is_equal_to(&"hello");
    /// ```
    pub fn is_equal_to(&mut self, expected: &S) -> &mut Self {
        let subject = self.subject;

        if !subject.eq(expected) {
            self.with_expected(format!("<{:?}>", expected))
                .with_actual(format!("<{:?}>", subject))
                .fail();
        }

        self
    }
}

impl<'s, S> Spec<'s, S>
    where S: Debug
{
    /// Accepts a function accepting the value type which returns a bool. Returning false will
    /// cause the assertion to fail.
    ///
    /// NOTE: The resultant panic message will only state the actual value. It's recommended that
    /// you write your own assertion rather than relying upon this.
    ///
    /// ```rust,ignore
    /// assert_that(&"hello").matches(|x| x.eq(&"hello"));
    /// ```
    pub fn matches<F>(&mut self, matching_function: F) -> &mut Self
        where F: Fn(&'s S) -> bool
    {
        let subject = self.subject;

        if !matching_function(subject) {
            self.fail_with_message(format!("expectation failed for value <{:?}>", subject));
        }

        self
    }

    /// Transforms the subject of the `Spec` by passing it through to the provided mapping
    /// function.
    ///
    /// ```rust,ignore
    /// let test_struct = TestStruct { value: 5 };
    /// assert_that(&test_struct).map(|val| &val.value).is_equal_to(&5);
    /// ```
    pub fn map<F, T>(self, mapping_function: F) -> Spec<'s, T>
        where F: Fn(&'s S) -> &'s T
    {
        Spec {
            subject: mapping_function(self.subject),
            description: self.description,
            expected: self.expected,
            actual: self.actual,
        }
    }
}

#[cfg(test)]
mod tests {

    use super::prelude::*;

    #[test]
    fn should_be_able_to_use_macro_form_with_deliberate_reference() {
        let test_vec = vec![1, 2, 3, 4, 5];

        assert_that!(&test_vec)
            .has_length(5)
            .contains(&3)
            .contains(&5)
            .mapped_contains(|val| val * 2, &6);
    }

    #[test]
    fn should_be_able_to_use_macro_form_without_deliberate_reference() {
        let test_vec = vec![1, 2, 3, 4, 5];

        assert_that!(test_vec)
            .has_length(5)
            .contains(&3)
            .contains(&5)
            .mapped_contains(|val| val * 2, &6);
    }

    #[test]
    fn should_be_able_to_chain_assertions() {
        assert_that(&vec![1, 2, 3, 4, 5])
            .has_length(5)
            .contains(&3)
            .contains(&5)
            .mapped_contains(|val| val * 2, &6);
    }

    #[test]
    #[should_panic(expected = "\n\ttest condition:\n\texpected: <2>\n\t but was: <1>")]
    fn should_contain_assertion_description_in_panic() {
        asserting(&"test condition").that(&1).is_equal_to(&2);
    }

    #[test]
    #[should_panic(expected = "\n\tclosure:\n\texpectation failed for value <\"Hello\">")]
    fn should_contain_assertion_description_if_message_is_provided() {
        let value = "Hello";
        asserting(&"closure").that(&value).matches(|val| val.eq(&"Hi"));
    }

    #[test]
    fn should_not_panic_on_equal_subjects() {
        assert_that(&1).is_equal_to(&1);
    }

    #[test]
    #[should_panic(expected = "\n\texpected: <2>\n\t but was: <1>")]
    fn should_panic_on_unequal_subjects() {
        assert_that(&1).is_equal_to(&2);
    }

    #[test]
    fn should_not_panic_if_value_matches() {
        let value = "Hello";
        assert_that(&value).matches(|val| val.eq(&"Hello"));
    }

    #[test]
    #[should_panic(expected = "\n\texpectation failed for value <\"Hello\">")]
    fn should_panic_if_value_does_not_match() {
        let value = "Hello";
        assert_that(&value).matches(|val| val.eq(&"Hi"));
    }

    #[test]
    fn should_be_able_to_map_to_inner_field_of_struct_when_matching() {
        let test_struct = TestStruct { value: 5 };
        assert_that(&test_struct).map(|val| &val.value).is_equal_to(&5);
    }

    #[derive(Debug, PartialEq)]
    struct TestStruct {
        pub value: u8,
    }

}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://cdn.rawgit.com/urschrei/polyline-ffi/master/line.svg",
       html_root_url = "https://urschrei.github.io/polyline-ffi/")]
//! This module exposes functions for accessing the Polyline encoding and decoding functions via FFI
extern crate polyline;
use polyline::{encode_coordinates, decode_polyline};
use std::mem;
use std::slice;
use std::f64;
use std::ffi::{CStr, CString};

extern crate libc;
use self::libc::{c_char, c_void, uint32_t, size_t};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: size_t,
}

// Build an Array from &[[f64; 2]], so it can be leaked across the FFI boundary
impl From<Vec<[f64; 2]>> for Array {
    fn from(sl: Vec<[f64; 2]>) -> Self {
        let array = Array {
            data: sl.as_ptr() as *const c_void,
            len: sl.len() as size_t,
        };
        mem::forget(sl);
        array
    }
}

// Build &[[f64; 2]] from an Array, so it can be dropped
impl From<Array> for Vec<[f64; 2]> {
    fn from(arr: Array) -> Self {
        unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
    }
}

// Decode a Polyline into an Array
fn arr_from_string(incoming: String, precision: uint32_t) -> Array {
    let result: Array = match decode_polyline(incoming, precision) {
        Ok(res) => res.into(),
        // should be easy to check for
        Err(_) => vec![[f64::NAN, f64::NAN]].into(),
    };
    result.into()
}

// Decode an Array into a Polyline
fn string_from_arr(incoming: Array, precision: uint32_t) -> String {
    let inc: Vec<_> = incoming.into();
    match encode_coordinates(&inc, precision) {
        Ok(res) => res,
        // we don't need to adapt the error
        Err(res) => res,
    }
}

/// Convert a Polyline into an array of coordinates
///
/// Callers must pass two arguments:
///
/// - a pointer to `NUL`-terminated characters (`char*`)
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will return an [Array](struct.Array.html) whose `data` field is `[[NaN, NaN]]`, and whose `len` field is `1`.
///
/// Implementations calling this function **must** call [`drop_float_array`](fn.drop_float_array.html)
/// with the returned [Array](struct.Array.html), in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn decode_polyline_ffi(pl: *const c_char, precision: uint32_t) -> Array {
    let s: String = unsafe { CStr::from_ptr(pl).to_string_lossy().into_owned() };
    arr_from_string(s, precision)
}

/// Convert an array of coordinates into a Polyline
///
/// Callers must pass two arguments:
///
/// - a [Struct](struct.Array.html) with two fields:
///     - `data`, a void pointer to an array of floating-point lat, lon coordinates: `[[1.0, 2.0]]`
///     - `len`, the length of the array being passed. Its type must be `size_t`: `1`
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will return one of the following:
///
/// - a `char*` beginning with "Longitude error:" if invalid longitudes are passed
/// - a `char*` beginning with "Latitude error:" if invalid latitudes are passed
///
/// Implementations calling this function **must** call [`drop_cstring`](fn.drop_cstring.html)
/// with the returned `c_char` pointer, in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn encode_coordinates_ffi(coords: Array, precision: uint32_t) -> *mut c_char {
    let s: String = string_from_arr(coords, precision);
    match CString::new(s) {
        Ok(res) => res.into_raw(),
        // It's arguably better to fail noisily, but this is robust
        Err(_) => CString::new("Couldn't decode Polyline".to_string()).unwrap().into_raw(),
    }
}

/// Free Array memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(arr: Array) {
    if arr.data.is_null() {
        return;
    }
    let _: Vec<_> = arr.into();
}

/// Free `CString` memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_cstring(p: *mut c_char) {
    let _ = unsafe { CString::from_raw(p) };
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::ptr;
    use std::ffi::{CString, CStr};

    #[test]
    fn test_array_conversion() {
        let original = vec![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
        // move into an Array, and leak it
        let arr: Array = original.into();
        // move back into a Vec -- leaked value still needs to be dropped
        let converted: Vec<_> = arr.into();
        assert_eq!(&converted, &[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]);
        // drop it
        drop_float_array(converted.into());
    }

    #[test]
    fn test_drop_empty_float_array() {
        let original = vec![[1.0, 2.0], [3.0, 4.0]];
        // move into an Array, and leak it
        let mut arr: Array = original.into();
        // zero Array contents
        arr.data = ptr::null();
        drop_float_array(arr);
    }

    #[test]
    fn test_coordinate_conversion() {
        let input = vec![[1.0, 2.0], [3.0, 4.0]];
        let output = "_ibE_seK_seK_seK";
        let input_arr: Array = input.into();
        let transformed: String = super::string_from_arr(input_arr, 5);
        assert_eq!(transformed, output);
    }

    #[test]
    fn test_string_conversion() {
        let input = "_ibE_seK_seK_seK".to_string();
        let output = [[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        assert_eq!(&transformed_arr, &output);
    }

    #[test]
    #[should_panic]
    fn test_bad_string_conversion() {
        let input = "_p~iF~ps|U_u🗑lLnnqC_mqNvxq`@".to_string();
        let output = vec![[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        // this will fail, bc transformed_arr is [[NaN, NaN]]
        assert_eq!(transformed_arr, output.as_slice());
    }

    #[test]
    fn test_ffi_polyline_decoding() {
        let input = CString::new("_ibE_seK_seK_seK").unwrap().as_ptr();
        let result: Vec<_> = decode_polyline_ffi(input, 5).into();
        assert_eq!(&result, &[[1.0, 2.0], [3.0, 4.0]]);
        drop_float_array(result.into());
    }

    #[test]
    fn test_ffi_coordinate_encoding() {
        let input: Array = vec![[1.0, 2.0], [3.0, 4.0]].into();
        let output = "_ibE_seK_seK_seK".to_string();
        let pl = encode_coordinates_ffi(input, 5);
        // Allocate a new String
        let result = unsafe { CStr::from_ptr(pl).to_str().unwrap() };
        assert_eq!(&result, &output);
        // Drop received FFI data
        drop_cstring(pl);
    }
}
<commit_msg>Fix test to fix UAF problem<commit_after>#![doc(html_logo_url = "https://cdn.rawgit.com/urschrei/polyline-ffi/master/line.svg",
       html_root_url = "https://urschrei.github.io/polyline-ffi/")]
//! This module exposes functions for accessing the Polyline encoding and decoding functions via FFI
extern crate polyline;
use polyline::{encode_coordinates, decode_polyline};
use std::mem;
use std::slice;
use std::f64;
use std::ffi::{CStr, CString};

extern crate libc;
use self::libc::{c_char, c_void, uint32_t, size_t};

#[repr(C)]
pub struct Array {
    pub data: *const c_void,
    pub len: size_t,
}

// Build an Array from &[[f64; 2]], so it can be leaked across the FFI boundary
impl From<Vec<[f64; 2]>> for Array {
    fn from(sl: Vec<[f64; 2]>) -> Self {
        let array = Array {
            data: sl.as_ptr() as *const c_void,
            len: sl.len() as size_t,
        };
        mem::forget(sl);
        array
    }
}

// Build &[[f64; 2]] from an Array, so it can be dropped
impl From<Array> for Vec<[f64; 2]> {
    fn from(arr: Array) -> Self {
        unsafe { slice::from_raw_parts(arr.data as *mut [f64; 2], arr.len).to_vec() }
    }
}

// Decode a Polyline into an Array
fn arr_from_string(incoming: String, precision: uint32_t) -> Array {
    let result: Array = match decode_polyline(incoming, precision) {
        Ok(res) => res.into(),
        // should be easy to check for
        Err(_) => vec![[f64::NAN, f64::NAN]].into(),
    };
    result.into()
}

// Decode an Array into a Polyline
fn string_from_arr(incoming: Array, precision: uint32_t) -> String {
    let inc: Vec<_> = incoming.into();
    match encode_coordinates(&inc, precision) {
        Ok(res) => res,
        // we don't need to adapt the error
        Err(res) => res,
    }
}

/// Convert a Polyline into an array of coordinates
///
/// Callers must pass two arguments:
///
/// - a pointer to `NUL`-terminated characters (`char*`)
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will return an [Array](struct.Array.html) whose `data` field is `[[NaN, NaN]]`, and whose `len` field is `1`.
///
/// Implementations calling this function **must** call [`drop_float_array`](fn.drop_float_array.html)
/// with the returned [Array](struct.Array.html), in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn decode_polyline_ffi(pl: *const c_char, precision: uint32_t) -> Array {
    let s: String = unsafe { CStr::from_ptr(pl).to_string_lossy().into_owned() };
    arr_from_string(s, precision)
}

/// Convert an array of coordinates into a Polyline
///
/// Callers must pass two arguments:
///
/// - a [Struct](struct.Array.html) with two fields:
///     - `data`, a void pointer to an array of floating-point lat, lon coordinates: `[[1.0, 2.0]]`
///     - `len`, the length of the array being passed. Its type must be `size_t`: `1`
/// - an unsigned 32-bit `int` for precision (5 for Google Polylines, 6 for
/// OSRM and Valhalla Polylines)
///
/// A decoding failure will return one of the following:
///
/// - a `char*` beginning with "Longitude error:" if invalid longitudes are passed
/// - a `char*` beginning with "Latitude error:" if invalid latitudes are passed
///
/// Implementations calling this function **must** call [`drop_cstring`](fn.drop_cstring.html)
/// with the returned `c_char` pointer, in order to free the memory it allocates.
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn encode_coordinates_ffi(coords: Array, precision: uint32_t) -> *mut c_char {
    let s: String = string_from_arr(coords, precision);
    match CString::new(s) {
        Ok(res) => res.into_raw(),
        // It's arguably better to fail noisily, but this is robust
        Err(_) => CString::new("Couldn't decode Polyline".to_string()).unwrap().into_raw(),
    }
}

/// Free Array memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_float_array(arr: Array) {
    if arr.data.is_null() {
        return;
    }
    let _: Vec<_> = arr.into();
}

/// Free `CString` memory which Rust has allocated across the FFI boundary
///
/// # Safety
///
/// This function is unsafe because it accesses a raw pointer which could contain arbitrary data
#[no_mangle]
pub extern "C" fn drop_cstring(p: *mut c_char) {
    let _ = unsafe { CString::from_raw(p) };
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::ptr;
    use std::ffi::{CString, CStr};

    #[test]
    fn test_array_conversion() {
        let original = vec![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
        // move into an Array, and leak it
        let arr: Array = original.into();
        // move back into a Vec -- leaked value still needs to be dropped
        let converted: Vec<_> = arr.into();
        assert_eq!(&converted, &[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]);
        // drop it
        drop_float_array(converted.into());
    }

    #[test]
    fn test_drop_empty_float_array() {
        let original = vec![[1.0, 2.0], [3.0, 4.0]];
        // move into an Array, and leak it
        let mut arr: Array = original.into();
        // zero Array contents
        arr.data = ptr::null();
        drop_float_array(arr);
    }

    #[test]
    fn test_coordinate_conversion() {
        let input = vec![[1.0, 2.0], [3.0, 4.0]];
        let output = "_ibE_seK_seK_seK";
        let input_arr: Array = input.into();
        let transformed: String = super::string_from_arr(input_arr, 5);
        assert_eq!(transformed, output);
    }

    #[test]
    fn test_string_conversion() {
        let input = "_ibE_seK_seK_seK".to_string();
        let output = [[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        assert_eq!(&transformed_arr, &output);
    }

    #[test]
    #[should_panic]
    fn test_bad_string_conversion() {
        let input = "_p~iF~ps|U_u🗑lLnnqC_mqNvxq`@".to_string();
        let output = vec![[1.0, 2.0], [3.0, 4.0]];
        // String to Array
        let transformed: Array = super::arr_from_string(input, 5);
        // Array to Vec
        let transformed_arr: Vec<_> = transformed.into();
        // this will fail, bc transformed_arr is [[NaN, NaN]]
        assert_eq!(transformed_arr, output.as_slice());
    }

    #[test]
    fn test_ffi_polyline_decoding() {
        let result: Vec<_> =
            decode_polyline_ffi(CString::new("_ibE_seK_seK_seK").unwrap().as_ptr(), 5).into();
        assert_eq!(&result, &[[1.0, 2.0], [3.0, 4.0]]);
        drop_float_array(result.into());
    }

    #[test]
    fn test_ffi_coordinate_encoding() {
        let input: Array = vec![[1.0, 2.0], [3.0, 4.0]].into();
        let output = "_ibE_seK_seK_seK".to_string();
        let pl = encode_coordinates_ffi(input, 5);
        // Allocate a new String
        let result = unsafe { CStr::from_ptr(pl).to_str().unwrap() };
        assert_eq!(&result, &output);
        // Drop received FFI data
        drop_cstring(pl);
    }
}
<|endoftext|>


<commit_before>extern crate snowflake;
use self::snowflake::ProcessUniqueId;

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
    tree_id: ProcessUniqueId,
    node_id: usize
}

pub struct TreeBuilder<T> {
    root: Option<Node<T>>,
    capacity: usize
}

impl<T> TreeBuilder<T> {
    pub fn new() -> TreeBuilder<T> {
        TreeBuilder {
            root: None,
            capacity: 0
        }
    }

    pub fn with_root(&mut self, root: Node<T>) -> TreeBuilder<T> {
        TreeBuilder {
            root: Some(root),
            capacity: self.capacity
        }
    }

    pub fn with_capacity(&mut self, capacity: usize) -> TreeBuilder<T> {
        TreeBuilder {
            root: self.root.take(),
            capacity: capacity
        }
    }

    pub fn build(&mut self) -> Tree<T> {

        let tree_id = ProcessUniqueId::new();

        let mut tree = Tree {
            id: tree_id,
            root: None,
            nodes: Vec::with_capacity(self.capacity),
            free_ids: Vec::new() //todo: should this start with capacity too?
        };

        if self.root.is_some() {

            let node_id = NodeId {
                tree_id: tree_id,
                node_id: 0
            };

            tree.nodes.push(self.root.take());
            tree.root = Some(node_id);
        }

        tree
    }
}

pub struct Tree<T> {
    id: ProcessUniqueId,
    root: Option<NodeId>,
    nodes: Vec<Option<Node<T>>>,
    free_ids: Vec<NodeId>
}

pub struct Node<T> {
    data: T,
    parent: Option<NodeId>,
    children: Vec<NodeId>
}

impl<T> Node<T> {
    pub fn new(data: T) -> Node<T> {
        Node {
            data: data,
            parent: None,
            children: Vec::new()
        }
    }

    pub fn data(&self) -> &T {
        &self.data
    }

    pub fn data_mut(&mut self) -> &mut T {
        &mut self.data
    }

    pub fn parent(&self) -> Option<NodeId> {
        self.parent
    }

    pub fn children(&self) -> &Vec<NodeId> {
        &self.children
    }

    fn set_parent(&mut self, parent: NodeId) {
        self.parent = Some(parent);
    }

    fn add_child(&mut self, child: NodeId) {
        self.children.push(child);
    }

    fn children_mut(&mut self) -> &mut Vec<NodeId> {
        &mut self.children
    }
}

#[cfg(test)]
mod tree_builder_tests {
    use super::TreeBuilder;
    use super::Node;

    #[test]
    fn test_new() {
        let tb: TreeBuilder<i32> = TreeBuilder::new();
        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_root() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5));

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_capacity(10);

        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 10);
    }

    #[test]
    fn test_with_root_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5))
            .with_capacity(10);

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 10);
    }
}

#[cfg(test)]
mod node_tests {
    use super::Node;
    use super::NodeId;
    use super::snowflake::ProcessUniqueId;

    #[test]
    fn test_new() {
        let _node = Node::new(5);
    }

    #[test]
    fn test_data() {
        let five = 5;
        let node = Node::new(five);
        assert_eq!(node.data(), &five);
    }

    #[test]
    fn test_data_mut() {
        let mut five = 5;
        let mut node = Node::new(five);
        assert_eq!(node.data_mut(), &mut five);
    }

    #[test]
    fn test_parent() {
        let node = Node::new(5);
        assert!(node.parent().is_none());

        let parent_id: NodeId = NodeId {
            tree_id: ProcessUniqueId::new(),
            node_id: 0
        };
        let mut node = Node::new(5);
        node.set_parent(parent_id);

        assert_eq!(node.parent(), Some(parent_id))
    }

    #[test]
    fn test_children() {
        let node = Node::new(5);
        assert_eq!(node.children().len(), 0);

        let tree_id = ProcessUniqueId::new();

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            node_id: 2
        };
        node.add_child(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            node_id: 2
        };
        node.children_mut().push(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);
    }
}
<commit_msg>add get, get_mut, and set_root methods to tree.<commit_after>extern crate snowflake;
use self::snowflake::ProcessUniqueId;

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct NodeId {
    tree_id: ProcessUniqueId,
    index: usize
}

pub struct TreeBuilder<T> {
    root: Option<Node<T>>,
    capacity: usize
}

impl<T> TreeBuilder<T> {
    pub fn new() -> TreeBuilder<T> {
        TreeBuilder {
            root: None,
            capacity: 0
        }
    }

    pub fn with_root(&mut self, root: Node<T>) -> TreeBuilder<T> {
        TreeBuilder {
            root: Some(root),
            capacity: self.capacity
        }
    }

    pub fn with_capacity(&mut self, capacity: usize) -> TreeBuilder<T> {
        TreeBuilder {
            root: self.root.take(),
            capacity: capacity
        }
    }

    pub fn build(&mut self) -> Tree<T> {

        let tree_id = ProcessUniqueId::new();

        let mut tree = Tree {
            id: tree_id,
            root: None,
            nodes: Vec::with_capacity(self.capacity),
            free_ids: Vec::new() //todo: should this start with capacity too?
        };

        if self.root.is_some() {

            let node_id = NodeId {
                tree_id: tree_id,
                index: 0
            };

            tree.nodes.push(self.root.take());
            tree.root = Some(node_id);
        }

        tree
    }
}

pub struct Tree<T> {
    id: ProcessUniqueId,
    root: Option<NodeId>,
    nodes: Vec<Option<Node<T>>>,
    free_ids: Vec<NodeId>
}

impl<T> Tree<T> {
    pub fn set_root(&mut self, new_root: Node<T>) -> NodeId {
        let new_root_id = self.insert_new_node(new_root);

        match self.root {
            Some(current_root_node_id) => {
                self.set_as_parent_and_child(new_root_id, current_root_node_id);
            },
            None => ()
        };

        self.root = Some(new_root_id);
        new_root_id
    }

    pub fn get(&self, node_id: NodeId) -> Option<&Node<T>> {
        if self.is_valid_node_id(node_id) {
            return (*self.nodes.get(node_id.index).unwrap()).as_ref();
        }
        None
    }

    pub fn get_mut(&mut self, node_id: NodeId) -> Option<&mut Node<T>> {
        if self.is_valid_node_id(node_id) {
            return (*self.nodes.get_mut(node_id.index).unwrap()).as_mut();
        }
        None
    }

    pub fn root_node_id(&self) -> Option<NodeId> {
        self.root
    }

    fn set_as_parent_and_child(&mut self, parent_id: NodeId, child_id: NodeId) {
        self.get_mut(parent_id)
            .expect("parent_id refers to a None value.")
            .add_child(child_id);

        self.get_mut(child_id)
            .expect("child_id refers to a None value.")
            .set_parent(parent_id);
    }

    fn insert_new_node(&mut self, new_node: Node<T>) -> NodeId {

        if self.free_ids.len() > 0 {
            let new_node_id: NodeId = self.free_ids.pop()
                .expect("Couldn't pop from Vec with len() > 0 while inserting a new node.");

            self.nodes.push(Some(new_node));
            self.nodes.swap_remove(new_node_id.index);
            return new_node_id;

        } else {
            let new_node_index = self.nodes.len();
            self.nodes.push(Some(new_node));

            return self.new_node_id(new_node_index);
        }
    }

    fn new_node_id(&self, node_index: usize) -> NodeId {
        NodeId {
            tree_id: self.id,
            index: node_index
        }
    }

    fn is_valid_node_id(&self, node_id: NodeId) -> bool {
        if node_id.tree_id != self.id {
            //the node_id belongs to a different tree.
            return false;
        }

        if self.nodes.get(node_id.index).is_none() {
            //the index is out of bounds
            return false;
        }

        if self.nodes.get(node_id.index).unwrap().is_none() {
            //the node at that index was removed.
            return false;
        }

        true
    }
}

pub struct Node<T> {
    data: T,
    parent: Option<NodeId>,
    children: Vec<NodeId>
}

impl<T> Node<T> {
    pub fn new(data: T) -> Node<T> {
        Node {
            data: data,
            parent: None,
            children: Vec::new()
        }
    }

    pub fn data(&self) -> &T {
        &self.data
    }

    pub fn data_mut(&mut self) -> &mut T {
        &mut self.data
    }

    pub fn parent(&self) -> Option<NodeId> {
        self.parent
    }

    pub fn children(&self) -> &Vec<NodeId> {
        &self.children
    }

    fn set_parent(&mut self, parent: NodeId) {
        self.parent = Some(parent);
    }

    fn add_child(&mut self, child: NodeId) {
        self.children.push(child);
    }

    fn children_mut(&mut self) -> &mut Vec<NodeId> {
        &mut self.children
    }
}

#[cfg(test)]
mod tree_builder_tests {
    use super::TreeBuilder;
    use super::Node;

    #[test]
    fn test_new() {
        let tb: TreeBuilder<i32> = TreeBuilder::new();
        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_root() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5));

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 0);
    }

    #[test]
    fn test_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_capacity(10);

        assert!(tb.root.is_none());
        assert_eq!(tb.capacity, 10);
    }

    #[test]
    fn test_with_root_with_capacity() {
        let tb: TreeBuilder<i32> = TreeBuilder::new()
            .with_root(Node::new(5))
            .with_capacity(10);

        assert_eq!(tb.root.unwrap().data(), &5);
        assert_eq!(tb.capacity, 10);
    }
}

#[cfg(test)]
mod tree_tests {
    use super::Tree;
    use super::TreeBuilder;
    use super::NodeId;
    use super::Node;

    #[test]
    fn test_get() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);

        let root_node_ref = tree.get(root_id).unwrap();
        assert_eq!(root_node_ref.data(), &5);
    }

    #[test]
    fn test_get_mut() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);

        {
            let root_node_ref: &mut Node<i32> = tree.get_mut(root_id).unwrap();
            assert_eq!(root_node_ref.data(), &5);
        }

        {
            let root_node_ref: &mut Node<i32> = tree.get_mut(root_id).unwrap();
            *root_node_ref.data_mut() = 6;
        }

        let root_node_ref = tree.get_mut(root_id).unwrap();
        assert_eq!(root_node_ref.data(), &6);
    }

    #[test]
    fn test_set_root() {
        let node_a = Node::new(5);
        let node_b = Node::new(6);
        let mut tree = TreeBuilder::new().build();

        let node_a_id = tree.set_root(node_a);
        let root_id = tree.root_node_id().unwrap();
        assert_eq!(node_a_id, root_id);
        {
            let node_a_ref = tree.get(node_a_id).unwrap();
            let root_ref = tree.get(root_id).unwrap();
            assert_eq!(node_a_ref.data(), &5);
            assert_eq!(root_ref.data(), &5);
        }

        let node_b_id = tree.set_root(node_b);
        let root_id = tree.root_node_id().unwrap();
        assert_eq!(node_b_id, root_id);
        {
            let node_b_ref = tree.get(node_b_id).unwrap();
            let root_ref = tree.get(root_id).unwrap();
            assert_eq!(node_b_ref.data(), &6);
            assert_eq!(root_ref.data(), &6);

            let node_b_child_id = node_b_ref.children().get(0).unwrap();
            let node_b_child_ref = tree.get(*node_b_child_id).unwrap();
            assert_eq!(node_b_child_ref.data(), &5);
        }
    }

    #[test]
    fn test_root_node_id() {
        let root_node = Node::new(5);
        let mut tree = TreeBuilder::new().build();

        let root_id = tree.set_root(root_node);
        let root_node_id = tree.root_node_id().unwrap();

        assert_eq!(root_id, root_node_id);
    }
}

#[cfg(test)]
mod node_tests {
    use super::Node;
    use super::NodeId;
    use super::snowflake::ProcessUniqueId;

    #[test]
    fn test_new() {
        let _node = Node::new(5);
    }

    #[test]
    fn test_data() {
        let five = 5;
        let node = Node::new(five);
        assert_eq!(node.data(), &five);
    }

    #[test]
    fn test_data_mut() {
        let mut five = 5;
        let mut node = Node::new(five);
        assert_eq!(node.data_mut(), &mut five);
    }

    #[test]
    fn test_parent() {
        let node = Node::new(5);
        assert!(node.parent().is_none());

        let parent_id: NodeId = NodeId {
            tree_id: ProcessUniqueId::new(),
            index: 0
        };
        let mut node = Node::new(5);
        node.set_parent(parent_id);

        assert_eq!(node.parent(), Some(parent_id))
    }

    #[test]
    fn test_children() {
        let node = Node::new(5);
        assert_eq!(node.children().len(), 0);

        let tree_id = ProcessUniqueId::new();

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            index: 2
        };
        node.add_child(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);

        let mut node = Node::new(5);
        let child_id: NodeId = NodeId {
            tree_id: tree_id,
            index: 2
        };
        node.children_mut().push(child_id);
        let children = node.children();

        assert_eq!(children.len(), 1);
        assert_eq!(children.get(0).unwrap(), &child_id);
    }
}
<|endoftext|>


<commit_before>fn check_easter_happened(year: i32) {
    if year < 33 {
        panic!(format!("Jesus isn't dead yet in the year {}", year));
    }
}

pub mod gregorian {
    /// Easter in the Gregorian calendar
    pub fn month_day(year: i32) -> (u32, u32) {
        super::check_easter_happened(year);
        let aa = year % 19;
        let bb = year / 100;
        let cc = year % 100;
        let dd = bb / 4;
        let ee = bb % 4;
        let ff = (bb + 8) / 25;
        let gg = (bb - ff + 1) / 3;
        let hh = (19 * aa + bb - dd - gg + 15) % 30;
        let ii = cc / 4;
        let kk = cc % 4;
        let ll = (32 + 2 * ee + 2 * ii - hh - kk) % 7;
        let mm = (aa + 11 * hh + 22 * ll) / 451;
        let month = (hh + ll - 7 * mm + 114) / 31;
        let day = (hh + ll - 7 * mm + 114) % 31 + 1;
        (month as u32, day as u32)
    }
}

pub mod julian {
    /// Easter in the Julian calendar
    pub fn month_day(year: i32) -> (u32, u32) {
        super::check_easter_happened(year);
        let aa = year % 4;
        let bb = year % 7;
        let cc = year % 19;
        let dd = (19 * cc + 15) % 30;
        let ee = (2 * aa + 4 * bb - dd + 34) % 7;
        let ff = dd + ee + 114;
        let month = ff / 31;
        let day = ff % 31 + 1;
        (month as u32, day as u32)
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn gregorian_month_day() {
        use super::gregorian::month_day;
        assert_eq!(month_day(1961), (4, 2));
        assert_eq!(month_day(1996), (4, 7));
        assert_eq!(month_day(1997), (3, 30));
        assert_eq!(month_day(1998), (4, 12));
        assert_eq!(month_day(2000), (4, 23));
        assert_eq!(month_day(2001), (4, 15));
        assert_eq!(month_day(2002), (3, 31));
        assert_eq!(month_day(2003), (4, 20));
        assert_eq!(month_day(2004), (4, 11));
        assert_eq!(month_day(2005), (3, 27));
        assert_eq!(month_day(2006), (4, 16));
        assert_eq!(month_day(2007), (4, 8));
        assert_eq!(month_day(2008), (3, 23));
        assert_eq!(month_day(2009), (4, 12));
        assert_eq!(month_day(2010), (4, 4));
        assert_eq!(month_day(2011), (4, 24));
        assert_eq!(month_day(2012), (4, 8));
        assert_eq!(month_day(2013), (3, 31));
        assert_eq!(month_day(2014), (4, 20));
        assert_eq!(month_day(2015), (4, 5));
        assert_eq!(month_day(2016), (3, 27));
        assert_eq!(month_day(2017), (4, 16));
        assert_eq!(month_day(2018), (4, 1));
        assert_eq!(month_day(2019), (4, 21));
        assert_eq!(month_day(2020), (4, 12));
    }

    #[test]
    fn julian_month_day() {
        use super::julian::month_day;
        assert_eq!(month_day(1961), (3, 27));
        assert_eq!(month_day(1996), (4, 1));
        assert_eq!(month_day(1997), (4, 14));
        assert_eq!(month_day(1998), (4, 6));
        assert_eq!(month_day(1999), (3, 29));
        assert_eq!(month_day(2000), (4, 17));
        assert_eq!(month_day(2001), (4, 2));
        assert_eq!(month_day(2002), (4, 22));
        assert_eq!(month_day(2003), (4, 14));
        assert_eq!(month_day(2004), (3, 29));
        assert_eq!(month_day(2005), (4, 18));
        assert_eq!(month_day(2006), (4, 10));
        assert_eq!(month_day(2007), (3, 26));
        assert_eq!(month_day(2008), (4, 14));
        assert_eq!(month_day(2009), (4, 6));
        assert_eq!(month_day(2010), (3, 22));
        assert_eq!(month_day(2011), (4, 11));
        assert_eq!(month_day(2012), (4, 2));
        assert_eq!(month_day(2013), (4, 22));
        assert_eq!(month_day(2014), (4, 7));
        assert_eq!(month_day(2015), (3, 30));
        assert_eq!(month_day(2016), (4, 18));
        assert_eq!(month_day(2017), (4, 3));
        assert_eq!(month_day(2018), (3, 26));
        assert_eq!(month_day(2019), (4, 15));
        assert_eq!(month_day(2020), (4, 6));
    }
}
<commit_msg>result instead of panic<commit_after>const OUT_OF_RANGE_ERR: &'static str = "Computus is only valid from 1583 to 9999";

pub mod gregorian {
    /// Easter in the Gregorian calendar
    pub fn month_day(year: i32) -> Result<(u32, u32), &'static str> {
        if year < 1583 || year > 9999 {
            return Err(::OUT_OF_RANGE_ERR);
        }
        let aa = year % 19;
        let bb = year / 100;
        let cc = year % 100;
        let dd = bb / 4;
        let ee = bb % 4;
        let ff = (bb + 8) / 25;
        let gg = (bb - ff + 1) / 3;
        let hh = (19 * aa + bb - dd - gg + 15) % 30;
        let ii = cc / 4;
        let kk = cc % 4;
        let ll = (32 + 2 * ee + 2 * ii - hh - kk) % 7;
        let mm = (aa + 11 * hh + 22 * ll) / 451;
        let month = (hh + ll - 7 * mm + 114) / 31;
        let day = (hh + ll - 7 * mm + 114) % 31 + 1;
        Ok((month as u32, day as u32))
    }
}

pub mod julian {
    /// Easter in the Julian calendar
    pub fn month_day(year: i32) -> Result<(u32, u32), &'static str> {
        if year < 1583 || year > 9999 {
            return Err(::OUT_OF_RANGE_ERR);
        }
        let aa = year % 4;
        let bb = year % 7;
        let cc = year % 19;
        let dd = (19 * cc + 15) % 30;
        let ee = (2 * aa + 4 * bb - dd + 34) % 7;
        let ff = dd + ee + 114;
        let month = ff / 31;
        let day = ff % 31 + 1;
        Ok((month as u32, day as u32))
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn gregorian_month_day() {
        use super::gregorian::month_day as gregorian;
        assert_eq!(gregorian(1961), Ok((4, 2)));
        assert_eq!(gregorian(1996), Ok((4, 7)));
        assert_eq!(gregorian(1997), Ok((3, 30)));
        assert_eq!(gregorian(1998), Ok((4, 12)));
        assert_eq!(gregorian(2000), Ok((4, 23)));
        assert_eq!(gregorian(2001), Ok((4, 15)));
        assert_eq!(gregorian(2002), Ok((3, 31)));
        assert_eq!(gregorian(2003), Ok((4, 20)));
        assert_eq!(gregorian(2004), Ok((4, 11)));
        assert_eq!(gregorian(2005), Ok((3, 27)));
        assert_eq!(gregorian(2006), Ok((4, 16)));
        assert_eq!(gregorian(2007), Ok((4, 8)));
        assert_eq!(gregorian(2008), Ok((3, 23)));
        assert_eq!(gregorian(2009), Ok((4, 12)));
        assert_eq!(gregorian(2010), Ok((4, 4)));
        assert_eq!(gregorian(2011), Ok((4, 24)));
        assert_eq!(gregorian(2012), Ok((4, 8)));
        assert_eq!(gregorian(2013), Ok((3, 31)));
        assert_eq!(gregorian(2014), Ok((4, 20)));
        assert_eq!(gregorian(2015), Ok((4, 5)));
        assert_eq!(gregorian(2016), Ok((3, 27)));
        assert_eq!(gregorian(2017), Ok((4, 16)));
        assert_eq!(gregorian(2018), Ok((4, 1)));
        assert_eq!(gregorian(2019), Ok((4, 21)));
        assert_eq!(gregorian(2020), Ok((4, 12)));
        assert_eq!(gregorian(2021), Ok((4, 4)));
        assert_eq!(gregorian(2022), Ok((4, 17)));
        assert_eq!(gregorian(3035), Ok((4, 19)));
        assert_eq!(gregorian(4000), Ok((4, 9)));
        assert_eq!(gregorian(9999), Ok((3, 28)));
    }

    #[test]
    fn julian_month_day() {
        use super::julian::month_day as julian;
        assert_eq!(julian(1961), Ok((3, 27)));
        assert_eq!(julian(1996), Ok((4, 1)));
        assert_eq!(julian(1997), Ok((4, 14)));
        assert_eq!(julian(1998), Ok((4, 6)));
        assert_eq!(julian(1999), Ok((3, 29)));
        assert_eq!(julian(2000), Ok((4, 17)));
        assert_eq!(julian(2001), Ok((4, 2)));
        assert_eq!(julian(2002), Ok((4, 22)));
        assert_eq!(julian(2003), Ok((4, 14)));
        assert_eq!(julian(2004), Ok((3, 29)));
        assert_eq!(julian(2005), Ok((4, 18)));
        assert_eq!(julian(2006), Ok((4, 10)));
        assert_eq!(julian(2007), Ok((3, 26)));
        assert_eq!(julian(2008), Ok((4, 14)));
        assert_eq!(julian(2009), Ok((4, 6)));
        assert_eq!(julian(2010), Ok((3, 22)));
        assert_eq!(julian(2011), Ok((4, 11)));
        assert_eq!(julian(2012), Ok((4, 2)));
        assert_eq!(julian(2013), Ok((4, 22)));
        assert_eq!(julian(2014), Ok((4, 7)));
        assert_eq!(julian(2015), Ok((3, 30)));
        assert_eq!(julian(2016), Ok((4, 18)));
        assert_eq!(julian(2017), Ok((4, 3)));
        assert_eq!(julian(2018), Ok((3, 26)));
        assert_eq!(julian(2019), Ok((4, 15)));
        assert_eq!(julian(2020), Ok((4, 6)));
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A simple and type agnostic quaternion math library designed for reexporting

extern crate vecmath;

use vecmath::Vector3;
use std::num::{Float, FromPrimitive};

/// Quaternion type alias.
pub type Quaternion<T> = (T, [T; 3]);

/// Constructs identity quaternion.
#[inline(always)]
pub fn id<T: Float + Copy>() -> Quaternion<T> {
    let one = Float::one();
    let zero = Float::zero();
    (one, [zero, zero, zero])
}

/// Adds two quaternions.
#[inline(always)]
pub fn add<T: Float>(
    a: Quaternion<T>,
    b: Quaternion<T>
) -> Quaternion<T> {
    use vecmath::vec3_add as add;
    (a.0 + b.0, add(a.1, b.1))
}

/// Multiplies two quaternions.
#[inline(always)]
pub fn mul<T: Float + Copy>(
    a: Quaternion<T>,
    b: Quaternion<T>
) -> Quaternion<T> {
    use vecmath::vec3_cross as cross;
    use vecmath::vec3_add as add;
    use vecmath::vec3_dot as dot;
    use vecmath::vec3_scale as scale;

    (
        a.0 * b.0 - dot(a.1, b.1),
        add(
            add(scale(b.1, a.0), scale(a.1, b.0)),
            cross(a.1, b.1)
        )
    )
}

/// Takes the quaternion conjugate.
#[inline(always)]
pub fn conj<T: Float>(a: Quaternion<T>) -> Quaternion<T> {
    use vecmath::vec3_neg as neg;

    (a.0, neg(a.1))
}

/// Computes the square length of a quaternion.
#[inline(always)]
pub fn square_len<T: Float>(q: Quaternion<T>) -> T {
    use vecmath::vec3_square_len as square_len;
    q.0 * q.0 + square_len(q.1)
}

/// Computes the length of a quaternion.
#[inline(always)]
pub fn len<T: Float>(q: Quaternion<T>) -> T {
    square_len(q).sqrt()
}

/// Rotate the given vector using the given quaternion
#[inline(always)]
pub fn rotate_vector<T: Float>(q: Quaternion<T>, v: Vector3<T>) -> Vector3<T> {
    let zero = Float::zero();
    let v_as_q : Quaternion<T> = (zero, v);
    let q_conj = conj(q);
    mul(mul(q, v_as_q), q_conj).1
}

/// Construct a quaternion representing the given euler angle rotations (in radians)
#[inline(always)]
pub fn euler_angles<T: Float + FromPrimitive>(x: T, y: T, z: T) -> Quaternion<T> {
    let two: T = FromPrimitive::from_int(2).unwrap();

    let half_x = x / two;
    let half_y = y / two;
    let half_z = z / two;

    let cos_x_2 = half_x.cos();
    let cos_y_2 = half_y.cos();
    let cos_z_2 = half_z.cos();

    let sin_x_2 = half_x.sin();
    let sin_y_2 = half_y.sin();
    let sin_z_2 = half_z.sin();

    (
        cos_x_2 * cos_y_2 * cos_z_2 + sin_x_2 * sin_y_2 * sin_z_2,
        [
            sin_x_2 * cos_y_2 * cos_z_2 + cos_x_2 * sin_y_2 * sin_z_2,
            cos_x_2 * sin_y_2 * cos_z_2 + sin_x_2 * cos_y_2 * sin_z_2,
            cos_x_2 * cos_y_2 * sin_z_2 + sin_x_2 * sin_y_2 * cos_z_2
        ]
    )
}

/// Construct a quaternion for the given angle (in radians)
/// about the given axis.
/// Axis must be a unit vector.
#[inline(always)]
pub fn axis_angle<T: Float + FromPrimitive>(axis: Vector3<T>, angle: T) -> Quaternion<T> {
    use vecmath::vec3_scale as scale;
    let two: T = FromPrimitive::from_int(2).unwrap();
    let half_angle = angle / two;
    (half_angle.cos(), scale(axis, half_angle.sin()))
}

/// Tests
#[cfg(test)]
mod test {
    use super::*;
    use vecmath::Vector3;
    use std::f32::consts::PI;
    use std::num::Float;

    /// Fudge factor for float equality checks
    static EPSILON: f32 = 0.000001;

    #[test]
    fn test_axis_angle() {
        use vecmath::vec3_normalized as normalized;
        let axis: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = axis_angle(
            normalized(axis),
            PI
        );

        // Should be a unit quaternion
        assert!((square_len(q) - 1.0).abs() < EPSILON);
    }

    #[test]
    fn test_euler_angle() {
        let q: Quaternion<f32> = euler_angles(PI, PI, PI);
        // Should be a unit quaternion
        assert!((square_len(q) - 1.0).abs() < EPSILON);
    }

    #[test]
    fn test_rotate_vector_axis_angle() {
        let v: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = axis_angle([0.0, 1.0, 0.0], PI);
        let rotated = rotate_vector(q, v);
        assert!((rotated[0] - -1.0).abs() < EPSILON);
        assert!((rotated[1] - 1.0).abs() < EPSILON);
        assert!((rotated[2] - -1.0).abs() < EPSILON);
    }

    #[test]
    fn test_rotate_vector_euler_angle() {
        let v: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = euler_angles(0.0, PI, 0.0);
        let rotated = rotate_vector(q, v);
        assert!((rotated[0] - -1.0).abs() < EPSILON);
        assert!((rotated[1] - 1.0).abs() < EPSILON);
        assert!((rotated[2] - -1.0).abs() < EPSILON);
    }

    /// Rotation on axis parallel to vector direction should have no effect
    #[test]
    fn test_rotate_vector_axis_angle_same_axis() {
        use vecmath::vec3_normalized as normalized;

        let v: Vector3<f32> = [1.0, 1.0, 1.0];
        let arbitrary_angle = 32.12f32;
        let axis: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = axis_angle(
            normalized(axis),
            arbitrary_angle
        );
        let rotated = rotate_vector(q, v);

        assert!((rotated[0] - 1.0).abs() < EPSILON);
        assert!((rotated[1] - 1.0).abs() < EPSILON);
        assert!((rotated[2] - 1.0).abs() < EPSILON);
    }
}
<commit_msg>Added #![feature(core, std_misc)]<commit_after>#![deny(missing_docs)]
#![feature(core, std_misc)]

//! A simple and type agnostic quaternion math library designed for reexporting

extern crate vecmath;

use vecmath::Vector3;
use std::num::{Float, FromPrimitive};

/// Quaternion type alias.
pub type Quaternion<T> = (T, [T; 3]);

/// Constructs identity quaternion.
#[inline(always)]
pub fn id<T: Float + Copy>() -> Quaternion<T> {
    let one = Float::one();
    let zero = Float::zero();
    (one, [zero, zero, zero])
}

/// Adds two quaternions.
#[inline(always)]
pub fn add<T: Float>(
    a: Quaternion<T>,
    b: Quaternion<T>
) -> Quaternion<T> {
    use vecmath::vec3_add as add;
    (a.0 + b.0, add(a.1, b.1))
}

/// Multiplies two quaternions.
#[inline(always)]
pub fn mul<T: Float + Copy>(
    a: Quaternion<T>,
    b: Quaternion<T>
) -> Quaternion<T> {
    use vecmath::vec3_cross as cross;
    use vecmath::vec3_add as add;
    use vecmath::vec3_dot as dot;
    use vecmath::vec3_scale as scale;

    (
        a.0 * b.0 - dot(a.1, b.1),
        add(
            add(scale(b.1, a.0), scale(a.1, b.0)),
            cross(a.1, b.1)
        )
    )
}

/// Takes the quaternion conjugate.
#[inline(always)]
pub fn conj<T: Float>(a: Quaternion<T>) -> Quaternion<T> {
    use vecmath::vec3_neg as neg;

    (a.0, neg(a.1))
}

/// Computes the square length of a quaternion.
#[inline(always)]
pub fn square_len<T: Float>(q: Quaternion<T>) -> T {
    use vecmath::vec3_square_len as square_len;
    q.0 * q.0 + square_len(q.1)
}

/// Computes the length of a quaternion.
#[inline(always)]
pub fn len<T: Float>(q: Quaternion<T>) -> T {
    square_len(q).sqrt()
}

/// Rotate the given vector using the given quaternion
#[inline(always)]
pub fn rotate_vector<T: Float>(q: Quaternion<T>, v: Vector3<T>) -> Vector3<T> {
    let zero = Float::zero();
    let v_as_q : Quaternion<T> = (zero, v);
    let q_conj = conj(q);
    mul(mul(q, v_as_q), q_conj).1
}

/// Construct a quaternion representing the given euler angle rotations (in radians)
#[inline(always)]
pub fn euler_angles<T: Float + FromPrimitive>(x: T, y: T, z: T) -> Quaternion<T> {
    let two: T = FromPrimitive::from_int(2).unwrap();

    let half_x = x / two;
    let half_y = y / two;
    let half_z = z / two;

    let cos_x_2 = half_x.cos();
    let cos_y_2 = half_y.cos();
    let cos_z_2 = half_z.cos();

    let sin_x_2 = half_x.sin();
    let sin_y_2 = half_y.sin();
    let sin_z_2 = half_z.sin();

    (
        cos_x_2 * cos_y_2 * cos_z_2 + sin_x_2 * sin_y_2 * sin_z_2,
        [
            sin_x_2 * cos_y_2 * cos_z_2 + cos_x_2 * sin_y_2 * sin_z_2,
            cos_x_2 * sin_y_2 * cos_z_2 + sin_x_2 * cos_y_2 * sin_z_2,
            cos_x_2 * cos_y_2 * sin_z_2 + sin_x_2 * sin_y_2 * cos_z_2
        ]
    )
}

/// Construct a quaternion for the given angle (in radians)
/// about the given axis.
/// Axis must be a unit vector.
#[inline(always)]
pub fn axis_angle<T: Float + FromPrimitive>(axis: Vector3<T>, angle: T) -> Quaternion<T> {
    use vecmath::vec3_scale as scale;
    let two: T = FromPrimitive::from_int(2).unwrap();
    let half_angle = angle / two;
    (half_angle.cos(), scale(axis, half_angle.sin()))
}

/// Tests
#[cfg(test)]
mod test {
    use super::*;
    use vecmath::Vector3;
    use std::f32::consts::PI;
    use std::num::Float;

    /// Fudge factor for float equality checks
    static EPSILON: f32 = 0.000001;

    #[test]
    fn test_axis_angle() {
        use vecmath::vec3_normalized as normalized;
        let axis: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = axis_angle(
            normalized(axis),
            PI
        );

        // Should be a unit quaternion
        assert!((square_len(q) - 1.0).abs() < EPSILON);
    }

    #[test]
    fn test_euler_angle() {
        let q: Quaternion<f32> = euler_angles(PI, PI, PI);
        // Should be a unit quaternion
        assert!((square_len(q) - 1.0).abs() < EPSILON);
    }

    #[test]
    fn test_rotate_vector_axis_angle() {
        let v: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = axis_angle([0.0, 1.0, 0.0], PI);
        let rotated = rotate_vector(q, v);
        assert!((rotated[0] - -1.0).abs() < EPSILON);
        assert!((rotated[1] - 1.0).abs() < EPSILON);
        assert!((rotated[2] - -1.0).abs() < EPSILON);
    }

    #[test]
    fn test_rotate_vector_euler_angle() {
        let v: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = euler_angles(0.0, PI, 0.0);
        let rotated = rotate_vector(q, v);
        assert!((rotated[0] - -1.0).abs() < EPSILON);
        assert!((rotated[1] - 1.0).abs() < EPSILON);
        assert!((rotated[2] - -1.0).abs() < EPSILON);
    }

    /// Rotation on axis parallel to vector direction should have no effect
    #[test]
    fn test_rotate_vector_axis_angle_same_axis() {
        use vecmath::vec3_normalized as normalized;

        let v: Vector3<f32> = [1.0, 1.0, 1.0];
        let arbitrary_angle = 32.12f32;
        let axis: Vector3<f32> = [1.0, 1.0, 1.0];
        let q: Quaternion<f32> = axis_angle(
            normalized(axis),
            arbitrary_angle
        );
        let rotated = rotate_vector(q, v);

        assert!((rotated[0] - 1.0).abs() < EPSILON);
        assert!((rotated[1] - 1.0).abs() < EPSILON);
        assert!((rotated[2] - 1.0).abs() < EPSILON);
    }
}
<|endoftext|>


<commit_before>extern crate num;

use std::cmp::Eq;
use std::ops::{BitAnd,Index,Not,Shl};
use num::{One,Zero,Unsigned,NumCast};

pub trait BitStorage: Sized + BitAnd<Self, Output = Self> + Shl<Self, Output = Self> + Not + Eq + Zero + One + Unsigned + NumCast + Copy {}

impl<S> BitStorage for S where S: Sized + BitAnd<S, Output = S> + Shl<S, Output = S> + Not + Eq + Zero + One + Unsigned + NumCast + Copy {}

pub struct BitVector<S: BitStorage = usize> {
    data: Vec<S>,
    capacity: usize
}

impl<S: BitStorage> BitVector<S> {
    pub fn with_capacity(capacity: usize) -> BitVector<S> {
        let len = (capacity / (std::mem::size_of::<S>() * 8)) + 1;
        BitVector { data: vec![S::zero(); len], capacity: capacity }
    }
}

static TRUE: bool = true;
static FALSE: bool = false;

macro_rules! bool_ref {
    ($cond:expr) => (if $cond { &TRUE } else { &FALSE })
}

impl<S: BitStorage> Index<usize> for BitVector<S> {
    type Output = bool;

    fn index(&self, index: usize) -> &bool {
        let data_index = index / (std::mem::size_of::<S>() * 8);
        let remainder = index % (std::mem::size_of::<S>() * 8);
        // we know that remainder is always smaller or equal to the size that S can hold
        // for example if S = u8 then remainder <= 2^8 - 1
        let remainder: S = num::cast(remainder).unwrap();
        bool_ref!((self.data[data_index] & (S::one() << remainder)) != S::zero())
    }
}

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

    #[test]
    fn test_with_capacity() {
        //TODO rewrite range checks to use iter

        let vec_32_1024 = BitVector::<u32>::with_capacity(1024);
        for i in 0..1024 {
            assert_eq!(vec_32_1024[i], false);
        }

        let vec_32_1000 = BitVector::<u32>::with_capacity(1000);
        for i in 0..1000 {
            assert_eq!(vec_32_1000[i], false);
        }
    }

    //TODO in index() check out of bounds
}
<commit_msg>Removed unused Not trait<commit_after>extern crate num;

use std::cmp::Eq;
use std::ops::{BitAnd,Index,Shl};
use num::{One,Zero,Unsigned,NumCast};

pub trait BitStorage: Sized + BitAnd<Self, Output = Self> + Shl<Self, Output = Self> + Eq + Zero + One + Unsigned + NumCast + Copy {}

impl<S> BitStorage for S where S: Sized + BitAnd<S, Output = S> + Shl<S, Output = S> + Eq + Zero + One + Unsigned + NumCast + Copy {}

pub struct BitVector<S: BitStorage = usize> {
    data: Vec<S>,
    capacity: usize
}

impl<S: BitStorage> BitVector<S> {
    pub fn with_capacity(capacity: usize) -> BitVector<S> {
        let len = (capacity / (std::mem::size_of::<S>() * 8)) + 1;
        BitVector { data: vec![S::zero(); len], capacity: capacity }
    }
}

static TRUE: bool = true;
static FALSE: bool = false;

macro_rules! bool_ref {
    ($cond:expr) => (if $cond { &TRUE } else { &FALSE })
}

impl<S: BitStorage> Index<usize> for BitVector<S> {
    type Output = bool;

    fn index(&self, index: usize) -> &bool {
        let data_index = index / (std::mem::size_of::<S>() * 8);
        let remainder = index % (std::mem::size_of::<S>() * 8);
        // we know that remainder is always smaller or equal to the size that S can hold
        // for example if S = u8 then remainder <= 2^8 - 1
        let remainder: S = num::cast(remainder).unwrap();
        bool_ref!((self.data[data_index] & (S::one() << remainder)) != S::zero())
    }
}

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

    #[test]
    fn test_with_capacity() {
        //TODO rewrite range checks to use iter

        let vec_32_1024 = BitVector::<u32>::with_capacity(1024);
        for i in 0..1024 {
            assert_eq!(vec_32_1024[i], false);
        }

        let vec_32_1000 = BitVector::<u32>::with_capacity(1000);
        for i in 0..1000 {
            assert_eq!(vec_32_1000[i], false);
        }
    }

    //TODO in index() check out of bounds
}
<|endoftext|>


<commit_before>
extern crate gl;
extern crate glutin;
extern crate png;
extern crate cable_math;
extern crate rusttype;

pub mod color;
pub mod texture;
#[macro_use]
pub mod shader;
pub mod buffer;
pub mod matrix_stack;
pub mod util;
pub mod framebuffer;
pub mod font;

/// Creates a new window
pub fn create_window() -> glutin::Window {
    let window = glutin::Window::new().unwrap();
    unsafe {
        window.make_current().unwrap();
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    }
    window
}

<commit_msg>Initial work on proper game running code<commit_after>
extern crate gl;
extern crate glutin;
extern crate png;
extern crate cable_math;
extern crate rusttype;

pub mod color;
pub mod texture;
#[macro_use]
pub mod shader;
pub mod buffer;
pub mod matrix_stack;
pub mod util;
pub mod framebuffer;
pub mod font;

pub use color::*;
pub use util::graphics;

use cable_math::Vec2;
use glutin::*;
use std::io;
use std::time::{Instant, Duration};

pub fn run<T: Game + Sized>() {
    // Create window
    let window = glutin::Window::new().unwrap();
    unsafe {
        window.make_current().unwrap();
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    }

    // Set up game state
    let mut state = GameState::new();
    state.window_size = {
        let window_size = window.get_inner_size_pixels().unwrap();
        Vec2::new(window_size.0, window_size.1)
    };
    graphics::viewport(0, 0, state.window_size.x, state.window_size.y);

    // Set up game
    let mut game = match T::setup(&mut state) {
        Err(err) => {
            println!("Failed to launch game:\n{}", err);
            panic!();
        },
        Ok(game) => game,
    };

    let mut delta: u64 = 16;
    let target_delta = Duration::from_millis(14);

    'main_loop:
    loop {
        let start_time = Instant::now();

        // Events
        state.input.update();
        for event in window.poll_events() {
            match event {
                Event::Closed => break 'main_loop,
                Event::Resized(width, height) => {
                    if width != 0 && height != 0 {
                        state.window_size = Vec2::new(width, height);
                        graphics::viewport(0, 0, state.window_size.x, state.window_size.y);
                        game.on_resize(&state);
                    }
                }
                other => state.input.handle_event(other),
            }
        }

        // Logic and rendering
        game.update(delta as u32, &mut state);
        game.draw(&state);
        window.swap_buffers().unwrap();
        graphics::print_errors();

        if state.exit {
            break 'main_loop;
        }

        // Timing
        let elapsed = start_time.elapsed();
        if elapsed < target_delta {
            std::thread::sleep(target_delta - elapsed); // This is not very precice :/
        }
        let delta_dur = start_time.elapsed();
        delta = delta_dur.as_secs()*1000 + (delta_dur.subsec_nanos() as u64)/1000000;
    }

    game.close();
}

pub struct GameState {
    window_size: Vec2<u32>,
    input: InputManager,
    exit: bool,
}

pub struct InputManager {
    mouse_pos: Vec2<f32>,
    mouse_delta: Vec2<f32>,
}

pub trait Game: Sized {
    fn setup(state: &mut GameState) -> io::Result<Self>;
    fn update(&mut self, delta: u32, state: &mut GameState);
    fn draw(&mut self, state: &GameState);

    fn on_resize(&mut self, state: &GameState) {}
    fn close(&mut self) {} // Most simple games dont need any special logic here
}

impl GameState {
    pub fn new() -> GameState {
        GameState {
            window_size: Vec2::zero(),
            input: InputManager::new(),
            exit: false
        }
    }

    /// Causes the game to exit. The game is exited after calls to `update` and
    /// `draw` have returned.
    pub fn exit(&mut self) { self.exit = true; }

    pub fn input(&self) -> &InputManager { &self.input }
    pub fn window_size(&self) -> Vec2<u32> { self.window_size }
}

impl InputManager {
    fn new() -> InputManager {
        InputManager {
            mouse_pos: Vec2::zero(),
            mouse_delta: Vec2::zero(),
        }
    }

    fn update(&mut self) {
        self.mouse_delta = Vec2::zero();
    }

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::MouseMoved(x, y) => {
                let old_mouse_pos = self.mouse_pos;
                self.mouse_pos = Vec2::new(x as f32, y as f32);
                self.mouse_delta = self.mouse_pos - old_mouse_pos;
            },
            _ => {},
        }
    }

    // Getters
    pub fn mouse_pos(&self)   -> Vec2<f32> { self.mouse_pos }
    pub fn mouse_delta(&self) -> Vec2<f32> { self.mouse_delta }
}

<|endoftext|>