separate out the line/column counting from character iteration
This commit is contained in:
parent
195f7380b5
commit
c37f67b0a1
46
src/iterator.rs
Normal file
46
src/iterator.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use std::iter::Peekable;
|
||||
use std::io;
|
||||
|
||||
pub struct LineColIterator<Iter: Iterator<Item=io::Result<u8>>> {
|
||||
rdr: Peekable<Iter>,
|
||||
line: usize,
|
||||
col: usize,
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=io::Result<u8>>> LineColIterator<Iter> {
|
||||
pub fn new(iter: Iter) -> LineColIterator<Iter> {
|
||||
LineColIterator {
|
||||
line: 1,
|
||||
col: 0,
|
||||
rdr: iter.peekable(),
|
||||
}
|
||||
}
|
||||
fn peek(&mut self) -> Option<u8> {
|
||||
match self.rdr.peek() {
|
||||
None => None,
|
||||
Some(&Ok(c)) => Some(c),
|
||||
Some(&Err(_)) => None,
|
||||
}
|
||||
}
|
||||
pub fn line(&self) -> usize { self.line }
|
||||
pub fn col(&self) -> usize { self.col }
|
||||
}
|
||||
|
||||
impl<Iter: Iterator<Item=io::Result<u8>>> Iterator for LineColIterator<Iter> {
|
||||
type Item = io::Result<u8>;
|
||||
fn next(&mut self) -> Option<io::Result<u8>> {
|
||||
match self.rdr.next() {
|
||||
None => None,
|
||||
Some(Ok(b'\n')) => {
|
||||
self.line += 1;
|
||||
self.col = 0;
|
||||
Some(Ok(b'\n'))
|
||||
},
|
||||
Some(Ok(c)) => {
|
||||
self.col += 1;
|
||||
Some(Ok(c))
|
||||
},
|
||||
Some(Err(e)) => Some(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
@ -4,12 +4,11 @@ use std::str;
|
||||
|
||||
use de;
|
||||
use super::error::{Error, ErrorCode};
|
||||
use iterator::LineColIterator;
|
||||
|
||||
pub struct Deserializer<Iter> {
|
||||
rdr: Iter,
|
||||
pub struct Deserializer<Iter: Iterator<Item=io::Result<u8>>> {
|
||||
rdr: LineColIterator<Iter>,
|
||||
ch: Option<u8>,
|
||||
line: usize,
|
||||
col: usize,
|
||||
str_buf: Vec<u8>,
|
||||
}
|
||||
|
||||
@ -20,10 +19,8 @@ impl<Iter> Deserializer<Iter>
|
||||
#[inline]
|
||||
pub fn new(rdr: Iter) -> Result<Deserializer<Iter>, Error> {
|
||||
let mut deserializer = Deserializer {
|
||||
rdr: rdr,
|
||||
rdr: LineColIterator::new(rdr),
|
||||
ch: None,
|
||||
line: 1,
|
||||
col: 0,
|
||||
str_buf: Vec::with_capacity(128),
|
||||
};
|
||||
|
||||
@ -53,13 +50,6 @@ impl<Iter> Deserializer<Iter>
|
||||
None => None,
|
||||
};
|
||||
|
||||
if self.ch_is(b'\n') {
|
||||
self.line += 1;
|
||||
self.col = 1;
|
||||
} else {
|
||||
self.col += 1;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -73,7 +63,7 @@ impl<Iter> Deserializer<Iter>
|
||||
}
|
||||
|
||||
fn error(&mut self, reason: ErrorCode) -> Error {
|
||||
Error::SyntaxError(reason, self.line, self.col)
|
||||
Error::SyntaxError(reason, self.rdr.line(), self.rdr.col())
|
||||
}
|
||||
|
||||
fn parse_whitespace(&mut self) -> Result<(), Error> {
|
||||
@ -476,12 +466,12 @@ impl<Iter> de::Deserializer for Deserializer<Iter>
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqVisitor<'a, Iter: 'a> {
|
||||
struct SeqVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
|
||||
de: &'a mut Deserializer<Iter>,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a, Iter> SeqVisitor<'a, Iter> {
|
||||
impl<'a, Iter: Iterator<Item=io::Result<u8>>> SeqVisitor<'a, Iter> {
|
||||
fn new(de: &'a mut Deserializer<Iter>) -> Self {
|
||||
SeqVisitor {
|
||||
de: de,
|
||||
@ -533,12 +523,12 @@ impl<'a, Iter> de::SeqVisitor for SeqVisitor<'a, Iter>
|
||||
}
|
||||
}
|
||||
|
||||
struct MapVisitor<'a, Iter: 'a> {
|
||||
struct MapVisitor<'a, Iter: 'a + Iterator<Item=io::Result<u8>>> {
|
||||
de: &'a mut Deserializer<Iter>,
|
||||
first: bool,
|
||||
}
|
||||
|
||||
impl<'a, Iter> MapVisitor<'a, Iter> {
|
||||
impl<'a, Iter: Iterator<Item=io::Result<u8>>> MapVisitor<'a, Iter> {
|
||||
fn new(de: &'a mut Deserializer<Iter>) -> Self {
|
||||
MapVisitor {
|
||||
de: de,
|
||||
|
@ -16,3 +16,4 @@ pub mod ser;
|
||||
pub mod de;
|
||||
pub mod json;
|
||||
pub mod bytes;
|
||||
mod iterator;
|
||||
|
@ -668,8 +668,8 @@ fn test_parse_err<T>(errors: Vec<(&'static str, Error)>)
|
||||
#[test]
|
||||
fn test_parse_null() {
|
||||
test_parse_err::<()>(vec![
|
||||
("n", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
|
||||
("nul", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
|
||||
("n", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 1)),
|
||||
("nul", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 3)),
|
||||
("nulla", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
|
||||
]);
|
||||
|
||||
@ -681,9 +681,9 @@ fn test_parse_null() {
|
||||
#[test]
|
||||
fn test_parse_bool() {
|
||||
test_parse_err::<bool>(vec![
|
||||
("t", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
|
||||
("t", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 1)),
|
||||
("truz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 4)),
|
||||
("f", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 2)),
|
||||
("f", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 1)),
|
||||
("faz", Error::SyntaxError(ErrorCode::ExpectedSomeIdent, 1, 3)),
|
||||
("truea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 5)),
|
||||
("falsea", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
|
||||
@ -702,11 +702,11 @@ fn test_parse_number_errors() {
|
||||
test_parse_err::<f64>(vec![
|
||||
("+", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
||||
(".", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
||||
("-", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||
("-", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 1)),
|
||||
("00", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||
("1.", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
||||
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
||||
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 4)),
|
||||
("1.", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||
("1e", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 2)),
|
||||
("1e+", Error::SyntaxError(ErrorCode::InvalidNumber, 1, 3)),
|
||||
("1a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 2)),
|
||||
]);
|
||||
}
|
||||
@ -745,8 +745,8 @@ fn test_parse_f64() {
|
||||
#[test]
|
||||
fn test_parse_string() {
|
||||
test_parse_err::<String>(vec![
|
||||
("\"", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 2)),
|
||||
("\"lol", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 5)),
|
||||
("\"", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 1)),
|
||||
("\"lol", Error::SyntaxError(ErrorCode::EOFWhileParsingString, 1, 4)),
|
||||
("\"lol\"a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 6)),
|
||||
]);
|
||||
|
||||
@ -767,10 +767,10 @@ fn test_parse_string() {
|
||||
#[test]
|
||||
fn test_parse_list() {
|
||||
test_parse_err::<Vec<f64>>(vec![
|
||||
("[", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 1)),
|
||||
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
|
||||
("[ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
||||
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 3)),
|
||||
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 4)),
|
||||
("[1", Error::SyntaxError(ErrorCode::EOFWhileParsingList, 1, 2)),
|
||||
("[1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
||||
("[1,]", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 4)),
|
||||
("[1 2]", Error::SyntaxError(ErrorCode::ExpectedListCommaOrEnd, 1, 4)),
|
||||
("[]a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
|
||||
@ -819,17 +819,17 @@ fn test_parse_list() {
|
||||
#[test]
|
||||
fn test_parse_object() {
|
||||
test_parse_err::<BTreeMap<String, u32>>(vec![
|
||||
("{", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 1)),
|
||||
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 2)),
|
||||
("{ ", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 3)),
|
||||
("{1", Error::SyntaxError(ErrorCode::KeyMustBeAString, 1, 2)),
|
||||
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
|
||||
("{ \"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
|
||||
("{\"a\" ", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
|
||||
("{\"a\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 4)),
|
||||
("{\"a\" ", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 5)),
|
||||
("{\"a\" 1", Error::SyntaxError(ErrorCode::ExpectedColon, 1, 6)),
|
||||
("{\"a\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 6)),
|
||||
("{\"a\":1", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 7)),
|
||||
("{\"a\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 5)),
|
||||
("{\"a\":1", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 1, 6)),
|
||||
("{\"a\":1 1", Error::SyntaxError(ErrorCode::ExpectedObjectCommaOrEnd, 1, 8)),
|
||||
("{\"a\":1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 8)),
|
||||
("{\"a\":1,", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 7)),
|
||||
("{}a", Error::SyntaxError(ErrorCode::TrailingCharacters, 1, 3)),
|
||||
]);
|
||||
|
||||
@ -870,8 +870,8 @@ fn test_parse_object() {
|
||||
#[test]
|
||||
fn test_parse_struct() {
|
||||
test_parse_err::<Outer>(vec![
|
||||
("5", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 2)),
|
||||
("\"hello\"", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
|
||||
("5", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 1)),
|
||||
("\"hello\"", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 7)),
|
||||
("{\"inner\": true}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 15)),
|
||||
]);
|
||||
|
||||
@ -933,7 +933,7 @@ fn test_parse_option() {
|
||||
fn test_parse_enum_errors() {
|
||||
test_parse_err::<Animal>(vec![
|
||||
("{}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 2)),
|
||||
("{\"Dog\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 8)),
|
||||
("{\"Dog\":", Error::SyntaxError(ErrorCode::EOFWhileParsingValue, 1, 7)),
|
||||
("{\"Dog\":}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 8)),
|
||||
("{\"unknown\":[]}", Error::SyntaxError(ErrorCode::UnknownField("unknown".to_string()), 1, 11)),
|
||||
("{\"Dog\":{}}", Error::SyntaxError(ErrorCode::ExpectedSomeValue, 1, 9)),
|
||||
@ -994,7 +994,7 @@ fn test_parse_trailing_whitespace() {
|
||||
#[test]
|
||||
fn test_multiline_errors() {
|
||||
test_parse_err::<BTreeMap<String, String>>(vec![
|
||||
("{\n \"foo\":\n \"bar\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 3, 8)),
|
||||
("{\n \"foo\":\n \"bar\"", Error::SyntaxError(ErrorCode::EOFWhileParsingObject, 3, 6)),
|
||||
]);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user