use crate::common::{Define, Separator};
use crate::error::{Error, ParseError, Result};
use crate::lines::DefIter;
use crate::parse::{self, Integer, Number};
use serde::de::{
self, Deserialize, DeserializeOwned, DeserializeSeed, MapAccess, SeqAccess,
Visitor,
};
use std::io::Read;
use std::str;
enum TextVal<'a> {
Owned(String),
Borrowed(&'a str),
}
#[derive(Debug)]
enum BranchState {
Visit,
Cleanup,
}
#[derive(Debug)]
struct Branch<'a> {
fields: &'static [&'static str],
visited: Vec<bool>,
state: BranchState,
key: Option<&'a str>,
list: bool,
substitute: Option<&'a str>,
}
impl<'a> Branch<'a> {
fn with_fields(fields: &'static [&'static str]) -> Self {
let visited = vec![false; fields.len()];
Branch {
fields,
visited,
state: BranchState::Visit,
key: None,
list: false,
substitute: None,
}
}
fn new() -> Self {
Branch::with_fields(&[])
}
fn first_field(&self) -> Option<&'a str> {
match self.fields.first() {
Some(field) => Some(*field),
_ => None,
}
}
fn visit(&mut self, key: Option<&'a str>) {
self.key = key;
if let Some(f) = key {
for i in 0..self.fields.len() {
if self.fields[i] == f {
self.visited[i] = true
}
}
}
}
fn has_unvisited(&self) -> bool {
self.visited.iter().any(|v| !v)
}
fn cleanup_visit(&mut self) -> Option<&'static str> {
if let BranchState::Cleanup = self.state {
for i in 0..self.fields.len() {
if !self.visited[i] {
self.visited[i] = true;
return Some(self.fields[i]);
}
}
}
None
}
fn is_substitute(&self) -> bool {
self.key.is_some() && self.key == self.substitute
}
}
struct MappingIter<'a> {
defs: DefIter<'a>,
define: Option<Define<'a>>,
stack: Vec<Branch<'a>>,
}
impl<'a> Iterator for MappingIter<'a> {
type Item = Define<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.define.is_none() {
self.define = self.defs.next();
}
if self.is_list() {
self.next_list()
} else {
self.define.take()
}
}
}
impl<'a> MappingIter<'a> {
fn new(input: &'a str) -> Self {
let defs = DefIter::new(input);
let define = None;
let stack = vec![];
MappingIter {
defs,
define,
stack,
}
}
fn peek(&mut self) -> Result<Option<Define<'a>>> {
if let Some(e) = self.defs.error() {
return Err(Error::FailedParse(e));
}
if self.define.is_none() {
self.define = self.defs.next();
}
Ok(self.define)
}
fn next_list(&mut self) -> Option<Define<'a>> {
if let Some(define) = self.define {
match define.separator {
Separator::Normal => {
let (d0, d1) = define.split_list();
self.define = d1;
Some(d0)
}
_ => {
self.define = None;
Some(define)
}
}
} else {
self.define
}
}
fn push_stack(&mut self, branch: Branch<'a>) {
self.stack.push(branch)
}
fn pop_stack(&mut self) {
self.stack.pop();
}
fn check_substitute(&mut self) -> Result<()> {
let indent = self.stack.len();
if let Some(branch) = self.stack.last_mut() {
if let Some(key) = branch.first_field() {
if let Some(define) = self.define.take() {
if define.value.len() > 0 && indent > 0 {
branch.substitute = Some(key);
self.define = Some(Define::new(
indent - 1,
key,
define.separator,
define.value,
))
}
}
}
}
Ok(())
}
fn check_cleanup(&mut self) -> bool {
if let Some(branch) = self.stack.last_mut() {
branch.state = BranchState::Cleanup;
branch.has_unvisited()
} else {
false
}
}
fn set_key(&mut self, key: Option<&'a str>) {
if let Some(branch) = self.stack.last_mut() {
branch.visit(key)
}
}
fn set_list(&mut self, list: bool) {
if let Some(branch) = self.stack.last_mut() {
branch.list = list;
}
}
fn is_list(&self) -> bool {
match self.stack.last() {
Some(branch) => branch.list,
_ => false,
}
}
fn check_indent(&mut self) -> Result<bool> {
match self.peek()? {
Some(define) => Ok(define.check_indent(self.stack.len())),
None => Ok(false),
}
}
fn check_key(&mut self) -> Result<bool> {
if let Some(branch) = self.stack.last() {
if let Some(k) = branch.key {
if let Some(define) = self.peek()? {
return Ok(define.key == k);
}
}
}
Ok(false)
}
fn is_append(&mut self) -> Result<bool> {
Ok(self.check_indent()? && self.check_key()?)
}
fn is_separator_text_append(&mut self) -> Result<bool> {
match self.peek()? {
Some(define) => Ok(define.separator == Separator::TextAppend),
_ => Ok(false),
}
}
fn is_text_append(&mut self) -> Result<bool> {
Ok(self.is_append()? && self.is_separator_text_append()?)
}
}
pub struct Deserializer<'de> {
mappings: MappingIter<'de>,
}
impl<'de> Deserializer<'de> {
fn from_str(input: &'de str) -> Self {
let mappings = MappingIter::new(input);
Deserializer { mappings }
}
}
pub fn from_str<'a, T>(s: &'a str) -> Result<T>
where
T: Deserialize<'a>,
{
let mut deserializer = Deserializer::from_str(s);
let t = T::deserialize(&mut deserializer)?;
Ok(t)
}
pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<T>
where
T: Deserialize<'a>,
{
from_str(str::from_utf8(v)?)
}
pub fn from_reader<R, T>(mut reader: R) -> Result<T>
where
R: Read,
T: DeserializeOwned,
{
let mut s = String::new();
reader.read_to_string(&mut s)?;
from_str(&s)
}
impl<'de> Deserializer<'de> {
fn define_result(
&self,
define: Option<Define<'de>>,
) -> Result<Define<'de>> {
match define {
Some(define) => Ok(define),
None => match self.mappings.defs.error() {
Some(e) => Err(Error::FailedParse(e)),
None => Err(Error::FailedParse(ParseError::ExpectedMore)),
},
}
}
fn peek_key(&mut self) -> Result<&'de str> {
let def = self.mappings.peek()?;
match self.define_result(def)? {
define => Ok(define.key),
}
}
fn get_value(&mut self) -> Result<&'de str> {
let def = self.mappings.next();
match self.define_result(def)? {
define => Ok(define.value),
}
}
fn parse_text(&mut self) -> Result<TextVal<'de>> {
let val = self.get_value()?;
if self.mappings.is_text_append()? {
let mut value = val.to_string();
while self.mappings.is_text_append()? {
value.push('\n');
value.push_str(self.get_value()?);
}
Ok(TextVal::Owned(value))
} else {
Ok(TextVal::Borrowed(val))
}
}
fn parse_char(&mut self) -> Result<char> {
let text = self.get_value()?;
let mut chars = text.chars();
if let Some(c) = chars.next() {
if chars.next().is_none() {
return Ok(c);
}
}
Err(Error::FailedParse(ParseError::ExpectedChar))
}
fn parse_bool(&mut self) -> Result<bool> {
let value = self.get_value()?;
match value {
"true" => Ok(true),
"false" => Ok(false),
_ => Err(Error::FailedParse(ParseError::ExpectedBool)),
}
}
fn parse_int<T: Integer>(&mut self) -> Result<T> {
let value = self.get_value()?;
if let Some(v) = parse::int(value) {
Ok(v)
} else {
Err(Error::FailedParse(ParseError::ExpectedInt))
}
}
fn parse_number<T: Number>(&mut self) -> Result<T> {
let value = self.get_value()?;
if let Some(v) = parse::number(value) {
Ok(v)
} else {
Err(Error::FailedParse(ParseError::ExpectedNumber))
}
}
}
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if let Some(branch) = self.mappings.stack.last() {
dbg!(&branch.key);
}
Err(Error::FailedParse(ParseError::UnexpectedKey))
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_any(visitor)
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_bool(self.parse_bool()?)
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i8(self.parse_int()?)
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i16(self.parse_int()?)
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i32(self.parse_int()?)
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_i64(self.parse_int()?)
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u8(self.parse_int()?)
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u16(self.parse_int()?)
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u32(self.parse_int()?)
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_u64(self.parse_int()?)
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_f32(self.parse_number()?)
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_f64(self.parse_number()?)
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_char(self.parse_char()?)
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
match self.parse_text()? {
TextVal::Owned(val) => visitor.visit_str(&val),
TextVal::Borrowed(val) => visitor.visit_borrowed_str(&val),
}
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
Err(Error::UnsupportedType("bytes"))
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
Err(Error::UnsupportedType("byte_buf"))
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if let Some(branch) = self.mappings.stack.last() {
if let BranchState::Cleanup = branch.state {
return visitor.visit_none();
}
if branch.is_substitute() {
return Err(Error::FailedParse(ParseError::InvalidSubstitute));
}
}
visitor.visit_some(self)
}
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_unit()
}
fn deserialize_unit_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_unit(visitor)
}
fn deserialize_newtype_struct<V>(
self,
_name: &'static str,
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
visitor.visit_newtype_struct(self)
}
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.mappings.set_list(true);
if let Some(branch) = self.mappings.stack.last() {
if branch.is_substitute() {
return Err(Error::FailedParse(ParseError::InvalidSubstitute));
}
}
visitor.visit_seq(self)
}
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_seq(visitor)
}
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.mappings.push_stack(Branch::new());
visitor.visit_map(self)
}
fn deserialize_struct<V>(
self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.mappings.push_stack(Branch::with_fields(fields));
self.mappings.check_substitute()?;
visitor.visit_map(self)
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
_visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
Err(Error::UnsupportedType("enum"))
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
if let Some(branch) = self.mappings.stack.last_mut() {
if let Some(field) = branch.cleanup_visit() {
return visitor.visit_borrowed_str(field);
}
}
let key = self.peek_key()?;
self.mappings.set_key(Some(key));
visitor.visit_borrowed_str(key)
}
}
impl<'de> SeqAccess<'de> for Deserializer<'de> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: DeserializeSeed<'de>,
{
if self.mappings.is_append()? {
seed.deserialize(&mut *self).map(Some)
} else {
self.mappings.set_list(false);
self.mappings.set_key(None);
Ok(None)
}
}
}
impl<'de> MapAccess<'de> for Deserializer<'de> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
if self.mappings.check_indent()? || self.mappings.check_cleanup() {
seed.deserialize(&mut *self).map(Some)
} else {
self.mappings.pop_stack();
Ok(None)
}
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
seed.deserialize(&mut *self)
}
}
#[cfg(test)]
mod test {
use super::super::datetime::*;
use super::{from_str, Error, ParseError};
use serde::Deserialize;
#[derive(Deserialize, PartialEq, Debug)]
struct A {
b: bool,
uint: u32,
int: i32,
}
#[test]
fn integers() -> Result<(), Box<Error>> {
let a = "b: false\nuint: 7\nint: -5\n";
let expected = A {
b: false,
uint: 7,
int: -5,
};
assert_eq!(expected, from_str(a)?);
let a = "b: true\nuint: xF00D\nint: b1111_0000_1111\n";
let expected = A {
b: true,
uint: 0xF00D,
int: 0xF0F,
};
assert_eq!(expected, from_str(a)?);
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct B {
flags: Vec<bool>,
values: Vec<String>,
ints: [i16; 3],
}
#[test]
fn lists() -> Result<(), Box<Error>> {
let b =
"flags: false true true false\nvalues: Hello World\nints: 1 2 -5\n";
let expected = B {
flags: vec![false, true, true, false],
values: vec!["Hello".to_string(), "World".to_string()],
ints: [1, 2, -5],
};
assert_eq!(expected, from_str(b)?);
let b = "flags: true true\nflags: false false\nints: 30 -25 0\n";
let expected = B {
flags: vec![true, true, false, false],
values: vec![],
ints: [30, -25, 0],
};
assert_eq!(expected, from_str(b)?);
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct C {
float: f32,
double: f64,
}
#[test]
fn numbers() -> Result<(), Box<Error>> {
let c = "float: +3.14159\ndouble: -123.456789e0\n";
let expected = C {
float: 3.14159,
double: -123.456789,
};
assert_eq!(expected, from_str(c)?);
let c = "float: 1e15\ndouble: inf\n";
let expected = C {
float: 1e15,
double: std::f64::INFINITY,
};
assert_eq!(expected, from_str(c)?);
let c = "float: 8_765.432_1\ndouble: -inf\n";
let expected = C {
float: 8_765.432_1,
double: std::f64::NEG_INFINITY,
};
assert_eq!(expected, from_str(c)?);
let c = "float: 123_.456\ndouble: 1.0\n";
assert!(from_str::<C>(c).is_err());
let c = "float: _123.456\ndouble: 1.0\n";
assert!(from_str::<C>(c).is_err());
let c = "float: 123.456_\ndouble: 1.0\n";
assert!(from_str::<C>(c).is_err());
let c = "float: 123.456\ndouble: 1__0.0\n";
assert!(from_str::<C>(c).is_err());
let c = "float: .123_456\ndouble: 1.0\n";
assert!(from_str::<C>(c).is_err());
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct D {
struct_e: E,
}
#[derive(Deserialize, PartialEq, Debug)]
struct E {
struct_f: F,
flag: bool,
}
#[derive(Deserialize, PartialEq, Debug)]
struct F {
int: i64,
}
#[test]
fn nesting() -> Result<(), Box<Error>> {
let d = D {
struct_e: {
E {
struct_f: F { int: 321 },
flag: false,
}
},
};
assert_eq!(
d,
from_str("struct_e:\n struct_f:\n int: 321\n flag: false\n")?
);
assert_eq!(
d,
from_str("struct_e:\n flag: false\n struct_f:\n int: 321\n")?
);
match from_str::<E>("struct_f: 223344\n int: 55\n") {
Err(Error::Deserialize(_)) => (),
r => panic!("bad result {:?}", r),
}
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct G {
string: String,
}
#[test]
fn text_append() -> Result<(), Box<Error>> {
let g = "string: This is a long string\n :>for testing\n :>append definitions\n";
let expected = G {
string: "This is a long string\nfor testing\nappend definitions"
.to_string(),
};
assert_eq!(expected, from_str(g)?);
match from_str::<G>("string: test\njunk: stuff\n") {
Err(Error::FailedParse(ParseError::UnexpectedKey)) => (),
r => panic!("bad result {:?}", r),
}
Ok(())
}
#[derive(Debug, Deserialize, PartialEq)]
struct H {
strings: Vec<String>,
}
#[test]
fn text_list() -> Result<(), Box<Error>> {
let h = "strings: first second third\n :>item\n : fourth\n :=fifth item\n : sixth\n";
assert_eq!(
H {
strings: vec![
"first".to_string(),
"second".to_string(),
"third\nitem".to_string(),
"fourth".to_string(),
"fifth item".to_string(),
"sixth".to_string(),
],
},
from_str::<H>(h)?
);
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct I {
flag: Option<bool>,
int: Option<i64>,
float: Option<f32>,
}
#[test]
fn options() -> Result<(), Box<Error>> {
let i = "flag: false\n";
let expected = I {
flag: Some(false),
int: None,
float: None,
};
assert_eq!(expected, from_str(i)?);
let i = "int: xfab\n";
let expected = I {
flag: None,
int: Some(0xFAB),
float: None,
};
assert_eq!(expected, from_str(i)?);
let i = "float: -5e37\n";
let expected = I {
flag: None,
int: None,
float: Some(-5e37),
};
assert_eq!(expected, from_str(i)?);
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct J {
person: Vec<K>,
}
#[derive(Deserialize, PartialEq, Debug)]
struct K {
name: String,
score: i32,
}
#[test]
fn record_list() -> Result<(), Box<Error>> {
let j = "person:\n name: Genghis Khan\n score: 500\nperson:\n name: Josef Stalin\n score: 250\nperson:\n name: Dudley Do-Right\n score: 800\n";
let expected = J {
person: vec![
K {
name: "Genghis Khan".to_string(),
score: 500,
},
K {
name: "Josef Stalin".to_string(),
score: 250,
},
K {
name: "Dudley Do-Right".to_string(),
score: 800,
},
],
};
assert_eq!(expected, from_str(j)?);
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct M {
name: String,
date: Date,
time: Time,
datetime: DateTime,
}
#[test]
fn datetime() -> Result<(), Box<Error>> {
let date = "2019-08-07".parse().map_err(|e| Error::FailedParse(e))?;
let time = "12:34:56.789".parse().map_err(|e| Error::FailedParse(e))?;
let datetime = "1999-12-31T23:59:59.999-00:00"
.parse()
.map_err(|e| Error::FailedParse(e))?;
assert_eq!(
M { name: "one day".to_string(), date, time, datetime },
from_str("name: one day\ndate: 2019-08-07\ntime: 12:34:56.789\ndatetime: 1999-12-31T23:59:59.999-00:00\n")?
);
Ok(())
}
#[test]
fn record_substitute() -> Result<(), Box<Error>> {
assert_eq!(
J {
person: vec![
K {
name: "Immanuel Kant".to_string(),
score: 600,
},
K {
name: "Arthur Schopenhauer".to_string(),
score: 225,
},
K {
name: "René Descartes".to_string(),
score: 400,
},
],
},
from_str("person: Immanuel Kant\n score: 600\nperson: Arthur Schopenhauer\n score: 225\nperson: René Descartes\n score: 400\n")?
);
Ok(())
}
#[derive(Deserialize, PartialEq, Debug)]
struct N {
name: Option<String>,
id: u32,
}
#[derive(Deserialize, PartialEq, Debug)]
struct O {
thing: Vec<N>,
}
#[test]
fn record_optional() -> Result<(), Box<Error>> {
assert_eq!(
O {
thing: vec![
N {
name: Some("X".to_string()),
id: 1
},
N { name: None, id: 2 },
]
},
from_str("thing:\n name: X\n id: 1\nthing:\n id: 2\n")?
);
match from_str::<O>("thing: X\n id: 1\nthing:\n id: 2\n") {
Err(Error::FailedParse(ParseError::InvalidSubstitute)) => (),
r => panic!("bad result {:?}", r),
};
Ok(())
}
#[derive(Debug, Deserialize, PartialEq)]
struct R {
name: F,
other: u32,
}
#[test]
fn substitute_record() -> Result<(), Box<Error>> {
let r = R {
name: F { int: 999 },
other: 15,
};
assert_eq!(r, from_str("name: 999\nother: 15\n")?);
assert_eq!(r, from_str("name:\n int: 999\nother: 15\n")?);
Ok(())
}
#[derive(Debug, Deserialize, PartialEq)]
struct S {
group: Option<T>,
}
#[derive(Debug, Deserialize, PartialEq)]
struct T {
label: String,
}
#[test]
fn no_substitute_optional() -> Result<(), Box<Error>> {
assert_eq!(
S {
group: Some(T {
label: String::from("group label")
})
},
from_str("group: group label\n")?,
);
Ok(())
}
#[derive(Debug, Deserialize, PartialEq)]
struct U {
chan: Vec<H>,
}
#[test]
fn no_substitute_list() -> Result<(), Box<Error>> {
match from_str::<U>("chan: first second\n") {
Err(Error::FailedParse(ParseError::InvalidSubstitute)) => (),
r => panic!("bad result {:?}", r),
};
Ok(())
}
}