rust-bakery / nom

Rust parser combinator framework
MIT License
9.18k stars 792 forks source link

take_while_m_n don't correctly work with custom types #1686

Open Dangerise opened 10 months ago

Dangerise commented 10 months ago

I implemented the traits that nom requires for Tokens what wraps a slice reference , Usually , the functions of nom return like (rest_of_the_input , result) In the code blow , I expected the return values of wrap a to be empty and b got something , like the return values of wrap2, but things didn't happened like that .

The output

I expected `a` to be empty and `b` has element Variant .
[src\main.rs:27] a = Tokens {
    tok: [
        Variant,
    ],
}
[src\main.rs:27] b = Tokens {
    tok: [],
}

The type &str works well
[src\main.rs:30] a = ""
[src\main.rs:30] b = "1"
#[derive(Debug, Clone, Copy)]
pub enum Token {
    Variant,
}

#[derive(Debug)]
pub struct Tokens<'a> {
    tok: &'a [Token],
}

use nom::bytes::complete::take_while_m_n;

fn wrap(tokens: Tokens) -> IResult<Tokens, Tokens> {
    take_while_m_n(1, 1, |_| true)(tokens)
}

fn wrap2(s: &str) -> IResult<&str, &str> {
    take_while_m_n(1, 1, |_| true)(s)
}

fn main() {
    let slice = &[Token::Variant];
    let tokens = Tokens {
        tok: slice as &[Token],
    };
    let (a, b) = wrap(tokens).unwrap();
    dbg!(a, b);

    let (a, b) = wrap2("1").unwrap();
    dbg!(a, b);
}

impl<'a> From<&'a [Token]> for Tokens<'a> {
    fn from(tok: &'a [Token]) -> Self {
        Self { tok }
    }
}
impl<'a> From<&'a Vec<Token>> for Tokens<'a> {
    fn from(value: &'a Vec<Token>) -> Self {
        Self {
            tok: value.as_slice(),
        }
    }
}

impl<'a> std::ops::Deref for Tokens<'a> {
    type Target = &'a [Token];
    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.tok
    }
}

impl<'a> std::ops::DerefMut for Tokens<'a> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.tok
    }
}

use nom::*;

impl InputLength for Token {
    fn input_len(&self) -> usize {
        1
    }
}

impl<'a> InputTake for Tokens<'a> {
    #[inline]
    fn take(&self, count: usize) -> Self {
        Self {
            tok: &self.tok[..count],
        }
    }
    #[inline]
    fn take_split(&self, count: usize) -> (Self, Self) {
        let (prefix, suffix) = self.tok.split_at(count);
        dbg!(prefix, suffix);
        (Self { tok: prefix }, Self { tok: suffix })
    }
}

impl<'a> InputLength for Tokens<'a> {
    fn input_len(&self) -> usize {
        self.tok.len()
    }
}

use std::ops::{Range, RangeFrom, RangeFull, RangeTo};
impl<'a> Slice<Range<usize>> for Tokens<'a> {
    #[inline]
    fn slice(&self, range: Range<usize>) -> Self {
        Tokens {
            tok: self.tok.slice(range.clone()),
        }
    }
}

impl<'a> Slice<RangeTo<usize>> for Tokens<'a> {
    #[inline]
    fn slice(&self, range: RangeTo<usize>) -> Self {
        self.slice(0..range.end)
    }
}

impl<'a> Slice<RangeFrom<usize>> for Tokens<'a> {
    #[inline]
    fn slice(&self, range: RangeFrom<usize>) -> Self {
        self.slice(range.start..self.len());
        panic!()
    }
}

impl<'a> Slice<RangeFull> for Tokens<'a> {
    #[inline]
    fn slice(&self, _: RangeFull) -> Self {
        Tokens { tok: self.tok }
    }
}

use std::iter::Enumerate;
// use std::slice::Iter;
impl<'a> InputIter for Tokens<'a> {
    type Item = &'a Token;
    type Iter = Enumerate<::std::slice::Iter<'a, Token>>;
    type IterElem = ::std::slice::Iter<'a, Token>;

    #[inline]
    fn iter_indices(&self) -> Enumerate<::std::slice::Iter<'a, Token>> {
        self.tok.iter().enumerate()
    }
    #[inline]
    fn iter_elements(&self) -> ::std::slice::Iter<'a, Token> {
        self.tok.iter()
    }
    #[inline]
    fn position<P>(&self, predicate: P) -> Option<usize>
    where
        P: Fn(Self::Item) -> bool,
    {
        self.tok.iter().position(predicate)
    }
    #[inline]
    fn slice_index(&self, count: usize) -> Result<usize, Needed> {
        if self.tok.len() >= count {
            Ok(count)
        } else {
            Err(Needed::Unknown)
        }
    }
}