xod 1.0.1

A tiny REPL for bitwise arithmetic and expression evaluation.
Documentation
use super::Span;
use nom::{
    IResult, Parser,
    bytes::complete::tag,
    character::streaming::multispace0,
    sequence::{delimited, preceded, terminated},
};

pub fn space_around<'a, P, O>(
    input: P,
) -> impl Parser<Span<'a>, Output = O, Error = nom::error::Error<Span<'a>>>
where
    P: Parser<Span<'a>, Output = O, Error = nom::error::Error<Span<'a>>>,
{
    delimited(opt_multispace0, input, opt_multispace0)
}

pub fn opt_multispace0(input: Span) -> IResult<Span, ()> {
    let input = match (multispace0).parse_complete(input) {
        Ok((input, _)) => input,
        Err(e) => match e {
            nom::Err::Incomplete(_) => input,
            nom::Err::Error(_) => input,
            nom::Err::Failure(_) => return Err(e),
        },
    };
    Ok((input, ()))
}

#[inline(always)]
pub fn open_bracket(input: Span) -> IResult<Span, Span> {
    terminated(tag("["), opt_multispace0).parse_complete(input)
}

#[inline(always)]
pub fn close_bracket(input: Span) -> IResult<Span, Span> {
    preceded(opt_multispace0, tag("]")).parse_complete(input)
}

#[inline(always)]
pub fn open_paren(input: Span) -> IResult<Span, Span> {
    terminated(tag("("), opt_multispace0).parse_complete(input)
}

#[inline(always)]
pub fn close_paren(input: Span) -> IResult<Span, Span> {
    preceded(opt_multispace0, tag(")")).parse_complete(input)
}

#[inline(always)]
pub fn open_brace(input: Span) -> IResult<Span, Span> {
    space_around(tag("{")).parse_complete(input)
}

#[inline(always)]
pub fn close_brace(input: Span) -> IResult<Span, Span> {
    space_around(tag("}")).parse_complete(input)
}

#[inline(always)]
pub fn comma(input: Span) -> IResult<Span, Span> {
    terminated(tag(","), opt_multispace0).parse_complete(input)
}

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

    #[test]
    fn test_brackets() {
        let input = Span::new("[ ]");
        let result1 = (open_bracket).parse_complete(input);
        eprintln!("{:?}", result1);
        assert!(result1.is_ok());
        let (input, result1) = result1.unwrap();
        let result2 = (close_bracket).parse_complete(input);
        eprintln!("{:?}", result2);
        assert!(result2.is_ok());
        let (_, result2) = result2.unwrap();
        unsafe {
            assert_eq!(result1, Span::new_from_raw_offset(0, 1, "[", ()));
            assert_eq!(result2, Span::new_from_raw_offset(2, 1, "]", ()))
        }
    }

    #[test]
    fn test_braces() {
        let input = Span::new("{ }");
        let result1 = (open_brace).parse_complete(input);
        eprintln!("{:?}", result1);
        assert!(result1.is_ok());
        let (input, result1) = result1.unwrap();
        let result2 = (close_brace).parse_complete(input);
        eprintln!("{:?}", result2);
        assert!(result2.is_ok());
        let (_, result2) = result2.unwrap();
        unsafe {
            assert_eq!(result1, Span::new_from_raw_offset(0, 1, "{", ()));
            assert_eq!(result2, Span::new_from_raw_offset(2, 1, "}", ()))
        }
    }

    #[test]
    fn test_parentheses() {
        let input = Span::new("( )");
        let result1 = (open_paren).parse_complete(input);
        eprintln!("{:?}", result1);
        assert!(result1.is_ok());
        let (input, result1) = result1.unwrap();
        let result2 = (close_paren).parse_complete(input);
        eprintln!("{:?}", result2);
        assert!(result2.is_ok());
        let (_, result2) = result2.unwrap();
        unsafe {
            assert_eq!(result1, Span::new_from_raw_offset(0, 1, "(", ()));
            assert_eq!(result2, Span::new_from_raw_offset(2, 1, ")", ()))
        }
    }
}