<commit_before>use std::cmp::Ordering;
use std::fmt;

use crate::conversion::ToPyObject;
use crate::err::{self, PyErr, PyResult};
use crate::ffi;
use crate::objects::{PyObject, PyInt, PyLong, PyFloat};
use crate::python::{Python, PythonObject, ToPythonPointer};

use super::ObjectProtocol;

/// Operations on numeric objects
pub trait NumberProtocol: ObjectProtocol {
    /// Perform addition (self + other)
    ///
    /// Invokes the `__add__` magic-method
    #[inline]
    fn add(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Add(self.as_ptr(), other))
        })
    }
    /// Perform subtraction (self - other)
    ///
    /// Invokes the `__sub__` magic-method
    #[inline]
    fn subtract(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Subtract(self.as_ptr(), other))
        })
    }
    /// Perform multiplication (self * other)
    ///
    /// Invokes the `__mul__` magic-method
    #[inline]
    fn multiply(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Multiply(self.as_ptr(), other))
        })
    }
    /// Perform matrix multiplication, equivalent to the Python expression `self @ other`
    ///
    /// Invokes the `__matmul__` magic-method
    ///
    /// This was added in Python 3.5, and will unconditionally
    /// throw an exception on any version before that.
    ///
    /// See [PEP 0456](https://www.python.org/dev/peps/pep-0465/) for details.
    #[inline]
    fn matrix_multiply(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        #[cfg(not(any(feature = "python3-4", feature = "python2-sys")))] {
            other.with_borrowed_ptr(py, |other| unsafe {
                err::result_from_owned_ptr(py, ffi::PyNumber_MatrixMultiply(self.as_ptr(), other))
            })
        }
        #[cfg(any(feature = "python3-4", feature = "python2-sys"))] {

            drop(other);
            Err(crate::PyErr::new::<crate::exc::TypeError, _>(
                py,
                "Matrix multiplication is unsupported before Python 3.5"
            ))
        }
    }
    /// Perform exponentiation, equivalent to the Python expression `self ** other`,
    /// or the two-argument form of the builtin method pow: `pow(self, other)`
    ///
    /// Invokes the `__pow__` magic-method
    ///
    /// See also [NumberProtocol::pow_mod].
    #[inline]
    fn pow(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        self.pow_mod(py, other, py.None())
    }
    /// Perform exponentiation modulo an integer,
    /// mathematically equivalent to `self ** other % mod`
    /// but computed much more efficiently.
    ///
    /// Equivalent to invoking the three-argument form
    /// of the builtin `pow` method: `pow(self, other, z)`
    ///
    /// Invoking with a `None` for modulo is equivalent to
    /// the regular power operation.
    ///
    /// Invokes the `__pow__` magic-method
    #[inline]
    fn pow_mod(&self, py: Python, exp: impl ToPyObject, z: impl ToPyObject) -> PyResult<PyObject> {
        exp.with_borrowed_ptr(py, |exp| {
            z.with_borrowed_ptr(py, |z| unsafe {
                err::result_from_owned_ptr(py, ffi::PyNumber_Power(self.as_ptr(), exp, z))
            })
        })
    }
    /// Perform the "true division" operation,
    /// equivalent to the Python expression `self / other`,
    ///
    /// Invokes the `__truediv__` magic-method.
    #[inline]
    fn true_div(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_TrueDivide(self.as_ptr(), other))
        })
    }
    /// Perform the "floor division" operation,
    /// equivalent to the Python expression `self // other`,
    ///
    /// This method was added in Python 3.
    /// If compiling against Python 2, it unconditional throws an error.
    ///
    /// Invokes the `__floordiv__` magic-method.
    #[inline]
    fn div_floor(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_TrueDivide(self.as_ptr(), other))
        })
    }
    /// Return the remainder of dividing `self` by `other`,
    /// equivalent to the Python expression `self % other`
    ///
    /// Invokes the `__mod__` magic-method.
    #[inline]
    fn remainder(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Remainder(self.as_ptr(), other))
        })
    }
    /// Perform combined division and modulo,
    /// equivalent to the builtin method `divmod(self, other)`
    ///
    /// Invokes the `__divmod__` magic-method.
    #[inline]
    fn div_mod(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Divmod(self.as_ptr(), other))
        })
    }
    /// Perform the negation of self (-self)
    ///
    /// Invokes the `__neg__` magic-method.
    #[inline]
    fn negative(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Negative(self.as_ptr()))
        }
    }
    /// Invoke the 'positive' operation, equivalent to the
    /// Python expression `+self`
    ///
    /// Invokes the `__pos__` magic-method
    #[inline]
    fn positive(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Positive(self.as_ptr()))
        }
    }
    /// Return the absolute value of self,
    /// equivalent to calling the builtin function `abs`
    ///
    /// Invokes the `__abs__` magic-method.
    #[inline]
    fn absolute(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Absolute(self.as_ptr()))
        }
    }
    /// Perform the bitwise negation of self,
    /// equivalent to the Python expression `~self`
    ///
    /// Invokes the `__invert__` magic-method
    #[inline]
    fn bitwise_invert(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Invert(self.as_ptr()))
        }
    }
    /// Shift this value to the left by the specified number of bits,
    /// equivalent to the Python expression `self << bits`
    ///
    /// Invokes the `__lshift__` magic-method
    #[inline]
    fn left_shift(&self, py: Python, bits: impl ToPyObject) -> PyResult<PyObject> {
        bits.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Lshift(self.as_ptr(), other))
        })
    }
    /// Shift this value to the right by the specified number of bits,
    /// equivalent to the Python expression `self >> bits`
    ///
    /// Invokes the `__rshift__` magic-method
    #[inline]
    fn right_shift(&self, py: Python, bits: impl ToPyObject) -> PyResult<PyObject> {
        bits.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Rshift(self.as_ptr(), other))
        })
    }
    /// Perform the "bitwise and" of `self & other`
    ///
    /// Invokes the `__and__` magic-method.
    #[inline]
    fn bitwise_and(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_And(self.as_ptr(), other))
        })
    }
    /// Perform the "bitwise exclusive or",
    /// equivalent to Python expression `self ^ other`
    ///
    /// Invokes the `__xor__` magic-method.
    #[inline]
    fn bitwise_xor(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Xor(self.as_ptr(), other))
        })
    }
    /// Perform the "bitwise or" of `self | other`
    ///
    /// Invokes the `__or__` magic-method.
    #[inline]
    fn bitwise_or(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Or(self.as_ptr(), other))
        })
    }
    /// Convert this object to an integer,
    /// equivalent to the builtin function `int(self)`
    ///
    /// Invokes the `__int__` magic-method.
    ///
    /// Throws an exception if unable to perform
    /// the conversion.
    #[inline]
    fn as_int(&self, py: Python) -> PyResult<PyLong> {
        let obj = unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Long(self.as_ptr()))?
        };
        Ok(obj.cast_into::<PyLong>(py)?)
    }
    /// Convert this object to a float,
    /// equivalent to the builtin function `float(self)`
    ///
    /// Invokes the `__float__` magic-method.
    ///
    /// Throws an exception if unable to perform
    /// the conversion.
    #[inline]
    fn as_float(&self, py: Python) -> PyResult<PyFloat> {
        let obj = unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Float(self.as_ptr()))?
        };
        Ok(obj.cast_into::<PyFloat>(py)?)
    }
    /// Losslessly convert this object to an integer index,
    /// as if calling `operator.index()`
    ///
    /// The presence of this method indicates
    /// this object is an integer type.
    ///
    /// Calls the `__index__` magic-method.
    ///
    /// See also: [Documentation on the corresponding magic-method](https://docs.python.org/3/reference/datamodel.html?highlight=__index__#object.__index__)
    #[inline]
    fn as_int_index(&self, py: Python) -> PyResult<PyLong> {
        let obj = unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Long(self.as_ptr()))?
        };
        Ok(obj.cast_into::<PyLong>(py)?)
    }
}

impl NumberProtocol for PyObject {}

#[cfg(test)]
mod test {
    use crate::*;
    use super::*;

    #[test]
    fn addition() {
        let guard = Python::acquire_gil();
        let py = guard.python();
        let i1 = (5i32).to_py_object(py).into_object();
        let i2 = (12i32).to_py_object(py).into_object();
        let actual_res = i1.add(py, i2).unwrap();
        let expected_res = (17i32).to_py_object(py).into_object();
        assert_eq!(
            actual_res.compare(py, expected_res).unwrap(),
            Ordering::Equal
        );
    }

    py_class!(class DummyMatMul |py| {
        data number: i32;
        def __new__(_cls, arg: i32) -> PyResult<DummyMatMul> {
            DummyMatMul::create_instance(py, arg)
        }
        def __matmul__(left, other) -> PyResult<PyObject> {
            // Do a dummy operation that can be easily tested
            left.cast_as::<Self>(py)?.number(py)
                .to_py_object(py)
                .into_object()
                .multiply(py, other)?
                .add(py, 3)
        }
    });

