use crate::{
cache::ParsingCache,
parser::{Parsable, Parser, Source},
result::{Error, ParseResult},
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EndOfFile;
impl EndOfFile {
pub fn new() -> Self {
Self
}
}
impl Default for EndOfFile {
fn default() -> Self {
Self::new()
}
}
impl<Ctx> Parser<Ctx> for EndOfFile {
type Output = ();
fn read<S>(
&self,
source: &mut Source<S>,
_cache: &mut impl ParsingCache,
_context: &mut Ctx,
) -> ParseResult<Self::Output>
where
S: Parsable,
{
match source.peek1() {
Err(Error::NoMatch) => Ok(()), Ok(_) => Err(Error::NoMatch), Err(other_error) => Err(other_error), }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{literal::Literal, parser::parse, seq};
use std::io::Cursor;
#[test]
fn test_eof_on_empty_input() {
let eof_parser = EndOfFile::new();
let mut input = Cursor::new(b"");
let mut source = Source::new(&mut input);
let result = parse(eof_parser, &mut source);
assert!(result.is_ok());
}
#[test]
fn test_eof_fails_on_non_empty_input() {
let eof_parser = EndOfFile::new();
let mut input = Cursor::new(b"a");
let mut source = Source::new(&mut input);
let result = parse(eof_parser, &mut source);
assert!(result.is_err());
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_eof_fails_on_whitespace() {
let eof_parser = EndOfFile::new();
let mut input = Cursor::new(b" ");
let mut source = Source::new(&mut input);
let result = parse(eof_parser, &mut source);
assert!(result.is_err());
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_eof_with_sequence_success() {
let parser = seq![Literal::from_str("hello"), EndOfFile::new()];
let mut input = Cursor::new(b"hello");
let mut source = Source::new(&mut input);
let result = parse(parser, &mut source);
assert!(result.is_ok());
}
#[test]
fn test_eof_with_sequence_failure_trailing_content() {
let parser = seq![Literal::from_str("hello"), EndOfFile::new()];
let mut input = Cursor::new(b"hello world");
let mut source = Source::new(&mut input);
let result = parse(parser, &mut source);
assert!(result.is_err());
assert!(matches!(result, Err(Error::NoMatch)));
}
#[test]
fn test_eof_with_sequence_failure_incomplete() {
let parser = seq![Literal::from_str("hello"), EndOfFile::new()];
let mut input = Cursor::new(b"hel");
let mut source = Source::new(&mut input);
let result = parse(parser, &mut source);
assert!(result.is_err());
}
#[test]
fn test_eof_id_consistency() {
let eof1 = EndOfFile::new();
let eof2 = EndOfFile::new();
assert_eq!(
<EndOfFile as Parser<()>>::id(&eof1),
<EndOfFile as Parser<()>>::id(&eof2)
);
}
#[test]
fn test_eof_default() {
let eof_default = EndOfFile;
let eof_new = EndOfFile::new();
assert_eq!(
<EndOfFile as Parser<()>>::id(&eof_default),
<EndOfFile as Parser<()>>::id(&eof_new)
);
}
}