Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse trait #46

Open
Luro02 opened this issue Feb 28, 2020 · 0 comments
Open

Parse trait #46

Luro02 opened this issue Feb 28, 2020 · 0 comments
Assignees
Labels
Milestone

Comments

@Luro02
Copy link
Collaborator

Luro02 commented Feb 28, 2020

Right now this crate uses FromStr, but with #45 it might be better to use a custom trait, which has better support for parsing (the data will be consumed) and it would allow creating custom spans (without having to worry about indexing strings).

I think of something like this (inspired by syn):

pub trait Parse<'a> {
    type Error;

    fn parse(input: Cursor<'a>) -> Result<Self, Self::Error>;

    /// Returns how many chars will be consumed when parsing, if this is known.
    fn consumes() -> Option<usize> { None }
}

struct Cursor<'a> {
    buffer: &'a str,
    position: usize,
}

impl Cursor<'a> {
    pub fn take(&mut self, n: usize) -> Result<&str, Error> {
        self.position += n;
        self.peek(n)
    }

    pub fn peek(&self, n: usize) -> Result<&str, Error> {
        self.buffer.get(self.position..self.position+n).ok_or_else(|| Error::unexpected_eof(n))
    }

    pub fn tag<T: AsRef<str>>(&self, expected: T) -> Result<(), Error> {
        let tag = buffer.take()?;

        if expected.as_ref() == tag {
            Ok(())
        } else {
            Err(Error::mismatched_tag(expected.as_ref(), tag))
        }
    }
}

The nice thing is that with the above approach one could make the Cursor generic over different kind of inputs (not limited to &str):

use std::marker::PhantomData;

struct Cursor<'a, T = &'a str> {
    buffer: T,
    position: usize,
    _p: PhantomData<&'a T>,
}
@Luro02 Luro02 added this to the 0.4 milestone Feb 28, 2020
@Luro02 Luro02 self-assigned this Feb 28, 2020
@Luro02 Luro02 added the T-RFC label Feb 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant