1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Module containing crate macros.

/// Given an array of elements, converts each element to values and returns an `Arr` containing a
/// vector of the elements. For a non-panicking version, see `try_arr!`.
///
/// # Panics
/// Panics if the types don't check out.
#[macro_export]
macro_rules! arr {
    [] => {
        $crate::arr::Arr::new()
    };
    [ $( $elem:expr ),+ , ] => {
        // Rule with trailing comma.
        try_arr![$( $elem ),+].unwrap()
    };
    [ $( $elem:expr ),+ ] => {
        try_arr![$( $elem ),+].unwrap()
    };
}

/// Given an array of elements, converts each element to values and returns an `Arr` containing a
/// vector of the values. Returns an `OverResult` instead of panicking on error. To create an empty
/// `Arr`, use `arr!` as it will never fail.
#[macro_export]
macro_rules! try_arr {
    [ $( $elem:expr ),+ , ] => {
        // Rule with trailing comma.
        try_arr![$( $elem ),+]
    };
    [ $( $elem:expr ),+ ] => {
        {
            use $crate::arr::Arr;

            Arr::from_vec(vec![ $( $elem.into() ),+ ])
        }
    };
}

/// Given an array of elements, converts each element to values and returns a `Tup` containing a
/// vector of the values.
#[macro_export]
macro_rules! tup {
    ( $( $elem:expr ),* , ) => {
        tup!($( $elem ),*)
    };
    ( $( $elem:expr ),* ) => {
        {
            use $crate::tup::Tup;

            Tup::from_vec(vec![ $( $elem.into() ),+ ])
        }
    };
}

/// Given an array of field/value pairs, returns an `Obj` containing each pair.
#[macro_export]
macro_rules! obj {
    { $( $field:expr => $inner:expr ),* , } => {
        // Rule with trailing comma.
        obj!{ $( $field => $inner ),* };
    };
    { $( $field:expr => $inner:expr ),* } => {
        {
            use $crate::obj::Obj;

            let mut obj = Obj::new();

            $(
                obj.set($field, $inner.into());
            )*

            obj
        }
    };
}

#[cfg(test)]
mod tests {
    use OverError;
    use obj::Obj;
    use types::Type::*;
    use value::Value;

    #[test]
    fn arr_basic() {
        assert_eq!(
            arr![Value::Int(1.into()), Value::Int(2.into())],
            try_arr![1, 2].unwrap()
        );

        assert_ne!(
            arr![-1, 2],
            try_arr![Value::Int(1.into()), Value::Int(2.into())].unwrap()
        );
    }

    #[test]
    fn try_arr_mismatch() {
        assert_eq!(
            try_arr![arr![1, 1], arr!['c']],
            Err(OverError::ArrTypeMismatch(
                Arr(Box::new(Char)),
                Arr(Box::new(Int)),
            ))
        );
        assert_eq!(try_arr![1, 'c'], Err(OverError::ArrTypeMismatch(Char, Int)));
    }

    #[test]
    fn obj_basic() {
        let mut obj = Obj::new();
        obj.set("a", 1.into());
        obj.set("b", arr![1, 2].into());

        assert_eq!(
            obj,
            obj!{
            "a" => 1,
            "b" => arr![1, 2]
        }
        );
    }
}