use crate::error::{JsonError, Position};
use crate::input::Input;
use crate::mask::{self, Mask};
use crate::raw_token::RawToken;
use crate::scan::Scanner;
use crate::structure::JsonStructure;
use crate::token::Token;
use std::io::{self, Read};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Format {
Regular,
Concatenated,
}
impl Default for Format {
fn default() -> Self {
Self::Regular
}
}
#[derive(Debug, Clone)]
pub struct TokenReader<R, M> {
input: R,
mask: M,
format: Format,
}
impl<R: Read> TokenReader<R, mask::All> {
pub fn new(input: R) -> Self {
Self {
mask: mask::All,
input,
format: Format::default(),
}
}
}
impl<R: Read, M: Mask> TokenReader<R, M> {
pub fn with_mask<N: Mask>(self, mask: N) -> TokenReader<R, N> {
TokenReader {
input: self.input,
mask,
format: self.format,
}
}
pub fn with_format(mut self, format: Format) -> Self {
self.format = format;
self
}
}
impl<R: Read, M: Mask> IntoIterator for TokenReader<R, M> {
type Item = Result<Token, JsonError>;
type IntoIter = Tokens<R, M>;
fn into_iter(self) -> Self::IntoIter {
Tokens {
input: Input::new(self.input),
structure: JsonStructure::new(self.format),
mask: self.mask,
scanner: Scanner::new(),
failure: None,
}
}
}
#[derive(Debug)]
pub struct Tokens<R, M> {
failure: Option<JsonError>,
structure: JsonStructure,
scanner: Scanner,
input: Input<R>,
mask: M,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DryRun {
pub token_count: usize,
pub selected_token_count: usize,
}
impl<R: io::Read, M: Mask> Tokens<R, M> {
pub fn error(&self) -> Option<JsonError> {
self.failure
}
pub fn dry_run(&mut self) -> Result<DryRun, JsonError> {
if let Some(err) = self.failure {
return Err(err);
}
let mut counter = DryRun {
token_count: 0,
selected_token_count: 0,
};
loop {
let raw_token = self
.scanner
.read_token(&mut self.input)
.and_then(|t| self.structure.validate(t));
match raw_token {
Ok(RawToken::Eof) => return Ok(counter),
Ok(t) => {
counter.token_count += 1;
if self.mask.match_token(&t) {
counter.selected_token_count += 1;
}
}
Err(reason) => {
let position = self.input.position();
let e = JsonError { position, reason };
self.failure = Some(e);
return Err(e);
}
};
}
}
}
impl<R: io::Seek, M: Mask> Tokens<R, M> {
pub fn reset(&mut self) -> Result<(), JsonError> {
if let Some(err) = self.failure {
return Err(err);
}
self.input.reset().map_err(|reason| JsonError {
position: Position::default(),
reason,
})?;
self.structure.reset();
self.scanner.reset();
Ok(())
}
}
impl<R: io::Read, M: Mask> Iterator for Tokens<R, M> {
type Item = Result<Token, JsonError>;
fn next(&mut self) -> Option<Self::Item> {
if self.failure.is_some() {
return None;
}
loop {
let raw_token = self
.scanner
.read_token(&mut self.input)
.and_then(|t| self.structure.validate(t));
match raw_token {
Ok(RawToken::Eof) => return None,
Ok(t) => {
if self.mask.match_token(&t) {
return Some(Ok(Token::from(t)));
}
}
Err(reason) => {
let position = self.input.position();
let e = JsonError { position, reason };
self.failure = Some(e);
return Some(Err(e));
}
};
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{JsonError, Reason};
use std::io::Cursor;
#[test]
fn returns_none_after_failure() {
let cursor = Cursor::new("01");
let mut iter = TokenReader::new(cursor).into_iter();
let expected = JsonError {
position: Position {
offset: 1,
line: 1,
col: 2,
},
reason: Reason::ExpectedNumber,
};
assert_eq!(iter.next(), Some(Err(expected)));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.dry_run(), Err(expected));
assert_eq!(iter.reset(), Err(expected));
}
}