size_hinter 0.4.2

Iterator adaptors allowing overriding or specifying size_hint.
Documentation
#![allow(unused_macros)]

/// Unified macro to test iterator property tracking during iteration
///
///   next => Some(1), len: 3
///   next => Some(2), hint: (5, Some(10))
macro_rules! test_iter {
    // (name, initial => len: len, ( method => expected, len: remaining );+ )
    ($name:ident, $initial:expr => len: $len:expr, $( $method:ident => $expected:expr, len: $remaining:expr );+ $(;)?) => {
        #[test]
        fn $name() {
            let mut iter = $initial;
            assert_eq!(iter.len(), $len, "len should be {} at start", $len);
            assert_eq!(iter.size_hint(), ($len, Some($len)), "size_hint should be ({}, Some({})) at start", $len, $len);
            $(
                assert_eq!(iter.$method(), $expected, "{} did not return {:?}", stringify!($method), $expected);
                assert_eq!(iter.len(), $remaining, "len should be {} after {}", $remaining, stringify!($method));
                assert_eq!(iter.size_hint(), ($remaining, Some($remaining)), "size_hint should be ({}, Some({})) after {}", $remaining, $remaining, stringify!($method));
            )+
        }
    };

    // (name, initial => hint: initial_hint, ( method => expected, hint: hint );+ )
    ($name:ident, $initial:expr => hint: $initial_hint:expr, $( $method:ident => $expected:expr, hint: $hint:expr );+ $(;)?) => {
        #[test]
        fn $name() {
            let mut iter = $initial;
            assert_eq!(iter.size_hint(), Into::<(usize, Option<usize>)>::into($initial_hint), "size_hint should be {:?} at start", $initial_hint);
            $(
                assert_eq!(iter.$method(), $expected, "{} did not return {:?}", stringify!($method), $expected);
                assert_eq!(iter.size_hint(), Into::<(usize, Option<usize>)>::into($hint), "size_hint should be {:?} after {}", $hint, stringify!($method));
            )+
        }
    };
}

/// Macro to test initial state/construction of an iterator
///
/// (name, initial => hint: initial_hint)
/// (name, initial => len: initial_len)
/// (name, initial => panic: expected_msg)
macro_rules! test_ctor {
    ($name:ident, $iter:expr => hint: $hint:expr) => {
        #[test]
        fn $name() {
            let iter = $iter;
            assert_eq!(iter.size_hint(), Into::<(usize, Option<usize>)>::into($hint), "expected size_hint to match");
            assert!(matches!(iter.into_inner(), Range { .. }))
        }
    };

    ($name:ident, $iter:expr => len: $expected:expr) => {
        #[test]
        fn $name() {
            let iter = $iter;
            assert_eq!(iter.len(), $expected);
            assert!(matches!(iter.into_inner(), Range { .. }))
        }
    };

    ($name:ident, $iter:expr => panic: $expected_msg:expr) => {
        #[test]
        #[should_panic(expected = $expected_msg)]
        fn $name() {
            let _ = $iter;
        }
    };

    ($name:ident, $iter:expr => Err) => {
        #[test]
        fn $name() {
            let result = $iter;
            assert!(result.is_err(), "expected Err, got Ok");
        }
    };
}

/// Macro to create a test that expects a panic with a specific message
///
/// Usage: `panics!(test_name, code_to_panic, "expected panic message");`
#[allow(unused_macros)]
macro_rules! panics {
    ($name:ident, $code:expr, $msg:literal) => {
        #[test]
        #[should_panic(expected = $msg)]
        fn $name() {
            $code;
        }
    };
}

#[allow(unused_imports)]
pub(crate) use panics;
#[allow(unused_imports)]
pub(crate) use test_ctor;
#[allow(unused_imports)]
pub(crate) use test_iter;