either.rs raw

//! Alternative parser combinator and the `oneof!` macro.
//!
//! This module provides the [`Either`] combinator for choosing between alternative
//! parsers, along with the [`oneof!`](crate::oneof) macro for convenient choice syntax.
//!
//! The Either combinator implements a Chain of Responsibility pattern, trying the
//! first parser and falling back to the second if the first fails with `NoMatch`.
//! The result is a tuple `(Option<A>, Option<B>)` where exactly one option contains
//! a value.
//!
//! Alternative composition is fundamental for building parsers that can handle
//! multiple possible input formats or syntax variations.

use crate::{
    cache::ParsingCache,
    parser::{Parsable, Parser, Source},
    result::{Error, ParseResult},
};

/// A parser combinator that tries two parsers in sequence, succeeding if either matches.
///
/// Either applies the first parser, and if it fails with `NoMatch`, tries the second parser.
/// The output is a tuple `(Option<A::Output>, Option<B::Output>)` where exactly one option
/// contains the successful result and the other is `None`.
///
/// # Examples
///
/// ```rust
/// use neotoma::{either::Either, literal::Literal, parser::{parse, Source}};
/// use std::io::Cursor;
///
/// // Match either "hello" or "world"
/// let greeting = Either::new(
///     Literal::from_str("hello"),
///     Literal::from_str("world")
/// );
///
/// // Matches: "hello" -> (Some("hello"), None)
/// let mut input1 = Cursor::new(b"hello");
/// let mut source1 = Source::new(input1);
/// let result1 = parse(greeting, &mut source1).unwrap();
/// assert_eq!(result1.0, Some(b"hello".as_slice().into()));
/// assert_eq!(result1.1, None);
///
/// // Matches: "world" -> (None, Some("world"))
/// let greeting2 = Either::new(
///     Literal::from_str("hello"),
///     Literal::from_str("world")
/// );
/// let mut input2 = Cursor::new(b"world");
/// let mut source2 = Source::new(input2);
/// let result2 = parse(greeting2, &mut source2).unwrap();
/// assert_eq!(result2.0, None);
/// assert_eq!(result2.1, Some(b"world".as_slice().into()));
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Either<A, B> {
    first: A,
    second: B,
}

impl<A, B> Either<A, B> {
    /// Create a new Either parser that tries the first parser, then the second if the first fails.
    ///
    /// The first parser is tried first. If it succeeds, returns `(Some(result), None)`.
    /// If it fails with `NoMatch`, the second parser is tried. If the second parser succeeds,
    /// returns `(None, Some(result))`. If both fail with `NoMatch`, Either fails with `NoMatch`.
    /// Other errors (like IO errors) are propagated immediately.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use neotoma::{either::Either, literal::Literal, parser::{parse, Source}};
    /// use std::io::Cursor;
    ///
    /// let yes_or_no = Either::new(
    ///     Literal::from_str("yes"),
    ///     Literal::from_str("no")
    /// );
    ///
    /// // Matches "yes" -> (Some("yes"), None)
    /// let mut input1 = Cursor::new(b"yes");
    /// let mut source1 = Source::new(input1);
    /// let result1 = parse(yes_or_no, &mut source1).unwrap();
    /// assert_eq!(result1.0, Some(b"yes".as_slice().into()));
    /// assert_eq!(result1.1, None);
    ///
    /// // Matches "no" -> (None, Some("no"))
    /// let yes_or_no2 = Either::new(
    ///     Literal::from_str("yes"),
    ///     Literal::from_str("no")
    /// );
    /// let mut input2 = Cursor::new(b"no");
    /// let mut source2 = Source::new(input2);
    /// let result2 = parse(yes_or_no2, &mut source2).unwrap();
    /// assert_eq!(result2.0, None);
    /// assert_eq!(result2.1, Some(b"no".as_slice().into()));
    /// ```
    pub fn new(first: A, second: B) -> Self {
        Self { first, second }
    }
}

/// Macro for creating Either parsers with multiple alternatives.
///
/// This macro creates a right-associative structure of Either parsers.
/// `oneof![A, B, C]` becomes `Either<A, Either<B, C>>`.
///
/// # Examples
///
/// ```rust
/// use neotoma::{oneof, literal::Literal, parser::{parse, Source}};
/// use std::io::Cursor;
///
/// // Match one of several alternatives
/// let parser = oneof![
///     Literal::from_str("alpha"),
///     Literal::from_str("beta"),
///     Literal::from_str("gamma")
/// ];
///
/// // Test first alternative
/// let mut input = Cursor::new(b"alpha");
/// let mut source = Source::new(input);
/// let result = parse(parser, &mut source).unwrap();
/// assert_eq!(result.0, Some(b"alpha".as_slice().into()));
/// assert_eq!(result.1, None);
/// ```
#[macro_export]
macro_rules! oneof {
    // Base case: single parser wrapped in Either with empty alternative
    ($parser:expr) => {
        $parser
    };

    // Recursive case: first parser or oneof of the rest
    ($first:expr, $($rest:expr),+ $(,)?) => {
        $crate::either::Either::new($first, oneof!($($rest),+))
    };
}