    #[test]
    #[cfg_attr(any(feature = "python3-4", feature = "python2-sys"), should_panic)]
    fn matrix_multiply() {
        let guard = Python::acquire_gil();
        let py = guard.python();
        let first = DummyMatMul::create_instance(py, 5).unwrap().into_object();
        let seven = (7i32).to_py_object(py).into_object();
        let actual_res = first.matrix_multiply(py, seven).unwrap();
        // 5 * 7 + 3 => 38
        let expected_res = (38i32).to_py_object(py).into_object();
        assert_eq!(
            actual_res.compare(py, expected_res).unwrap(),
            Ordering::Equal
        );
    }
}
<commit_msg>Fix two wrong method calls in the number protocol<commit_after>use std::cmp::Ordering;
use std::fmt;

use crate::conversion::ToPyObject;
use crate::err::{self, PyErr, PyResult};
use crate::ffi;
use crate::objects::{PyObject, PyInt, PyLong, PyFloat};
use crate::python::{Python, PythonObject, ToPythonPointer};

use super::ObjectProtocol;

/// Operations on numeric objects
pub trait NumberProtocol: ObjectProtocol {
    /// Perform addition (self + other)
    ///
    /// Invokes the `__add__` magic-method
    #[inline]
    fn add(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Add(self.as_ptr(), other))
        })
    }
    /// Perform subtraction (self - other)
    ///
    /// Invokes the `__sub__` magic-method
    #[inline]
    fn subtract(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Subtract(self.as_ptr(), other))
        })
    }
    /// Perform multiplication (self * other)
    ///
    /// Invokes the `__mul__` magic-method
    #[inline]
    fn multiply(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Multiply(self.as_ptr(), other))
        })
    }
    /// Perform matrix multiplication, equivalent to the Python expression `self @ other`
    ///
    /// Invokes the `__matmul__` magic-method
    ///
    /// This was added in Python 3.5, and will unconditionally
    /// throw an exception on any version before that.
    ///
    /// See [PEP 0456](https://www.python.org/dev/peps/pep-0465/) for details.
    #[inline]
    fn matrix_multiply(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        #[cfg(not(any(feature = "python3-4", feature = "python2-sys")))] {
            other.with_borrowed_ptr(py, |other| unsafe {
                err::result_from_owned_ptr(py, ffi::PyNumber_MatrixMultiply(self.as_ptr(), other))
            })
        }
        #[cfg(any(feature = "python3-4", feature = "python2-sys"))] {

            drop(other);
            Err(crate::PyErr::new::<crate::exc::TypeError, _>(
                py,
                "Matrix multiplication is unsupported before Python 3.5"
            ))
        }
    }
    /// Perform exponentiation, equivalent to the Python expression `self ** other`,
    /// or the two-argument form of the builtin method pow: `pow(self, other)`
    ///
    /// Invokes the `__pow__` magic-method
    ///
    /// See also [NumberProtocol::pow_mod].
    #[inline]
    fn pow(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        self.pow_mod(py, other, py.None())
    }
    /// Perform exponentiation modulo an integer,
    /// mathematically equivalent to `self ** other % mod`
    /// but computed much more efficiently.
    ///
    /// Equivalent to invoking the three-argument form
    /// of the builtin `pow` method: `pow(self, other, z)`
    ///
    /// Invoking with a `None` for modulo is equivalent to
    /// the regular power operation.
    ///
    /// Invokes the `__pow__` magic-method
    #[inline]
    fn pow_mod(&self, py: Python, exp: impl ToPyObject, z: impl ToPyObject) -> PyResult<PyObject> {
        exp.with_borrowed_ptr(py, |exp| {
            z.with_borrowed_ptr(py, |z| unsafe {
                err::result_from_owned_ptr(py, ffi::PyNumber_Power(self.as_ptr(), exp, z))
            })
        })
    }
    /// Perform the "true division" operation,
    /// equivalent to the Python expression `self / other`,
    ///
    /// Invokes the `__truediv__` magic-method.
    #[inline]
    fn true_div(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_TrueDivide(self.as_ptr(), other))
        })
    }
    /// Perform the "floor division" operation,
    /// equivalent to the Python expression `self // other`,
    ///
    /// This method was added in Python 3.
    /// If compiling against Python 2, it unconditional throws an error.
    ///
    /// Invokes the `__floordiv__` magic-method.
    #[inline]
    fn div_floor(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_FloorDivide(self.as_ptr(), other))
        })
    }
    /// Return the remainder of dividing `self` by `other`,
    /// equivalent to the Python expression `self % other`
    ///
    /// Invokes the `__mod__` magic-method.
    #[inline]
    fn remainder(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Remainder(self.as_ptr(), other))
        })
    }
    /// Perform combined division and modulo,
    /// equivalent to the builtin method `divmod(self, other)`
    ///
    /// Invokes the `__divmod__` magic-method.
    #[inline]
    fn div_mod(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Divmod(self.as_ptr(), other))
        })
    }
    /// Perform the negation of self (-self)
    ///
    /// Invokes the `__neg__` magic-method.
    #[inline]
    fn negative(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Negative(self.as_ptr()))
        }
    }
    /// Invoke the 'positive' operation, equivalent to the
    /// Python expression `+self`
    ///
    /// Invokes the `__pos__` magic-method
    #[inline]
    fn positive(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Positive(self.as_ptr()))
        }
    }
    /// Return the absolute value of self,
    /// equivalent to calling the builtin function `abs`
    ///
    /// Invokes the `__abs__` magic-method.
    #[inline]
    fn absolute(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Absolute(self.as_ptr()))
        }
    }
    /// Perform the bitwise negation of self,
    /// equivalent to the Python expression `~self`
    ///
    /// Invokes the `__invert__` magic-method
    #[inline]
    fn bitwise_invert(&self, py: Python) -> PyResult<PyObject> {
        unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Invert(self.as_ptr()))
        }
    }
    /// Shift this value to the left by the specified number of bits,
    /// equivalent to the Python expression `self << bits`
    ///
    /// Invokes the `__lshift__` magic-method
    #[inline]
    fn left_shift(&self, py: Python, bits: impl ToPyObject) -> PyResult<PyObject> {
        bits.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Lshift(self.as_ptr(), other))
        })
    }
    /// Shift this value to the right by the specified number of bits,
    /// equivalent to the Python expression `self >> bits`
    ///
    /// Invokes the `__rshift__` magic-method
    #[inline]
    fn right_shift(&self, py: Python, bits: impl ToPyObject) -> PyResult<PyObject> {
        bits.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Rshift(self.as_ptr(), other))
        })
    }
    /// Perform the "bitwise and" of `self & other`
    ///
    /// Invokes the `__and__` magic-method.
    #[inline]
    fn bitwise_and(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_And(self.as_ptr(), other))
        })
    }
    /// Perform the "bitwise exclusive or",
    /// equivalent to Python expression `self ^ other`
    ///
    /// Invokes the `__xor__` magic-method.
    #[inline]
    fn bitwise_xor(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Xor(self.as_ptr(), other))
        })
    }
    /// Perform the "bitwise or" of `self | other`
    ///
    /// Invokes the `__or__` magic-method.
    #[inline]
    fn bitwise_or(&self, py: Python, other: impl ToPyObject) -> PyResult<PyObject> {
        other.with_borrowed_ptr(py, |other| unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Or(self.as_ptr(), other))
        })
    }
    /// Convert this object to an integer,
    /// equivalent to the builtin function `int(self)`
    ///
    /// Invokes the `__int__` magic-method.
    ///
    /// Throws an exception if unable to perform
    /// the conversion.
    #[inline]
    fn as_int(&self, py: Python) -> PyResult<PyLong> {
        let obj = unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Long(self.as_ptr()))?
        };
        Ok(obj.cast_into::<PyLong>(py)?)
    }
    /// Convert this object to a float,
    /// equivalent to the builtin function `float(self)`
    ///
    /// Invokes the `__float__` magic-method.
    ///
    /// Throws an exception if unable to perform
    /// the conversion.
    #[inline]
    fn as_float(&self, py: Python) -> PyResult<PyFloat> {
        let obj = unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Float(self.as_ptr()))?
        };
        Ok(obj.cast_into::<PyFloat>(py)?)
    }
    /// Losslessly convert this object to an integer index,
    /// as if calling `operator.index()`
    ///
    /// The presence of this method indicates
    /// this object is an integer type.
    ///
    /// Calls the `__index__` magic-method.
    ///
    /// See also: [Documentation on the corresponding magic-method](https://docs.python.org/3/reference/datamodel.html?highlight=__index__#object.__index__)
    #[inline]
    fn as_int_index(&self, py: Python) -> PyResult<PyLong> {
        let obj = unsafe {
            err::result_from_owned_ptr(py, ffi::PyNumber_Index(self.as_ptr()))?
        };
        Ok(obj.cast_into::<PyLong>(py)?)
    }
}

impl NumberProtocol for PyObject {}

#[cfg(test)]
mod test {
    use crate::*;
    use super::*;

