Search code examples
rustnom

How to emulate take_until_and_consume in nom 5.x?


I've updated my nom dependency from 4.x to 5.x version and found that macro take_until_and_consume is deprecated. Changelog says:

"this can be replaced with take_until combined with take"

but I don't know how to emulate take_until_and_consume with them. Has anyone encountered such a problem with version updating or does anyone know how to do this?

I mean this deprecated macro take_until_and_consume. And these new: take and take_until


Solution

  • I believe this is straiforward but here a generic implementation:

    fn take_until_and_consume<T, I, E>(tag: T) -> impl Fn(I) -> nom::IResult<I, I, E>
    where
        E: nom::error::ParseError<I>,
        I: nom::InputTake
            + nom::FindSubstring<T>
            + nom::Slice<std::ops::RangeFrom<usize>>
            + nom::InputIter<Item = u8>
            + nom::InputLength,
        T: nom::InputLength + Clone,
    {
        use nom::bytes::streaming::take;
        use nom::bytes::streaming::take_until;
        use nom::sequence::terminated;
    
        move |input| terminated(take_until(tag.clone()), take(tag.input_len()))(input)
    }
    
    #[test]
    fn test_take_until_and_consume() {
        let r = take_until_and_consume::<_, _, ()>("foo")(&b"abcd foo efgh"[..]);
        assert_eq!(r, Ok((&b" efgh"[..], &b"abcd "[..])));
    }