rust-bakery / nom

Rust parser combinator framework
MIT License
9.47k stars 806 forks source link

ExtendInto<Extender=Vec<u8>> appears to have no useful implementors #1206

Open ExpHP opened 4 years ago

ExpHP commented 4 years ago

It is unclear to me how to use bytes::complete::escape_transform on bytestrings, because the only implementors of ExtendInto<Extender=Vec<u8>> are [u8] and &[u8], neither of which can be returned without borrowing from the input.

Test case

use nom::{
    bytes::complete::{escaped_transform, take, is_not},
    combinator::{map},
};

fn main() {
    let res: nom::IResult<_, _> = escaped_transform(  // Error: ExtendInto is not implemented for u8
        is_not(r#"\""#),
        '\\',
        map(take(1u32), |bytes: &[u8]| match bytes[0] {
            b'n' => b'\n',
            b => b,
        }),
    )(b"sfj\\n\\isoeg");
    assert_eq!(res, Ok((&b""[..], b"sfj\nisoeg".to_vec())))
}
Geal commented 4 years ago

you could replace the closure like this:

|bytes: &[u8]| match bytes[0] {
            b'n' => &b"\n"[..],
            _ => &bytes[..1],
}
ExpHP commented 4 years ago

Okay, this is true, you can use static references if there are only a limited number of escapes.

Is there any particular reason why u8 and Vec<u8> do not implement the trait? They would provide additional power by allowing the values to be constructed at runtime, making it easier to support escapes like "\xXX" for an arbitrary byte. (I think this can be done with static refs but it's a bit janky, as it requires having a static string with all byte values like b"\x00\x01\x02\x03...\xfe\xff" to take slices from)