    #[test]
    fn addition() {
        let guard = Python::acquire_gil();
        let py = guard.python();
        let i1 = (5i32).to_py_object(py).into_object();
        let i2 = (12i32).to_py_object(py).into_object();
        let actual_res = i1.add(py, i2).unwrap();
        let expected_res = (17i32).to_py_object(py).into_object();
        assert_eq!(
            actual_res.compare(py, expected_res).unwrap(),
            Ordering::Equal
        );
    }

    py_class!(class DummyMatMul |py| {
        data number: i32;
        def __new__(_cls, arg: i32) -> PyResult<DummyMatMul> {
            DummyMatMul::create_instance(py, arg)
        }
        def __matmul__(left, other) -> PyResult<PyObject> {
            // Do a dummy operation that can be easily tested
            left.cast_as::<Self>(py)?.number(py)
                .to_py_object(py)
                .into_object()
                .multiply(py, other)?
                .add(py, 3)
        }
    });

    #[test]
    #[cfg_attr(any(feature = "python3-4", feature = "python2-sys"), should_panic)]
    fn matrix_multiply() {
        let guard = Python::acquire_gil();
        let py = guard.python();
        let first = DummyMatMul::create_instance(py, 5).unwrap().into_object();
        let seven = (7i32).to_py_object(py).into_object();
        let actual_res = first.matrix_multiply(py, seven).unwrap();
        // 5 * 7 + 3 => 38
        let expected_res = (38i32).to_py_object(py).into_object();
        assert_eq!(
            actual_res.compare(py, expected_res).unwrap(),
            Ordering::Equal
        );
    }
}
<|endoftext|>


<commit_before>// vim: tw=80
#![cfg_attr(feature = "nightly", feature(specialization))]

use cfg_if::cfg_if;
use downcast::*;
use std::{
    any,
    collections::hash_map::{DefaultHasher, HashMap},
    hash::{Hash, Hasher},
    mem,
    ops::DerefMut,
    sync::Mutex
};

trait ExpectationT : Any + Send {}
downcast!(ExpectationT);

/// Return functions for expectations
enum Rfunc<I, O> {
    Default,
    // Indicates that a `return_once` expectation has already returned
    Expired,
    Mut(Box<dyn FnMut(I) -> O + Send>),
    // Should be Box<dyn FnOnce> once that feature is stabilized
    // https://github.com/rust-lang/rust/issues/28796
    Once(Box<dyn FnMut(I) -> O + Send>),
}

// TODO: change this to "impl FnMut" once unboxed_closures are stable
// https://github.com/rust-lang/rust/issues/29625
impl<I, O>  Rfunc<I, O> {
    fn call_mut(&mut self, args: I) -> O {
        match self {
            Rfunc::Default => {
                Self::return_default()
            },
            Rfunc::Expired => {
                panic!("Called a method twice that was expected only once")
            },
            Rfunc::Mut(f) => {
                f(args)
            },
            Rfunc::Once(_) => {
                let fo = mem::replace(self, Rfunc::Expired);
                if let Rfunc::Once(mut f) = fo {
                    f(args)
                } else {
                    unreachable!()
                }
            },
        }
    }
}

trait ReturnDefault<O> {
    fn return_default() -> O;
}

cfg_if! {
    if #[cfg(feature = "nightly")] {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            default fn return_default() -> O {
                panic!("Can only return default values for types that impl std::Default");
            }
        }
    } else {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            fn return_default() -> O {
                panic!("Returning default values requires the \"nightly\" feature");
            }
        }
    }
}

#[cfg(feature = "nightly")]
impl<I, O: Default> ReturnDefault<O> for Rfunc<I, O> {
    fn return_default() -> O {
        O::default()
    }
}

struct Expectation<I, O> {
    rfunc: Rfunc<I, O>
}

impl<I, O> Expectation<I, O> {
    fn call_mut(&mut self, i: I) -> O {
        self.rfunc.call_mut(i)
    }

    fn new(rfunc: Rfunc<I, O>) -> Self {
        Expectation{rfunc}
    }
}

impl<I: 'static, O: 'static> ExpectationT for Expectation<I, O> {}

pub struct ExpectationBuilder<'object, I, O>
    where I: 'static, O: 'static
{
    e: &'object mut Expectations,
    rfunc: Rfunc<I, O>,
    ident: String
}

impl<'object, I, O> ExpectationBuilder<'object, I, O>
    where I: 'static, O: 'static
{
    fn new(e: &'object mut Expectations, ident: &str) -> Self {
        // Own the ident so we don't have to worry about lifetime issues
        let ident = ident.to_owned();
        ExpectationBuilder{rfunc: Rfunc::Default, e, ident}
    }

    pub fn returning<F>(mut self, f: F) -> Self
        where F: FnMut(I) -> O + Send + 'static
    {
        self.rfunc = Rfunc::Mut(Box::new(f));
        self
    }

    pub fn return_once<F>(mut self, f: F) -> Self
        where F: FnOnce(I) -> O + Send + 'static
    {
        let mut fopt = Some(f);
        let fmut = move |i| {
            if let Some(f) = fopt.take() {
                f(i)
            } else {
                panic!("Called a method twice that was expected only once")
            }
        };
        self.rfunc = Rfunc::Once(Box::new(fmut));
        self
    }
}

impl<'object, I, O> Drop for ExpectationBuilder<'object, I, O>
    where I: 'static, O: 'static
{
    fn drop(&mut self) {
        let rfunc = mem::replace(&mut self.rfunc, Rfunc::Default);
        self.e.register(&self.ident, Expectation::new(rfunc))
    }
}

/// Non-generic keys to `Expectations` internal storage
#[derive(Debug, Eq, Hash, PartialEq)]
struct Key(u64);

impl Key {
    fn new<I: 'static, O: 'static>(ident: &str) -> Self {
        let mut hasher = DefaultHasher::new();
        ident.hash(&mut hasher);
        any::TypeId::of::<(I, O)>().hash(&mut hasher);
        Key(hasher.finish())
    }
}

#[derive(Default)]
pub struct Expectations {
    store: Mutex<HashMap<Key, Box<dyn ExpectationT>>>
}

impl Expectations {
    fn register<I, O>(&mut self, ident: &str, expectation: Expectation<I, O>)
        where I: 'static, O: 'static
    {
        let key = Key::new::<I, O>(ident);
        let store = self.store.get_mut().unwrap();
        store.insert(key, Box::new(expectation));
    }

    pub fn expect<I, O>(&mut self, ident: &str) -> ExpectationBuilder<I, O>
        where I: 'static, O: 'static
    {
        ExpectationBuilder::<I, O>::new(self, ident)
    }

    // TODO: add a "called_nonstatic" method that can be used with types that
    // aren't 'static, and uses a different method to generate the key.
    pub fn called<I: 'static, O: 'static>(&self, ident: &str, args: I) -> O {
        let key = Key::new::<I, O>(ident);
        let mut guard = self.store.lock().unwrap();
        let store: &mut HashMap<_, _> = guard.deref_mut();
        let e: &mut Expectation<I, O> = store.get_mut(&key)
            .expect("No matching expectation found")
            .downcast_mut()
            .unwrap();
        e.call_mut(args)
    }
}
<commit_msg>Move the Mutex from Expectations.store to Expectation.rfunc<commit_after>// vim: tw=80
#![cfg_attr(feature = "nightly", feature(specialization))]

use cfg_if::cfg_if;
use downcast::*;
use std::{
    any,
    collections::hash_map::{DefaultHasher, HashMap},
    hash::{Hash, Hasher},
    mem,
    ops::DerefMut,
    sync::Mutex
};

trait ExpectationT : Any + Send {}
downcast!(ExpectationT);

/// Return functions for expectations
enum Rfunc<I, O> {
    Default,
    // Indicates that a `return_once` expectation has already returned
    Expired,
    Mut(Box<dyn FnMut(I) -> O + Send>),
    // Should be Box<dyn FnOnce> once that feature is stabilized
    // https://github.com/rust-lang/rust/issues/28796
    Once(Box<dyn FnMut(I) -> O + Send>),
}

// TODO: change this to "impl FnMut" once unboxed_closures are stable
// https://github.com/rust-lang/rust/issues/29625
impl<I, O>  Rfunc<I, O> {
    fn call_mut(&mut self, args: I) -> O {
        match self {
            Rfunc::Default => {
                Self::return_default()
            },
            Rfunc::Expired => {
                panic!("Called a method twice that was expected only once")
            },
            Rfunc::Mut(f) => {
                f(args)
            },
            Rfunc::Once(_) => {
                let fo = mem::replace(self, Rfunc::Expired);
                if let Rfunc::Once(mut f) = fo {
                    f(args)
                } else {
                    unreachable!()
                }
            },
        }
    }
}

trait ReturnDefault<O> {
    fn return_default() -> O;
}

