must 0.2.0

assertion library for rust
Documentation
// Based on https://github.com/carllerche/hamcrest-rust/blob/master/src/matchers/close_to.rs

use errors::ErrorKind;
use lazy::SimpleAssert;
use num_traits::{Float, Zero};
use std::fmt::Debug;


pub trait FloatMust: Debug + Float {
	fn must_be_nan(self) -> SimpleAssert<Self> {
		if self.is_nan() {
			self.into()
		} else {
			ErrorKind::MustBeNan.but_got(self)
		}
	}

	fn must_not_be_nan(self) -> SimpleAssert<Self> {
		if !self.is_nan() {
			self.into()
		} else {
			ErrorKind::MustNotBeNan.but_got(self)
		}
	}

	/// TODO(kdy): rewrite this with lazy must_be_close_to().within()
	fn must_be_close_to(self, expected: Self, epsilon: Self) -> SimpleAssert<Self> {
		if is_close_to(self, expected, epsilon) {
			self.into()
		} else {
			ErrorKind::Msg(format!("must be close to {:?} (with in epsilon={:?})",
			                       expected,
			                       epsilon))
				.but_got(self)
		}
	}

	fn must_not_be_close_to(self, expected: Self, epsilon: Self) -> SimpleAssert<Self> {
		if !is_close_to(self, expected, epsilon) {
			self.into()
		} else {
			ErrorKind::Msg(format!("must not be close to {:?} (with in epsilon={:?})",
			                       expected,
			                       epsilon))
				.but_got(self)
		}
	}
}

impl<V> FloatMust for V where V: Debug + Float {}

fn is_close_to<T: Float>(got: T, expected: T, epsilon: T) -> bool {
	let a = expected.abs();
	let b = got.abs();

	let d = (a - b).abs();

	let close =
            // shortcut, handles infinities
            a == b
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            || ((a == Zero::zero() || b == Zero::zero() || d < Float::min_positive_value()) &&
                d < (epsilon * Float::min_positive_value()))
            // use relative error
            || d / (a + b).min(Float::max_value()) < epsilon;

	close
}


fn _assert() {
	fn implemented_for<T: FloatMust>() {}

	implemented_for::<f32>();
	implemented_for::<f64>();
}