impl<A, B, Ctx> Parser<Ctx> for Either<A, B>
where
    A: Parser<Ctx>,
    B: Parser<Ctx>,
{
    type Output = (Option<A::Output>, Option<B::Output>);

    fn id(&self) -> u64 {
        use std::any::TypeId;
        use std::hash::{DefaultHasher, Hash, Hasher};

        let mut hasher = DefaultHasher::new();
        TypeId::of::<Self>().hash(&mut hasher);
        self.first.id().hash(&mut hasher);
        self.second.id().hash(&mut hasher);
        hasher.finish()
    }

    fn read<S>(
        &self,
        source: &mut Source<S>,
        cache: &mut impl ParsingCache,
        context: &mut Ctx,
    ) -> ParseResult<Self::Output>
    where
        S: Parsable,
    {
        match self.first.parse(source, cache, context) {
            Ok(result) => Ok((Some(result), None)),
            Err(Error::NoMatch) => {
                // First parser failed, try second
                match self.second.parse(source, cache, context) {
                    Ok(result) => Ok((None, Some(result))),
                    Err(err) => Err(err),
                }
            }
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{literal::Literal, parser::parse};
    use std::io::Cursor;

    #[test]
    fn test_id_implementation_different_either_parsers() {
        // Test that Either implements proper id() method
        // Different Either parsers should have different IDs to avoid cache conflicts

        let either1 = Either::new(Literal::from_str("hello"), Literal::from_str("world"));
        let either2 = Either::new(Literal::from_str("foo"), Literal::from_str("bar"));

        // These should have different IDs because they have different inner parsers
        // This test will FAIL if Either uses default id() implementation
        assert_ne!(
            <Either<_, _> as crate::parser::Parser<()>>::id(&either1),
            <Either<_, _> as crate::parser::Parser<()>>::id(&either2),
            "Different Either instances should have different IDs to avoid cache collisions"
        );
    }

    #[test]
    fn test_id_implementation_same_either_parsers() {
        // Test that identical Either parsers have the same ID
        let either1 = Either::new(Literal::from_str("hello"), Literal::from_str("world"));
        let either2 = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        assert_eq!(
            <Either<_, _> as crate::parser::Parser<()>>::id(&either1),
            <Either<_, _> as crate::parser::Parser<()>>::id(&either2),
            "Identical Either instances should have the same ID for cache efficiency"
        );
    }

    #[test]
    fn test_id_implementation_either_different_order() {
        // Test that order matters in Either parsers
        let either1 = Either::new(Literal::from_str("hello"), Literal::from_str("world"));
        let either2 = Either::new(Literal::from_str("world"), Literal::from_str("hello"));

        // These should have different IDs because order matters in Either
        // This test will FAIL if Either uses default id() implementation
        assert_ne!(
            <Either<_, _> as crate::parser::Parser<()>>::id(&either1),
            <Either<_, _> as crate::parser::Parser<()>>::id(&either2),
            "Either instances with different order should have different IDs"
        );
    }

    #[test]
    fn test_either_first_matches() {
        let parser = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        let mut input = Cursor::new(b"hello");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result.0, Some(b"hello".as_slice().into()));
        assert_eq!(result.1, None);
    }

    #[test]
    fn test_either_second_matches() {
        let parser = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        let mut input = Cursor::new(b"world");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result.0, None);
        assert_eq!(result.1, Some(b"world".as_slice().into()));
    }

    #[test]
    fn test_either_neither_matches() {
        let parser = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        let mut input = Cursor::new(b"foo");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source);
        assert!(matches!(result, Err(Error::NoMatch)));
    }

    #[test]
    fn test_either_empty_input() {
        let parser = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        let mut input = Cursor::new(b"");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source);
        assert!(matches!(result, Err(Error::NoMatch)));
    }

    #[test]
    fn test_either_first_parser_priority() {
        // Test that first parser has priority when both could match
        let parser = Either::new(Literal::from_str("he"), Literal::from_str("hello"));

        let mut input = Cursor::new(b"hello");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result.0, Some(b"he".as_slice().into()));
        assert_eq!(result.1, None);
    }

    #[test]
    fn test_either_different_types() {
        use crate::class::Class;
        use crate::parser::parse;

        // Either a literal or digits
        let parser = Either::new(Literal::from_str("prefix"), Class::digits());

        // First matches
        let mut input1 = Cursor::new(b"prefix");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser, &mut source1).unwrap();
        assert_eq!(result1.0, Some(b"prefix".as_slice().into()));
        assert_eq!(result1.1, None);

        // Second matches
        let parser2 = Either::new(Literal::from_str("prefix"), Class::digits());

        let mut input2 = Cursor::new(b"123");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        assert_eq!(result2.0, None);
        assert_eq!(result2.1, Some(b"123".to_vec()));
    }

    #[test]
    fn test_either_position_tracking() {
        use crate::parser::parse;

        // Verify position is correctly managed when first parser fails
        let parser = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        let mut input = Cursor::new(b"worldXYZ");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result.0, None);
        assert_eq!(result.1, Some(b"world".as_slice().into()));

        // Position should be at 'X'
        let next_byte = source.peek1().unwrap();
        assert_eq!(next_byte, b'X');
    }

    #[test]
    fn test_either_with_complex_parsers() {
        use crate::{parser::parse, repeat::Repeat, sequence::Sequence};

        // Either a repeated "a" or a sequence "hello world"
        let repeat_a = Repeat::new(Literal::from_str("a"));
        let hello_world = Sequence::new(Literal::from_str("hello"), Literal::from_str(" world"));
        let parser = Either::new(repeat_a, hello_world);

        // Test first alternative (repeated "a")
        let mut input1 = Cursor::new(b"aaaXYZ");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser, &mut source1).unwrap();
        if let Some(repeated_results) = result1.0 {
            assert_eq!(repeated_results.len(), 3);
            assert_eq!(result1.1, None);
        } else {
            // If first alternative didn't match, second should match
            assert!(result1.1.is_some());
        }

        // Test second alternative (sequence)
        let repeat_a2 = Repeat::new(Literal::from_str("a"));
        let hello_world2 = Sequence::new(Literal::from_str("hello"), Literal::from_str(" world"));
        let parser2 = Either::new(repeat_a2, hello_world2);

        let mut input2 = Cursor::new(b"hello worldXYZ");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        // Either the repeat matched (possibly empty) or the sequence matched
        if let Some(repeat_result) = result2.0 {
            // If repeat matched, it should be empty for this input
            assert_eq!(repeat_result.len(), 0);
        } else if let Some(sequence_result) = result2.1 {
            // If sequence matched, check its content
            let (hello, world) = sequence_result;
            assert_eq!(hello, b"hello".as_slice().into());
            assert_eq!(world, b" world".as_slice().into());
        } else {
            panic!("Either should match one alternative");
        }
    }

    #[test]
    fn test_either_nested() {
        use crate::parser::parse;

        // Test nested Either parsers: Either<Either<A, B>, C>
        let inner_either = Either::new(Literal::from_str("a"), Literal::from_str("b"));
        let outer_either = Either::new(inner_either, Literal::from_str("c"));

        // Test first inner alternative
        let mut input1 = Cursor::new(b"a");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(outer_either, &mut source1).unwrap();
        assert!(result1.0.is_some());
        let inner_result = result1.0.unwrap();
        assert_eq!(inner_result.0, Some(b"a".as_slice().into()));
        assert_eq!(inner_result.1, None);
        assert_eq!(result1.1, None);

        // Test second inner alternative
        let inner_either2 = Either::new(Literal::from_str("a"), Literal::from_str("b"));
        let outer_either2 = Either::new(inner_either2, Literal::from_str("c"));

        let mut input2 = Cursor::new(b"b");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(outer_either2, &mut source2).unwrap();
        assert!(result2.0.is_some());
        let inner_result2 = result2.0.unwrap();
        assert_eq!(inner_result2.0, None);
        assert_eq!(inner_result2.1, Some(b"b".as_slice().into()));
        assert_eq!(result2.1, None);

        // Test outer alternative
        let inner_either3 = Either::new(Literal::from_str("a"), Literal::from_str("b"));
        let outer_either3 = Either::new(inner_either3, Literal::from_str("c"));

        let mut input3 = Cursor::new(b"c");
        let mut source3 = crate::parser::Source::new(&mut input3);

        let result3 = parse(outer_either3, &mut source3).unwrap();
        assert_eq!(result3.0, None);
        assert_eq!(result3.1, Some(b"c".as_slice().into()));
    }

    #[test]
    fn test_either_chained_alternatives() {
        use crate::parser::parse;

        // Test chaining multiple Either parsers for many alternatives
        // Test each alternative
        let test_cases = vec![
            ("alpha", "first"),
            ("beta", "second"),
            ("gamma", "third"),
            ("delta", "fourth"),
        ];

        for (input_str, description) in test_cases {
            let choice1 = Either::new(Literal::from_str("alpha"), Literal::from_str("beta"));
            let choice2 = Either::new(choice1, Literal::from_str("gamma"));
            let choice3 = Either::new(choice2, Literal::from_str("delta"));

            let mut input = Cursor::new(input_str.as_bytes());
            let mut source = crate::parser::Source::new(&mut input);

            let result = parse(choice3, &mut source);
            assert!(result.is_ok(), "Failed to parse {description} alternative",);
        }
    }

    #[test]
    fn test_either_with_bounds() {
        use crate::{class::Class, parser::parse};

        // Either exactly 2 digits or exactly 3 letters
        let two_digits = Class::with_bounds(b"0123456789", 2, 2);
        let three_letters = Class::with_bounds(b"abcdefghijklmnopqrstuvwxyz", 3, 3);
        let parser = Either::new(two_digits, three_letters);

        // Test two digits
        let mut input1 = Cursor::new(b"12X");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser, &mut source1).unwrap();
        assert_eq!(result1.0, Some(b"12".to_vec()));
        assert_eq!(result1.1, None);

        // Test three letters
        let two_digits2 = Class::with_bounds(b"0123456789", 2, 2);
        let three_letters2 = Class::with_bounds(b"abcdefghijklmnopqrstuvwxyz", 3, 3);
        let parser2 = Either::new(two_digits2, three_letters2);

        let mut input2 = Cursor::new(b"abc1");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        assert_eq!(result2.0, None);
        assert_eq!(result2.1, Some(b"abc".to_vec()));
    }

    #[test]
    fn test_either_failure_modes() {
        use crate::parser::parse;

        // Test when both alternatives fail
        let parser = Either::new(Literal::from_str("hello"), Literal::from_str("world"));

        let mut input = Cursor::new(b"goodbye");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source);
        assert!(matches!(result, Err(Error::NoMatch)));

        // Verify position wasn't advanced
        let first_byte = source.peek1().unwrap();
        assert_eq!(first_byte, b'g');
    }

    #[test]
    fn test_either_backtracking_behavior() {
        use crate::{class::Class, parser::parse};

        // First parser consumes some input then fails, second should still work
        let digits_then_alpha = crate::sequence::Sequence::new(Class::digits(), Class::alpha());
        let just_alpha = Class::alpha();
        let parser = Either::new(digits_then_alpha, just_alpha);

        // Input has only letters, first parser should fail after consuming digits
        let mut input = Cursor::new(b"abcdef");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result.0, None);
        assert_eq!(result.1, Some(b"abcdef".to_vec()));
    }

    #[test]
    fn test_either_cache_interaction() {
        use crate::parser::parse;

        // Test that Either works correctly with caching
        let parser1 = Either::new(Literal::from_str("test"), Literal::from_str("demo"));
        let parser2 = Either::new(Literal::from_str("test"), Literal::from_str("demo"));

        // Parse first time
        let mut input1 = Cursor::new(b"testXYZ");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser1, &mut source1).unwrap();
        assert_eq!(result1.0, Some(b"test".as_slice().into()));

        // Parse with different input at different position - should work correctly
        let mut input2 = Cursor::new(b"demoXYZ");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        // Either parser can match either alternative, test that we get a valid result
        assert!(result2.0.is_some() || result2.1.is_some());
    }

    #[test]
    fn test_oneof_macro_single() {
        use crate::{oneof, parser::parse};

        let parser = oneof![Literal::from_str("hello")];

        let mut input = Cursor::new(b"hello");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result, b"hello".as_slice().into());
    }

    #[test]
    fn test_oneof_macro_two() {
        use crate::{oneof, parser::parse};

        let parser = oneof![Literal::from_str("hello"), Literal::from_str("world")];

        // Test first alternative
        let mut input1 = Cursor::new(b"hello");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser, &mut source1).unwrap();
        assert_eq!(result1.0, Some(b"hello".as_slice().into()));
        assert_eq!(result1.1, None);

        // Test second alternative
        let parser2 = oneof![Literal::from_str("hello"), Literal::from_str("world")];

        let mut input2 = Cursor::new(b"world");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        assert_eq!(result2.0, None);
        assert_eq!(result2.1, Some(b"world".as_slice().into()));
    }

    #[test]
    fn test_oneof_macro_three() {
        use crate::{oneof, parser::parse};

        let parser = oneof![
            Literal::from_str("alpha"),
            Literal::from_str("beta"),
            Literal::from_str("gamma")
        ];

        // Test first alternative
        let mut input1 = Cursor::new(b"alpha");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser, &mut source1).unwrap();
        assert_eq!(result1.0, Some(b"alpha".as_slice().into()));
        assert_eq!(result1.1, None);

        // Test second alternative (nested in right side)
        let parser2 = oneof![
            Literal::from_str("alpha"),
            Literal::from_str("beta"),
            Literal::from_str("gamma")
        ];

        let mut input2 = Cursor::new(b"beta");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        assert_eq!(result2.0, None);
        assert!(result2.1.is_some());
        if let Some(inner_result) = result2.1 {
            assert_eq!(inner_result.0, Some(b"beta".as_slice().into()));
            assert_eq!(inner_result.1, None);
        }

        // Test third alternative
        let parser3 = oneof![
            Literal::from_str("alpha"),
            Literal::from_str("beta"),
            Literal::from_str("gamma")
        ];

        let mut input3 = Cursor::new(b"gamma");
        let mut source3 = crate::parser::Source::new(&mut input3);

        let result3 = parse(parser3, &mut source3).unwrap();
        assert_eq!(result3.0, None);
        assert!(result3.1.is_some());
        if let Some(inner_result) = result3.1 {
            assert_eq!(inner_result.0, None);
            assert_eq!(inner_result.1, Some(b"gamma".as_slice().into()));
        }
    }

    #[test]
    fn test_oneof_macro_four() {
        use crate::{oneof, parser::parse};

        // Test each alternative
        let test_cases = vec![
            ("alpha", "first"),
            ("beta", "second"),
            ("gamma", "third"),
            ("delta", "fourth"),
        ];

        for (input_str, _description) in test_cases {
            let parser = oneof![
                Literal::from_str("alpha"),
                Literal::from_str("beta"),
                Literal::from_str("gamma"),
                Literal::from_str("delta")
            ];

            let mut input = Cursor::new(input_str.as_bytes());
            let mut source = crate::parser::Source::new(&mut input);

            let result = parse(parser, &mut source);
            assert!(result.is_ok());
        }
    }

    #[test]
    fn test_oneof_macro_with_trailing_comma() {
        use crate::{oneof, parser::parse};

        let parser = oneof![Literal::from_str("hello"), Literal::from_str("world"),];

        let mut input = Cursor::new(b"hello");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source).unwrap();
        assert_eq!(result.0, Some(b"hello".as_slice().into()));
        assert_eq!(result.1, None);
    }

    #[test]
    fn test_oneof_macro_different_types() {
        use crate::{class::Class, oneof, parser::parse};

        let parser = oneof![Literal::from_str("prefix"), Class::digits(), Class::alpha()];

        // Test literal
        let mut input1 = Cursor::new(b"prefix");
        let mut source1 = crate::parser::Source::new(&mut input1);

        let result1 = parse(parser, &mut source1).unwrap();
        assert_eq!(result1.0, Some(b"prefix".as_slice().into()));
        assert_eq!(result1.1, None);

        // Test digits
        let parser2 = oneof![Literal::from_str("prefix"), Class::digits(), Class::alpha()];

        let mut input2 = Cursor::new(b"123");
        let mut source2 = crate::parser::Source::new(&mut input2);

        let result2 = parse(parser2, &mut source2).unwrap();
        assert_eq!(result2.0, None);
        assert!(result2.1.is_some());
        if let Some(inner_result) = result2.1 {
            assert_eq!(inner_result.0, Some(b"123".to_vec()));
            assert_eq!(inner_result.1, None);
        }

        // Test alpha
        let parser3 = oneof![Literal::from_str("prefix"), Class::digits(), Class::alpha()];

        let mut input3 = Cursor::new(b"abc");
        let mut source3 = crate::parser::Source::new(&mut input3);

        let result3 = parse(parser3, &mut source3).unwrap();
        assert_eq!(result3.0, None);
        assert!(result3.1.is_some());
        if let Some(inner_result) = result3.1 {
            assert_eq!(inner_result.0, None);
            assert_eq!(inner_result.1, Some(b"abc".to_vec()));
        }
    }

    #[test]
    fn test_oneof_macro_failure() {
        use crate::{oneof, parser::parse};

        let parser = oneof![
            Literal::from_str("hello"),
            Literal::from_str("world"),
            Literal::from_str("test")
        ];

        let mut input = Cursor::new(b"goodbye");
        let mut source = crate::parser::Source::new(&mut input);

        let result = parse(parser, &mut source);
        assert!(matches!(result, Err(crate::result::Error::NoMatch)));
    }
}