cfg_if! {
    if #[cfg(feature = "nightly")] {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            default fn return_default() -> O {
                panic!("Can only return default values for types that impl std::Default");
            }
        }
    } else {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            fn return_default() -> O {
                panic!("Returning default values requires the \"nightly\" feature");
            }
        }
    }
}

#[cfg(feature = "nightly")]
impl<I, O: Default> ReturnDefault<O> for Rfunc<I, O> {
    fn return_default() -> O {
        O::default()
    }
}

struct Expectation<I, O> {
    rfunc: Mutex<Rfunc<I, O>>
}

impl<I, O> Expectation<I, O> {
    fn call(&self, i: I) -> O {
        self.rfunc.lock().unwrap()
            .call_mut(i)
    }

    fn new(rfunc: Rfunc<I, O>) -> Self {
        Expectation{rfunc: Mutex::new(rfunc)}
    }
}

impl<I: 'static, O: 'static> ExpectationT for Expectation<I, O> {}

pub struct ExpectationBuilder<'object, I, O>
    where I: 'static, O: 'static
{
    e: &'object mut Expectations,
    rfunc: Rfunc<I, O>,
    ident: String
}

impl<'object, I, O> ExpectationBuilder<'object, I, O>
    where I: 'static, O: 'static
{
    fn new(e: &'object mut Expectations, ident: &str) -> Self {
        // Own the ident so we don't have to worry about lifetime issues
        let ident = ident.to_owned();
        ExpectationBuilder{rfunc: Rfunc::Default, e, ident}
    }

    pub fn returning<F>(mut self, f: F) -> Self
        where F: FnMut(I) -> O + Send + 'static
    {
        self.rfunc = Rfunc::Mut(Box::new(f));
        self
    }

    pub fn return_once<F>(mut self, f: F) -> Self
        where F: FnOnce(I) -> O + Send + 'static
    {
        let mut fopt = Some(f);
        let fmut = move |i| {
            if let Some(f) = fopt.take() {
                f(i)
            } else {
                panic!("Called a method twice that was expected only once")
            }
        };
        self.rfunc = Rfunc::Once(Box::new(fmut));
        self
    }
}

impl<'object, I, O> Drop for ExpectationBuilder<'object, I, O>
    where I: 'static, O: 'static
{
    fn drop(&mut self) {
        let rfunc = mem::replace(&mut self.rfunc, Rfunc::Default);
        self.e.register(&self.ident, Expectation::new(rfunc))
    }
}

/// Non-generic keys to `Expectations` internal storage
#[derive(Debug, Eq, Hash, PartialEq)]
struct Key(u64);

impl Key {
    fn new<I: 'static, O: 'static>(ident: &str) -> Self {
        let mut hasher = DefaultHasher::new();
        ident.hash(&mut hasher);
        any::TypeId::of::<(I, O)>().hash(&mut hasher);
        Key(hasher.finish())
    }
}

#[derive(Default)]
pub struct Expectations {
    store: HashMap<Key, Box<dyn ExpectationT>>
}

impl Expectations {
    fn register<I, O>(&mut self, ident: &str, expectation: Expectation<I, O>)
        where I: 'static, O: 'static
    {
        let key = Key::new::<I, O>(ident);
        self.store.insert(key, Box::new(expectation));
    }

    pub fn expect<I, O>(&mut self, ident: &str) -> ExpectationBuilder<I, O>
        where I: 'static, O: 'static
    {
        ExpectationBuilder::<I, O>::new(self, ident)
    }

    // TODO: add a "called_nonstatic" method that can be used with types that
    // aren't 'static, and uses a different method to generate the key.
    pub fn called<I: 'static, O: 'static>(&self, ident: &str, args: I) -> O {
        let key = Key::new::<I, O>(ident);
        let e: &Expectation<I, O> = self.store.get(&key)
            .expect("No matching expectation found")
            .downcast_ref()
            .unwrap();
        e.call(args)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate regex;

use std::io::Write;
use std::str;

include!("../clap-test.rs");

use clap::{App, Arg};

static SCF2OP: &'static str = "flag NOT present
option NOT present
positional NOT present
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option NOT present
positional NOT present
subcmd present
flag present 2 times
scoption present with value: some
An scoption: some
scpositional present with value: value
";

static SCFOP: &'static str = "flag NOT present
option NOT present
positional NOT present
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option NOT present
positional NOT present
subcmd present
flag present 1 times
scoption present with value: some
An scoption: some
scpositional present with value: value
";

static O2P: &'static str = "flag NOT present
option present 2 times with value: some
An option: some
An option: other
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 2 times with value: some
An option: some
An option: other
positional present with value: value
subcmd NOT present
";

static F2OP: &'static str = "flag present 2 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
";

static FOP: &'static str = "flag present 1 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
";

pub fn check_complex_output(args: &str, out: &str) {
    let mut w = vec![];
    let matches = test::complex_app().get_matches_from(args.split(' ').collect::<Vec<_>>());
    if matches.is_present("flag") {
        writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
    } else {
        writeln!(w, "flag NOT present").unwrap();
    }

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
            writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap();
        }
        if let Some(ov) = matches.values_of("option") {
            for o in ov {
                writeln!(w, "An option: {}", o).unwrap();
            }
        }
    } else {
        writeln!(w, "option NOT present").unwrap();
    }

    if let Some(p) = matches.value_of("positional") {
        writeln!(w, "positional present with value: {}", p).unwrap();
    } else {
        writeln!(w, "positional NOT present").unwrap();
    }

    if matches.is_present("flag2") {
        writeln!(w, "flag2 present").unwrap();
        writeln!(w, "option2 present with value of: {}", matches.value_of("long-option-2").unwrap()).unwrap();
        writeln!(w, "positional2 present with value of: {}", matches.value_of("positional2").unwrap()).unwrap();
    } else {
        writeln!(w, "flag2 NOT present").unwrap();
        writeln!(w, "option2 maybe present with value of: {}", matches.value_of("long-option-2").unwrap_or("Nothing")).unwrap();
        writeln!(w, "positional2 maybe present with value of: {}", matches.value_of("positional2").unwrap_or("Nothing")).unwrap();
    }

    let _ = match matches.value_of("Option3").unwrap_or("") {
        "fast" => writeln!(w, "option3 present quickly"),
        "slow" => writeln!(w, "option3 present slowly"),
        _      => writeln!(w, "option3 NOT present")
    };

    let _ = match matches.value_of("positional3").unwrap_or("") {
        "vi" => writeln!(w, "positional3 present in vi mode"),
        "emacs" => writeln!(w, "positional3 present in emacs mode"),
        _      => writeln!(w, "positional3 NOT present")
    };

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
            writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap();
        }
        if let Some(ov) = matches.values_of("option") {
            for o in ov {
                writeln!(w, "An option: {}", o).unwrap();
            }
        }
    } else {
        writeln!(w, "option NOT present").unwrap();
    }

    if let Some(p) = matches.value_of("positional") {
        writeln!(w, "positional present with value: {}", p).unwrap();
    } else {
        writeln!(w, "positional NOT present").unwrap();
    }
    if matches.is_present("subcmd") {
        writeln!(w, "subcmd present").unwrap();
        if let Some(matches) = matches.subcommand_matches("subcmd") {
            if matches.is_present("flag") {
                writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
            } else {
                writeln!(w, "flag NOT present").unwrap();
            }

            if matches.is_present("option") {
                if let Some(v) = matches.value_of("option") {
                    writeln!(w, "scoption present with value: {}", v).unwrap();
                }
                if let Some(ov) = matches.values_of("option") {
                    for o in ov {
                        writeln!(w, "An scoption: {}", o).unwrap();
                    }
                }
            } else {
                writeln!(w, "scoption NOT present").unwrap();
            }

            if let Some(p) = matches.value_of("scpositional") {
                writeln!(w, "scpositional present with value: {}", p).unwrap();
            }
        }
    } else {
        writeln!(w, "subcmd NOT present").unwrap();
    }

    let res = str::from_utf8(&w).unwrap();
    assert_eq!(res, out);
}

arg_enum!{
    #[derive(Debug)]
    enum Val1 {
        ValOne,
        ValTwo
    }
}
arg_enum!{
    #[derive(Debug)]
    pub enum Val2 {
        ValOne,
        ValTwo
    }
}
arg_enum!{
    enum Val3 {
        ValOne,
        ValTwo
    }
}
arg_enum!{
    pub enum Val4 {
        ValOne,
        ValTwo
    }
}

#[test]
fn test_enums() {
    let v1_lower = "valone";
    let v1_camel = "ValOne";

    let v1_lp = v1_lower.parse::<Val1>().unwrap();
    let v1_cp = v1_camel.parse::<Val1>().unwrap();
    match v1_lp {
        Val1::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val1::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    let v1_lp = v1_lower.parse::<Val2>().unwrap();
    let v1_cp = v1_camel.parse::<Val2>().unwrap();
    match v1_lp {
        Val2::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val2::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    let v1_lp = v1_lower.parse::<Val3>().unwrap();
    let v1_cp = v1_camel.parse::<Val3>().unwrap();
    match v1_lp {
        Val3::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val3::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    let v1_lp = v1_lower.parse::<Val4>().unwrap();
    let v1_cp = v1_camel.parse::<Val4>().unwrap();
    match v1_lp {
        Val4::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val4::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
}

#[test]
fn create_app() {
    let _ =
        App::new("test").version("1.0").author("kevin").about("does awesome things").get_matches_from(vec![""]);
}

#[test]
fn add_multiple_arg() {
    let _ = App::new("test")
                .args(&mut [
                    Arg::with_name("test").short("s"),
                    Arg::with_name("test2").short("l")])
                .get_matches_from(vec![""]);
}
#[test]
fn flag_x2_opt() {
    check_complex_output("clap-test value -f -f -o some",
"flag present 2 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
");
}

#[test]
fn long_opt_x2_pos() {
    check_complex_output("clap-test value --option some --option other", O2P);
}

#[test]
fn long_opt_eq_x2_pos() {
    check_complex_output("clap-test value --option=some --option=other", O2P);
}

#[test]
fn short_opt_x2_pos() {
    check_complex_output("clap-test value -o some -o other", O2P);
}

#[test]
fn short_opt_eq_x2_pos() {
    check_complex_output("clap-test value -o=some -o=other", O2P);
}

#[test]
fn short_flag_x2_comb_short_opt_pos() {
    check_complex_output("clap-test value -ff -o some", F2OP);
}

#[test]
fn short_flag_short_opt_pos() {
    check_complex_output("clap-test value -f -o some", FOP);
}

#[test]
fn long_flag_long_opt_pos() {
    check_complex_output("clap-test value --flag --option some", FOP);
}

#[test]
fn long_flag_long_opt_eq_pos() {
    check_complex_output("clap-test value --flag --option=some", FOP);
}

#[test]
fn sc_long_flag_long_opt() {
    check_complex_output("clap-test subcmd value --flag --option some", SCFOP);
}

#[test]
fn sc_long_flag_short_opt_pos() {
    check_complex_output("clap-test subcmd value --flag -o some", SCFOP);
}

#[test]
fn sc_long_flag_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value --flag --option=some", SCFOP);
}

#[test]
fn sc_short_flag_long_opt_pos() {
    check_complex_output("clap-test subcmd value -f --option some", SCFOP);
}

#[test]
fn sc_short_flag_short_opt_pos() {
    check_complex_output("clap-test subcmd value -f -o some", SCFOP);
}

#[test]
fn sc_short_flag_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f -o=some", SCFOP);
}

#[test]
fn sc_short_flag_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f --option=some", SCFOP);
}

#[test]
fn sc_short_flag_x2_comb_long_opt_pos() {
    check_complex_output("clap-test subcmd value -ff --option some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_comb_short_opt_pos() {
    check_complex_output("clap-test subcmd value -ff -o some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_comb_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -ff --option=some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_comb_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -ff -o=some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_long_opt_pos() {
    check_complex_output("clap-test subcmd value --flag --flag --option some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_short_opt_pos() {
    check_complex_output("clap-test subcmd value --flag --flag -o some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value --flag --flag -o=some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value --flag --flag --option=some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_long_opt_pos() {
    check_complex_output("clap-test subcmd value -f -f --option some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_short_opt_pos() {
    check_complex_output("clap-test subcmd value -f -f -o some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f -f -o=some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f -f --option=some", SCF2OP);
}
<commit_msg>tests: updates tests new global values being propagated up and down<commit_after>#[macro_use]
extern crate clap;
extern crate regex;

use std::io::Write;
use std::str;

include!("../clap-test.rs");

use clap::{App, Arg};

static SCF2OP: &'static str = "flag present 2 times
option NOT present
positional NOT present
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option NOT present
positional NOT present
subcmd present
flag present 2 times
scoption present with value: some
An scoption: some
scpositional present with value: value
";

static SCFOP: &'static str = "flag present 1 times
option NOT present
positional NOT present
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option NOT present
positional NOT present
subcmd present
flag present 1 times
scoption present with value: some
An scoption: some
scpositional present with value: value
";

static O2P: &'static str = "flag NOT present
option present 2 times with value: some
An option: some
An option: other
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 2 times with value: some
An option: some
An option: other
positional present with value: value
subcmd NOT present
";

static F2OP: &'static str = "flag present 2 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
";

static FOP: &'static str = "flag present 1 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
";

pub fn check_complex_output(args: &str, out: &str) {
    let mut w = vec![];
    let matches = test::complex_app().get_matches_from(args.split(' ').collect::<Vec<_>>());
    if matches.is_present("flag") {
        writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
    } else {
        writeln!(w, "flag NOT present").unwrap();
    }

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
            writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap();
        }
        if let Some(ov) = matches.values_of("option") {
            for o in ov {
                writeln!(w, "An option: {}", o).unwrap();
            }
        }
    } else {
        writeln!(w, "option NOT present").unwrap();
    }

    if let Some(p) = matches.value_of("positional") {
        writeln!(w, "positional present with value: {}", p).unwrap();
    } else {
        writeln!(w, "positional NOT present").unwrap();
    }

    if matches.is_present("flag2") {
        writeln!(w, "flag2 present").unwrap();
        writeln!(w, "option2 present with value of: {}", matches.value_of("long-option-2").unwrap()).unwrap();
        writeln!(w, "positional2 present with value of: {}", matches.value_of("positional2").unwrap()).unwrap();
    } else {
        writeln!(w, "flag2 NOT present").unwrap();
        writeln!(w, "option2 maybe present with value of: {}", matches.value_of("long-option-2").unwrap_or("Nothing")).unwrap();
        writeln!(w, "positional2 maybe present with value of: {}", matches.value_of("positional2").unwrap_or("Nothing")).unwrap();
    }

    let _ = match matches.value_of("Option3").unwrap_or("") {
        "fast" => writeln!(w, "option3 present quickly"),
        "slow" => writeln!(w, "option3 present slowly"),
        _      => writeln!(w, "option3 NOT present")
    };

    let _ = match matches.value_of("positional3").unwrap_or("") {
        "vi" => writeln!(w, "positional3 present in vi mode"),
        "emacs" => writeln!(w, "positional3 present in emacs mode"),
        _      => writeln!(w, "positional3 NOT present")
    };

    if matches.is_present("option") {
        if let Some(v) = matches.value_of("option") {
            writeln!(w, "option present {} times with value: {}",matches.occurrences_of("option"), v).unwrap();
        }
        if let Some(ov) = matches.values_of("option") {
            for o in ov {
                writeln!(w, "An option: {}", o).unwrap();
            }
        }
    } else {
        writeln!(w, "option NOT present").unwrap();
    }

    if let Some(p) = matches.value_of("positional") {
        writeln!(w, "positional present with value: {}", p).unwrap();
    } else {
        writeln!(w, "positional NOT present").unwrap();
    }
    if matches.is_present("subcmd") {
        writeln!(w, "subcmd present").unwrap();
        if let Some(matches) = matches.subcommand_matches("subcmd") {
            if matches.is_present("flag") {
                writeln!(w, "flag present {} times", matches.occurrences_of("flag")).unwrap();
            } else {
                writeln!(w, "flag NOT present").unwrap();
            }

            if matches.is_present("option") {
                if let Some(v) = matches.value_of("option") {
                    writeln!(w, "scoption present with value: {}", v).unwrap();
                }
                if let Some(ov) = matches.values_of("option") {
                    for o in ov {
                        writeln!(w, "An scoption: {}", o).unwrap();
                    }
                }
            } else {
                writeln!(w, "scoption NOT present").unwrap();
            }

            if let Some(p) = matches.value_of("scpositional") {
                writeln!(w, "scpositional present with value: {}", p).unwrap();
            }
        }
    } else {
        writeln!(w, "subcmd NOT present").unwrap();
    }

    let res = str::from_utf8(&w).unwrap();
    assert_eq!(res, out);
}

arg_enum!{
    #[derive(Debug)]
    enum Val1 {
        ValOne,
        ValTwo
    }
}
arg_enum!{
    #[derive(Debug)]
    pub enum Val2 {
        ValOne,
        ValTwo
    }
}
arg_enum!{
    enum Val3 {
        ValOne,
        ValTwo
    }
}
arg_enum!{
    pub enum Val4 {
        ValOne,
        ValTwo
    }
}

#[test]
fn test_enums() {
    let v1_lower = "valone";
    let v1_camel = "ValOne";

    let v1_lp = v1_lower.parse::<Val1>().unwrap();
    let v1_cp = v1_camel.parse::<Val1>().unwrap();
    match v1_lp {
        Val1::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val1::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    let v1_lp = v1_lower.parse::<Val2>().unwrap();
    let v1_cp = v1_camel.parse::<Val2>().unwrap();
    match v1_lp {
        Val2::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val2::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    let v1_lp = v1_lower.parse::<Val3>().unwrap();
    let v1_cp = v1_camel.parse::<Val3>().unwrap();
    match v1_lp {
        Val3::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val3::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    let v1_lp = v1_lower.parse::<Val4>().unwrap();
    let v1_cp = v1_camel.parse::<Val4>().unwrap();
    match v1_lp {
        Val4::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
    match v1_cp {
        Val4::ValOne => (),
        _ => panic!("Val1 didn't parse correctly"),
    }
}

#[test]
fn create_app() {
    let _ =
        App::new("test").version("1.0").author("kevin").about("does awesome things").get_matches_from(vec![""]);
}

#[test]
fn add_multiple_arg() {
    let _ = App::new("test")
                .args(&mut [
                    Arg::with_name("test").short("s"),
                    Arg::with_name("test2").short("l")])
                .get_matches_from(vec![""]);
}
#[test]
fn flag_x2_opt() {
    check_complex_output("clap-test value -f -f -o some",
"flag present 2 times
option present 1 times with value: some
An option: some
positional present with value: value
flag2 NOT present
option2 maybe present with value of: Nothing
positional2 maybe present with value of: Nothing
option3 NOT present
positional3 NOT present
option present 1 times with value: some
An option: some
positional present with value: value
subcmd NOT present
");
}

#[test]
fn long_opt_x2_pos() {
    check_complex_output("clap-test value --option some --option other", O2P);
}

#[test]
fn long_opt_eq_x2_pos() {
    check_complex_output("clap-test value --option=some --option=other", O2P);
}

#[test]
fn short_opt_x2_pos() {
    check_complex_output("clap-test value -o some -o other", O2P);
}

#[test]
fn short_opt_eq_x2_pos() {
    check_complex_output("clap-test value -o=some -o=other", O2P);
}

#[test]
fn short_flag_x2_comb_short_opt_pos() {
    check_complex_output("clap-test value -ff -o some", F2OP);
}

#[test]
fn short_flag_short_opt_pos() {
    check_complex_output("clap-test value -f -o some", FOP);
}

#[test]
fn long_flag_long_opt_pos() {
    check_complex_output("clap-test value --flag --option some", FOP);
}

#[test]
fn long_flag_long_opt_eq_pos() {
    check_complex_output("clap-test value --flag --option=some", FOP);
}

#[test]
fn sc_long_flag_long_opt() {
    check_complex_output("clap-test subcmd value --flag --option some", SCFOP);
}

#[test]
fn sc_long_flag_short_opt_pos() {
    check_complex_output("clap-test subcmd value --flag -o some", SCFOP);
}

#[test]
fn sc_long_flag_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value --flag --option=some", SCFOP);
}

#[test]
fn sc_short_flag_long_opt_pos() {
    check_complex_output("clap-test subcmd value -f --option some", SCFOP);
}

#[test]
fn sc_short_flag_short_opt_pos() {
    check_complex_output("clap-test subcmd value -f -o some", SCFOP);
}

#[test]
fn sc_short_flag_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f -o=some", SCFOP);
}

#[test]
fn sc_short_flag_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f --option=some", SCFOP);
}

#[test]
fn sc_short_flag_x2_comb_long_opt_pos() {
    check_complex_output("clap-test subcmd value -ff --option some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_comb_short_opt_pos() {
    check_complex_output("clap-test subcmd value -ff -o some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_comb_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -ff --option=some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_comb_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -ff -o=some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_long_opt_pos() {
    check_complex_output("clap-test subcmd value --flag --flag --option some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_short_opt_pos() {
    check_complex_output("clap-test subcmd value --flag --flag -o some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value --flag --flag -o=some", SCF2OP);
}

#[test]
fn sc_long_flag_x2_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value --flag --flag --option=some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_long_opt_pos() {
    check_complex_output("clap-test subcmd value -f -f --option some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_short_opt_pos() {
    check_complex_output("clap-test subcmd value -f -f -o some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_short_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f -f -o=some", SCF2OP);
}

#[test]
fn sc_short_flag_x2_long_opt_eq_pos() {
    check_complex_output("clap-test subcmd value -f -f --option=some", SCF2OP);
}
<|endoftext|>


<commit_before>use {Field, Value, Borrowed, Matrix2d, Color};
use vecmath::{multiply, translate, rotate_radians, scale, shear};
use {Transform2d, Fill, BackEnd};
use triangulation::{with_polygon_tri_list_xy_rgba_f32};

/// A polygon color context.
pub struct PolygonColorContext<'a> {
    /// Base/origin transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current color.
    pub color: Field<'a, Color>,
    /// Current polygon.
    pub polygon: Field<'a, &'a [f64]>,
}

impl<'a> Transform2d<'a> for PolygonColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for PolygonColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_rgba_f32() {
            let polygon = self.polygon.get();
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            with_polygon_tri_list_xy_rgba_f32(
                self.transform.get(),
                *polygon,
                color,
                |vertices, colors| {
                    back_end.tri_list_xy_rgba_f32(vertices, colors)
                }
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}
<commit_msg>Implemented Clear for PolygonColorContext<commit_after>use {Field, Value, Borrowed, Matrix2d, Color};
use vecmath::{multiply, translate, rotate_radians, scale, shear};
use {Transform2d, Fill, BackEnd, Clear};
use triangulation::{with_polygon_tri_list_xy_rgba_f32};

/// A polygon color context.
pub struct PolygonColorContext<'a> {
    /// Base/origin transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current color.
    pub color: Field<'a, Color>,
    /// Current polygon.
    pub polygon: Field<'a, &'a [f64]>,
}

impl<'a> Transform2d<'a> for PolygonColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> PolygonColorContext<'a> {
        PolygonColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            polygon: Borrowed(self.polygon.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for PolygonColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_rgba_f32() {
            let polygon = self.polygon.get();
            let color = self.color.get();
            let color: [f32, ..4] = [color[0], color[1], color[2], color[3]];
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            with_polygon_tri_list_xy_rgba_f32(
                self.transform.get(),
                *polygon,
                color,
                |vertices, colors| {
                    back_end.tri_list_xy_rgba_f32(vertices, colors)
                }
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a> Clear for PolygonColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::Neg;
use std::{f32, f64};
use std::num::Wrapping;

use Num;

/// Useful functions for signed numbers (i.e. numbers that can be negative).
pub trait Signed: Sized + Num + Neg<Output = Self> {
    /// Computes the absolute value.
    ///
    /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
    ///
    /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
    fn abs(&self) -> Self;

    /// The positive difference of two numbers.
    ///
    /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
    /// between `self` and `other` is returned.
    fn abs_sub(&self, other: &Self) -> Self;

    /// Returns the sign of the number.
    ///
    /// For `f32` and `f64`:
    ///
    /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
    /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
    /// * `NaN` if the number is `NaN`
    ///
    /// For signed integers:
    ///
    /// * `0` if the number is zero
    /// * `1` if the number is positive
    /// * `-1` if the number is negative
    fn signum(&self) -> Self;

    /// Returns true if the number is positive and false if the number is zero or negative.
    fn is_positive(&self) -> bool;

    /// Returns true if the number is negative and false if the number is zero or positive.
    fn is_negative(&self) -> bool;
}

macro_rules! signed_impl {
    ($($t:ty)*) => ($(
        impl Signed for $t {
            #[inline]
            fn abs(&self) -> $t {
                if self.is_negative() { -*self } else { *self }
            }

            #[inline]
            fn abs_sub(&self, other: &$t) -> $t {
                if *self <= *other { 0 } else { *self - *other }
            }

            #[inline]
            fn signum(&self) -> $t {
                match *self {
                    n if n > 0 => 1,
                    0 => 0,
                    _ => -1,
                }
            }

            #[inline]
            fn is_positive(&self) -> bool { *self > 0 }

            #[inline]
            fn is_negative(&self) -> bool { *self < 0 }
        }
    )*)
}

signed_impl!(isize i8 i16 i32 i64);

impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
{
    #[inline]
    fn abs(&self) -> Self {
        Wrapping(self.0.abs())
    }

    #[inline]
    fn abs_sub(&self, other: &Self) -> Self {
        Wrapping(self.0.abs_sub(&other.0))
    }

    #[inline]
    fn signum(&self) -> Self {
        Wrapping(self.0.signum())
    }

    #[inline]
    fn is_positive(&self) -> bool { self.0.is_positive() }

    #[inline]
    fn is_negative(&self) -> bool { self.0.is_negative() }
}

macro_rules! signed_float_impl {
    ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
        impl Signed for $t {
            /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
            #[inline]
            fn abs(&self) -> $t {
                <$t>::abs(*self)
            }

            /// The positive difference of two numbers. Returns `0.0` if the number is
            /// less than or equal to `other`, otherwise the difference between`self`
            /// and `other` is returned.
            #[inline]
            #[allow(deprecated)]
            fn abs_sub(&self, other: &$t) -> $t {
                <$t>::abs_sub(*self, *other)
            }

            /// # Returns
            ///
            /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
            /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
            /// - `NAN` if the number is NaN
            #[inline]
            fn signum(&self) -> $t {
                <$t>::signum(*self)
            }

            /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
            #[inline]
            fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }

            /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
            #[inline]
            fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
        }
    }
}

signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);

/// Computes the absolute value.
///
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
///
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
#[inline(always)]
pub fn abs<T: Signed>(value: T) -> T {
    value.abs()
}

/// The positive difference of two numbers.
///
/// Returns zero if `x` is less than or equal to `y`, otherwise the difference
/// between `x` and `y` is returned.
#[inline(always)]
pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
    x.abs_sub(&y)
}

/// Returns the sign of the number.
///
/// For `f32` and `f64`:
///
/// * `1.0` if the number is positive, `+0.0` or `INFINITY`
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// * `NaN` if the number is `NaN`
///
/// For signed integers:
///
/// * `0` if the number is zero
/// * `1` if the number is positive
/// * `-1` if the number is negative
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }

/// A trait for values which cannot be negative
pub trait Unsigned: Num {}

macro_rules! empty_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {}
    )*)
}

empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);

impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}

#[test]
fn unsigned_wrapping_is_unsigned() {
    fn require_unsigned<T: Unsigned>(_: &T) {}
    require_unsigned(&Wrapping(42_u32));
}
#[test]
fn signed_wrapping_is_signed() {
    fn require_signed<T: Signed>(_: &T) {}
    require_signed(&Wrapping(-42));
}
<commit_msg>comment out wrapping_is_signed test to make Rust 1.8 happy<commit_after>use std::ops::Neg;
use std::{f32, f64};
use std::num::Wrapping;

use Num;

/// Useful functions for signed numbers (i.e. numbers that can be negative).
pub trait Signed: Sized + Num + Neg<Output = Self> {
    /// Computes the absolute value.
    ///
    /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
    ///
    /// For signed integers, `::MIN` will be returned if the number is `::MIN`.
    fn abs(&self) -> Self;

    /// The positive difference of two numbers.
    ///
    /// Returns `zero` if the number is less than or equal to `other`, otherwise the difference
    /// between `self` and `other` is returned.
    fn abs_sub(&self, other: &Self) -> Self;

    /// Returns the sign of the number.
    ///
    /// For `f32` and `f64`:
    ///
    /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
    /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
    /// * `NaN` if the number is `NaN`
    ///
    /// For signed integers:
    ///
    /// * `0` if the number is zero
    /// * `1` if the number is positive
    /// * `-1` if the number is negative
    fn signum(&self) -> Self;

    /// Returns true if the number is positive and false if the number is zero or negative.
    fn is_positive(&self) -> bool;

    /// Returns true if the number is negative and false if the number is zero or positive.
    fn is_negative(&self) -> bool;
}

macro_rules! signed_impl {
    ($($t:ty)*) => ($(
        impl Signed for $t {
            #[inline]
            fn abs(&self) -> $t {
                if self.is_negative() { -*self } else { *self }
            }

            #[inline]
            fn abs_sub(&self, other: &$t) -> $t {
                if *self <= *other { 0 } else { *self - *other }
            }

            #[inline]
            fn signum(&self) -> $t {
                match *self {
                    n if n > 0 => 1,
                    0 => 0,
                    _ => -1,
                }
            }

            #[inline]
            fn is_positive(&self) -> bool { *self > 0 }

            #[inline]
            fn is_negative(&self) -> bool { *self < 0 }
        }
    )*)
}

signed_impl!(isize i8 i16 i32 i64);

impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
{
    #[inline]
    fn abs(&self) -> Self {
        Wrapping(self.0.abs())
    }

    #[inline]
    fn abs_sub(&self, other: &Self) -> Self {
        Wrapping(self.0.abs_sub(&other.0))
    }

    #[inline]
    fn signum(&self) -> Self {
        Wrapping(self.0.signum())
    }

    #[inline]
    fn is_positive(&self) -> bool { self.0.is_positive() }

    #[inline]
    fn is_negative(&self) -> bool { self.0.is_negative() }
}

macro_rules! signed_float_impl {
    ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => {
        impl Signed for $t {
            /// Computes the absolute value. Returns `NAN` if the number is `NAN`.
            #[inline]
            fn abs(&self) -> $t {
                <$t>::abs(*self)
            }

            /// The positive difference of two numbers. Returns `0.0` if the number is
            /// less than or equal to `other`, otherwise the difference between`self`
            /// and `other` is returned.
            #[inline]
            #[allow(deprecated)]
            fn abs_sub(&self, other: &$t) -> $t {
                <$t>::abs_sub(*self, *other)
            }

            /// # Returns
            ///
            /// - `1.0` if the number is positive, `+0.0` or `INFINITY`
            /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
            /// - `NAN` if the number is NaN
            #[inline]
            fn signum(&self) -> $t {
                <$t>::signum(*self)
            }

            /// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
            #[inline]
            fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == $inf }

            /// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
            #[inline]
            fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == $neg_inf }
        }
    }
}

signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY);
signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY);

/// Computes the absolute value.
///
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
///
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
#[inline(always)]
pub fn abs<T: Signed>(value: T) -> T {
    value.abs()
}

/// The positive difference of two numbers.
///
/// Returns zero if `x` is less than or equal to `y`, otherwise the difference
/// between `x` and `y` is returned.
#[inline(always)]
pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
    x.abs_sub(&y)
}

/// Returns the sign of the number.
///
/// For `f32` and `f64`:
///
/// * `1.0` if the number is positive, `+0.0` or `INFINITY`
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
/// * `NaN` if the number is `NaN`
///
/// For signed integers:
///
/// * `0` if the number is zero
/// * `1` if the number is positive
/// * `-1` if the number is negative
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }

/// A trait for values which cannot be negative
pub trait Unsigned: Num {}

macro_rules! empty_trait_impl {
    ($name:ident for $($t:ty)*) => ($(
        impl $name for $t {}
    )*)
}

empty_trait_impl!(Unsigned for usize u8 u16 u32 u64);

impl<T: Unsigned> Unsigned for Wrapping<T> where Wrapping<T>: Num {}

#[test]
fn unsigned_wrapping_is_unsigned() {
    fn require_unsigned<T: Unsigned>(_: &T) {}
    require_unsigned(&Wrapping(42_u32));
}
/*
// Commenting this out since it doesn't compile on Rust 1.8,
// because on this version Wrapping doesn't implement Neg and therefore can't
// implement Signed.
#[test]
fn signed_wrapping_is_signed() {
    fn require_signed<T: Signed>(_: &T) {}
    require_signed(&Wrapping(-42));
}
*/
<|endoftext|>


<commit_before>use Prefab;
use Rng;
use calx_grid::Dir6;
use field::Field;
use form::Form;
use location::{Location, Portal};
use mapfile;
use rand::{self, Rand, SeedableRng};
use serde;
use std::cmp;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::io::Cursor;
use std::slice;
use terrain::Terrain;
use world::Loadout;

/// Static generated world.
pub struct Worldgen {
    seed: u32,
    terrain: Field<Terrain>,
    portals: HashMap<Location, Portal>,
    spawns: Vec<(Location, Loadout)>,
    player_entry: Location,
}

impl Worldgen {
    pub fn new(seed: u32) -> Worldgen {
        let mut ret = Worldgen {
            seed: seed,
            terrain: Field::new(),
            portals: HashMap::new(),
            spawns: Vec::new(),
            player_entry: Location::new(0, 0, 0),
        };

        let mut rng: Rng = SeedableRng::from_seed([seed, seed, seed, seed]);
        //ret.sprint_map();
        ret.gen_caves(&mut rng);

        ret
    }

    fn sprint_map(&mut self) {
        const SPRINT_PREFAB: &'static str = include_str!("../../sprint.ron");

        let sprint_prefab = mapfile::load_prefab(&mut Cursor::new(SPRINT_PREFAB))
            .expect("Corrupt sprint file");

        // Top-left of the default on-screen area.
        let origin = Location::new(-21, -22, 0);
        self.load_prefab(origin, &sprint_prefab);
    }

    fn load_prefab(&mut self, origin: Location, prefab: &Prefab) {
        for (p, &(ref terrain, ref entities)) in prefab.iter() {
            let loc = origin + p;

            self.terrain.set(loc, *terrain);

            for spawn in entities.iter() {
                if spawn == "player" {
                    self.player_entry = loc;
                } else {
                    let form = Form::named(spawn).expect(&format!(
                        "Bad prefab: Form '{}' not found!",
                        spawn
                    ));
                    self.spawns.push((loc, form.loadout.clone()));
                }
            }
        }
    }

    pub fn seed(&self) -> u32 { self.seed }

    pub fn get_terrain(&self, loc: Location) -> Terrain { self.terrain.get(loc) }

    pub fn get_portal(&self, loc: Location) -> Option<Location> {
        self.portals.get(&loc).map(|&p| loc + p)
    }

    pub fn spawns(&self) -> slice::Iter<(Location, Loadout)> { self.spawns.iter() }

    pub fn player_entry(&self) -> Location { self.player_entry }

    fn gen_caves<R: rand::Rng>(&mut self, rng: &mut R) {
        use self::Prototerrain::*;

        let mut cells_to_dig = 500;

        let mut map = screen_map(Location::new(0, 0, 0));

        let start = *rand::sample(rng, map.iter().filter(|x| *x.1 == Unused), 1)[0].0;
        map.set(start, Floor);
        let mut edge: BTreeSet<Location> = Dir6::iter()
            .map(|&d| start + d)
            .filter(|&loc| map.get(loc) == Unused)
            .collect();

        // Arbitrary long iteration, should break after digging a sufficient number of cells before
        // this.
        for _ in 0..10000 {
            if edge.is_empty() {
                break;
            }

            let dig_loc = *rand::sample(rng, edge.iter(), 1)[0];

            // Prefer digging narrow corridors, there's an increasing chance to abort the dig when the
            // selected location is in a very open space.
            let adjacent_floors = Dir6::iter()
                .filter(|d| map.get(dig_loc + **d) == Floor)
                .count();
            if rng.gen_range(0, cmp::max(1, adjacent_floors * 2)) != 0 {
                continue;
            }

            map.set(dig_loc, Floor);
            edge.extend(Dir6::iter().map(|&d| dig_loc + d).filter(|&loc| {
                map.get(loc) == Unused
            }));

            cells_to_dig -= 1;
            if cells_to_dig == 0 {
                break;
            }
        }

        self.terrain.extend(map.iter().map(|(&loc, &t)| {
            let t = match t {
                Outside => Terrain::Empty,
                Unused => Terrain::Rock,
                Border => Terrain::Rock,
                Floor => Terrain::Ground,
                Wall => Terrain::Rock,
                Door => Terrain::Door,
            };
            (loc, t)
        }));

    }
}

impl serde::Serialize for Worldgen {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.seed.serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Worldgen {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        Ok(Worldgen::new(serde::Deserialize::deserialize(d)?))
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum Prototerrain {
    /// Area completely outside the map to be generated.
    Outside,
    /// Area that should be filled with map content but hasn't been yet.
    Unused,
    /// Area that the player cannot enter but that may be visible on screen.
    Border,
    Floor,
    Wall,
    Door,
}

impl Default for Prototerrain {
    fn default() -> Self { Prototerrain::Outside }
}

fn screen_map(origin: Location) -> Field<Prototerrain> {
    let mut ret = Field::new();

    for &v in ::onscreen_locations() {
        let loc = origin + v;
        for &d in Dir6::iter() {
            if ret.get(loc + d) == Default::default() {
                ret.set(loc + d, Prototerrain::Border);
            }
            ret.set(loc, Prototerrain::Unused);
        }
    }

    ret
}
<commit_msg>Enhance cavegen<commit_after>use Prefab;
use Rng;
use calx_grid::Dir6;
use euclid::vec2;
use field::Field;
use form::Form;
use location::{Location, Portal};
use mapfile;
use rand::{self, Rand, SeedableRng};
use serde;
use std::cmp;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::io::Cursor;
use std::slice;
use terrain::Terrain;
use world::Loadout;

/// Static generated world.
pub struct Worldgen {
    seed: u32,
    terrain: Field<Terrain>,
    portals: HashMap<Location, Portal>,
    spawns: Vec<(Location, Loadout)>,
    player_entry: Location,
}

impl Worldgen {
    pub fn new(seed: u32) -> Worldgen {
        let mut ret = Worldgen {
            seed: seed,
            terrain: Field::new(),
            portals: HashMap::new(),
            spawns: Vec::new(),
            player_entry: Location::new(0, 0, 0),
        };

        let mut rng: Rng = SeedableRng::from_seed([seed, seed, seed, seed]);
        //ret.sprint_map();
        ret.gen_caves(&mut rng);

        ret
    }

    fn sprint_map(&mut self) {
        const SPRINT_PREFAB: &'static str = include_str!("../../sprint.ron");

        let sprint_prefab = mapfile::load_prefab(&mut Cursor::new(SPRINT_PREFAB))
            .expect("Corrupt sprint file");

        // Top-left of the default on-screen area.
        let origin = Location::new(-21, -22, 0);
        self.load_prefab(origin, &sprint_prefab);
    }

    fn load_prefab(&mut self, origin: Location, prefab: &Prefab) {
        for (p, &(ref terrain, ref entities)) in prefab.iter() {
            let loc = origin + p;

            self.terrain.set(loc, *terrain);

            for spawn in entities.iter() {
                if spawn == "player" {
                    self.player_entry = loc;
                } else {
                    let form = Form::named(spawn).expect(&format!(
                        "Bad prefab: Form '{}' not found!",
                        spawn
                    ));
                    self.spawns.push((loc, form.loadout.clone()));
                }
            }
        }
    }

    pub fn seed(&self) -> u32 { self.seed }

    pub fn get_terrain(&self, loc: Location) -> Terrain { self.terrain.get(loc) }

    pub fn get_portal(&self, loc: Location) -> Option<Location> {
        self.portals.get(&loc).map(|&p| loc + p)
    }

    pub fn spawns(&self) -> slice::Iter<(Location, Loadout)> { self.spawns.iter() }

    pub fn player_entry(&self) -> Location { self.player_entry }

    fn gen_caves<R: rand::Rng>(&mut self, rng: &mut R) {
        use self::Prototerrain::*;

        let mut cells_to_dig = 700;

        let mut map = screen_map(Location::new(0, 0, 0));

        let start = *rand::sample(rng, map.iter().filter(|x| *x.1 == Unused), 1)[0].0;
        map.set(start, Floor);
        let mut edge: BTreeSet<Location> = Dir6::iter()
            .map(|&d| start + d)
            .filter(|&loc| map.get(loc) == Unused)
            .collect();

        // Arbitrary long iteration, should break after digging a sufficient number of cells before
        // this.
        for _ in 0..10000 {
            if edge.is_empty() {
                break;
            }

            let dig_loc = *rand::sample(rng, edge.iter(), 1)[0];

            // Prefer digging narrow corridors, there's an increasing chance to abort the dig when the
            // selected location is in a very open space.
            let adjacent_floors = Dir6::iter()
                .filter(|d| map.get(dig_loc + **d) == Floor)
                .count();
            if rng.gen_range(0, cmp::max(1, adjacent_floors * adjacent_floors)) != 0 {
                continue;
            }

            map.set(dig_loc, Floor);
            edge.extend(Dir6::iter().map(|&d| dig_loc + d).filter(|&loc| {
                map.get(loc) == Unused
            }));

            cells_to_dig -= 1;
            if cells_to_dig == 0 {
                break;
            }
        }

        // Postprocess
        let cells: Vec<_> = map.iter().map(|(&loc, &c)| (loc, c)).collect();
        for (loc, c) in cells.into_iter() {
            // Clear pillars
            if c == Unused {
                let adjacent_floors = Dir6::iter().filter(|d| map.get(loc + **d) == Floor).count();

                if adjacent_floors == 6 {
                    map.set(loc, Floor);
                }
            }
        }

        // Map to actual terrains
        self.terrain.extend(map.iter().map(|(&loc, &t)| {
            let t = match t {
                Outside => Terrain::Empty,
                Unused => Terrain::Rock,
                Border => Terrain::Rock,
                Floor => Terrain::Ground,
                Wall => Terrain::Rock,
                Door => Terrain::Door,
            };
            (loc, t)
        }));

    }
}

impl serde::Serialize for Worldgen {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.seed.serialize(s)
    }
}

impl<'a> serde::Deserialize<'a> for Worldgen {
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        Ok(Worldgen::new(serde::Deserialize::deserialize(d)?))
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum Prototerrain {
    /// Area completely outside the map to be generated.
    Outside,
    /// Area that should be filled with map content but hasn't been yet.
    Unused,
    /// Area that the player cannot enter but that may be visible on screen.
    Border,
    Floor,
    Wall,
    Door,
}

impl Default for Prototerrain {
    fn default() -> Self { Prototerrain::Outside }
}

fn screen_map(origin: Location) -> Field<Prototerrain> {
    let mut ret = Field::new();

    // Cells two cells away from the live area at the bottom of the screen can still affect
    // the visible terrain via cell reshaping, so add those as well to the border.
    const BORDER_MASK: [(i32, i32); 9] = [
        (-1, -1),
        (0, -1),
        (1, 0),
        (1, 1),
        (0, 1),
        (-1, 0),
        (2, 1),
        (2, 2),
        (1, 2),
    ];

    for &v in ::onscreen_locations() {
        let loc = origin + v;
        // Paint border for every cell, all except the one from the cells at the actual border will
        // be overwritten.
        for d in &BORDER_MASK {
            let vec = vec2(d.0, d.1);
            if ret.get(loc + vec) == Default::default() {
                ret.set(loc + vec, Prototerrain::Border);
            }
        }

        ret.set(loc, Prototerrain::Unused);
    }

    ret
}
<|endoftext|>