use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::io;
use std::str::FromStr;
use serde::de::{
self, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess,
Visitor,
};
use crate::error::{Error, Result};
use crate::parser::{Parser, Watcher};
use crate::tokenizer::Mode;
use crate::tokenizer::{Token, TokenSpan, TokenType};
thread_local!(pub(crate) static SECTION_CTX: RefCell<SectionCtx> = RefCell::new(SectionCtx::empty()));
#[derive(Debug, Clone)]
pub(crate) struct SectionCtx {
token: Option<Token>,
typename: &'static str,
level: u32,
}
impl SectionCtx {
fn empty() -> SectionCtx {
SectionCtx {
token: None,
typename: "",
level: 0,
}
}
fn new<T>(&mut self) -> SectionCtx {
self.new2(std::any::type_name::<T>())
}
fn new2(&mut self, typename: &'static str) -> SectionCtx {
let this = self.clone();
self.token = None;
self.typename = typename.split("<").next().unwrap().split(":").last().unwrap();
self.level += 1;
SECTION_CTX.with(|ctx| *ctx.borrow_mut() = self.clone());
this
}
fn restore(&mut self, scx: SectionCtx) {
*self = scx;
SECTION_CTX.with(|ctx| *ctx.borrow_mut() = self.clone());
}
fn update_section_token(&mut self, section_token: Token) {
self.token = Some(section_token);
SECTION_CTX.with(|ctx| *ctx.borrow_mut() = self.clone());
}
pub fn section_type(&self) -> &'static str {
self.typename
}
pub fn subsection_name(&self) -> &str {
self.token.as_ref().map(|t| t.value()).unwrap_or("")
}
}
pub(crate) struct Deserializer {
pub(crate) parser: Parser,
eov: TokenType,
ctx: SectionCtx,
is_closed: bool,
mode: Mode,
aliases: HashMap<String, String>,
ignored: HashSet<String>,
}
impl Deserializer {
fn new(
parser: Parser,
mode: Mode,
aliases: HashMap<String, String>,
ignored: HashSet<String>,
) -> Self {
let eov = if mode == Mode::Semicolon {
TokenType::Semi
} else {
TokenType::Nl
};
Deserializer {
parser,
eov,
ctx: SectionCtx::empty(),
is_closed: false,
mode,
aliases,
ignored,
}
}
pub fn from_str(
s: impl Into<String>,
mode: Mode,
aliases: HashMap<String, String>,
ignored: HashSet<String>,
watcher: Option<Watcher>,
) -> Self {
let parser = Parser::from_string(s, mode, watcher);
Self::new(parser, mode, aliases, ignored)
}
pub fn from_file(
file: impl Into<String>,
mode: Mode,
aliases: HashMap<String, String>,
ignored: HashSet<String>,
watcher: Option<Watcher>,
) -> io::Result<Self> {
let parser = Parser::from_file(file, mode, watcher)?;
Ok(Self::new(parser, mode, aliases, ignored))
}
}
impl Deserializer {
fn parse_expr<T>(&mut self, name: &str) -> Result<(TokenSpan, T)>
where
T: FromStr,
{
let word = self.parser.expect(TokenType::Word)?;
let value: T = FromStr::from_str(word.value())
.map_err(|_| Error::new(format!("expected {} value", name), word.span()))?;
Ok((word.span(), value))
}
fn current_section(&self, t1: &Token) -> bool {
let v1 = format!("{}.{}", self.ctx.section_type(), t1.value());
let v2 = format!("{}.{}", self.ctx.section_type(), self.ctx.subsection_name());
let t1 = self.aliases.get(&v1).map(|v| v.as_str()).unwrap_or(t1.value());
let t2 = self
.aliases
.get(&v2)
.map(|s| s.as_str())
.unwrap_or(self.ctx.subsection_name());
t1 == t2
}
fn check_include(&mut self) -> Result<()> {
loop {
let mut lookahead = self.parser.lookahead(1);
if let Some(ident) = lookahead.peek(TokenType::Ident)? {
if ident.value() == "include" {
lookahead.advance(&mut self.parser);
let curfile = &ident.span().source.filename;
let filename = self.parser.expect(TokenType::Expr)?;
self.parser.expect(self.eov)?;
self.parser.include(filename.value(), curfile).map_err(|e| {
Error::new(e.to_string(), filename.span())
})?;
continue;
}
}
break;
}
Ok(())
}
}
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer {
type Error = Error;
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let value = self.parser.expect(TokenType::Word)?;
Err(Error::new("BUG: serde called deserialize_any", value.span()))
}
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let mut lookahead = self.parser.lookaheadnl(1);
if let Some(token) = lookahead.peek(self.eov)? {
return visitor
.visit_bool(true)
.map_err(|e| update_span(e, token.span()));
}
if let Some(token) = lookahead.peek(TokenType::Expr)? {
lookahead.advance(&mut self.parser);
let v = match token.value() {
"y" | "yes" | "t" | "true" | "on" | "1" => true,
"n" | "no" | "f" | "false" | "off" | "0" => false,
_ => return Err(Error::new(format!("expected boolean"), token.span())),
};
return visitor.visit_bool(v).map_err(|e| update_span(e, token.span()));
}
lookahead.error()
}
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("i8 integer")?;
visitor.visit_i8(value).map_err(|e| update_span(e, span))
}
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("i16 integer")?;
visitor.visit_i16(value).map_err(|e| update_span(e, span))
}
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("i32 integer")?;
visitor.visit_i32(value).map_err(|e| update_span(e, span))
}
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("i64 integer")?;
visitor.visit_i64(value).map_err(|e| update_span(e, span))
}
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("u8 integer")?;
visitor.visit_u8(value).map_err(|e| update_span(e, span))
}
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("u16 integer")?;
visitor.visit_u16(value).map_err(|e| update_span(e, span))
}
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("u32 integer")?;
visitor.visit_u32(value).map_err(|e| update_span(e, span))
}
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("u64 integer")?;
visitor.visit_u64(value).map_err(|e| update_span(e, span))
}
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("f32 float")?;
visitor.visit_f32(value).map_err(|e| update_span(e, span))
}
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("f64 float")?;
visitor.visit_f64(value).map_err(|e| update_span(e, span))
}
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr("single character")?;
visitor.visit_char(value).map_err(|e| update_span(e, span))
}
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr::<String>("string")?;
visitor.visit_str(&value).map_err(|e| update_span(e, span))
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
let (span, value) = self.parse_expr::<String>("string")?;
visitor.visit_str(&value).map_err(|e| update_span(e, span))
}
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
unimplemented!()
}
fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
unimplemented!()
}
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
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>,
{
unimplemented!()
}
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>(mut self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.is_closed = false;
visitor.visit_seq(ListAccess::new(&mut self, false)).map_err(|e| update_span(e, self.parser.last_span()))
}
fn deserialize_tuple<V>(mut self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.is_closed = false;
visitor.visit_seq(ListAccess::new(&mut self, true)).map_err(|e| update_span(e, self.parser.last_span()))
}
fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_tuple(_len, visitor)
}
fn deserialize_map<V>(mut self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
debug!("deserialize_map");
let hma = HashMapAccess::new::<V::Value>(&mut self);
let value = visitor
.visit_map(hma)
.map_err(|e| update_span(e, self.parser.last_span()))?;
self.is_closed = true;
Ok(value)
}
fn deserialize_struct<V>(
mut self,
_name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
debug!("deserialize_struct({})", _name);
let mut label = None;
if self.ctx.level > 0 {
let mut lookahead = self.parser.lookahead(1);
let token = lookahead.peek(TokenType::Expr)?;
debug!("deserialize_struct({}): peeked: {:?}", _name, token);
if let Some(lbl) = token {
lookahead.advance(&mut self.parser);
if !fields.contains(&"__label__") {
debug!("deserialize_struct({}): fields has no __label__", _name);
return Err(Error::new(format!("expected '{{'"), lbl.span()));
}
debug!("fields is OK");
label = Some(lbl.value().to_string());
} else {
if fields.contains(&"__label__") {
lookahead.end()?;
}
}
if self.mode == Mode::Diablo {
self.parser.expect(TokenType::Nl)?;
} else {
self.parser.expect(TokenType::LcBrace)?;
}
}
let saved_context = self.ctx.new::<V::Value>();
let res = visitor.visit_map(SectionAccess::new(&mut self, label, Some(fields)));
self.ctx.restore(saved_context);
let value = res.map_err(|e| update_span(e, self.parser.last_span()))?;
debug!("XX level is {}", self.ctx.level);
if self.ctx.level != 0 {
if self.mode == Mode::Diablo {
self.parser.expect(TokenType::End)?;
} else {
self.parser.expect(TokenType::RcBrace)?;
}
}
self.is_closed = true;
Ok(value)
}
fn deserialize_enum<V>(
self,
_name: &'static str,
_variants: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
let mut lookahead = self.parser.lookaheadnl(1);
if let Some(token) = lookahead.peek(TokenType::Ident)? {
visitor.visit_enum(Enum::new(self)).map_err(|e| update_span(e, token.span()))
} else {
lookahead.error()
}
}
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
self.deserialize_str(visitor)
}
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
loop {
let mut lookahead = self.parser.lookaheadnl(1);
if lookahead.peek(self.eov)?.is_some() {
break;
}
lookahead.advance(&mut self.parser);
}
self.deserialize_unit(visitor)
}
}
struct ListAccess<'a> {
de: &'a mut Deserializer,
first: bool,
is_tuple: bool,
}
impl<'a> ListAccess<'a> {
fn new(de: &'a mut Deserializer, is_tuple: bool) -> Self {
ListAccess { de, first: true, is_tuple }
}
}
impl<'de, 'a> SeqAccess<'de> for ListAccess<'a> {
type Error = Error;
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
where
T: DeserializeSeed<'de>,
{
if !self.first {
let mut lookahead = self.de.parser.lookaheadnl(2);
let mut expect_next = false;
let mut continuation = false;
let mut check_continuation_no_eov = false;
if self.de.is_closed && !self.is_tuple {
check_continuation_no_eov = true;
}
if let Some(_) = lookahead.peek(TokenType::Comma)? {
lookahead.advance(&mut self.de.parser);
check_continuation_no_eov = false;
expect_next = true;
}
if let Some(_) = lookahead.peek(self.de.eov)? {
check_continuation_no_eov = false;
let mut lookahead2 = self.de.parser.lookaheadnl(2);
if let Some(ident) = lookahead2.peek2(self.de.eov, TokenType::Ident)? {
if self.de.current_section(&ident) {
self.de.ctx.update_section_token(ident);
lookahead2.advance(&mut self.de.parser);
continuation = true;
}
}
}
if check_continuation_no_eov {
let mut lookahead = self.de.parser.lookahead(1);
if let Some(ident) = lookahead.peek(TokenType::Ident)? {
if self.de.current_section(&ident) {
self.de.ctx.update_section_token(ident);
lookahead.advance(&mut self.de.parser);
continuation = true;
}
}
}
if !continuation {
if !self.de.is_closed {
lookahead.end()?;
}
if !expect_next {
return Ok(None);
}
}
}
self.first = false;
self.de.is_closed = false;
let token = self.de.parser.peek()?;
seed.deserialize(&mut *self.de)
.map(Some)
.map_err(|e| update_tspan(e, &token))
}
}
struct SectionAccess<'a> {
de: &'a mut Deserializer,
label: Option<String>,
first: bool,
fields: Option<&'static [&'static str]>,
}
impl<'a> SectionAccess<'a> {
fn new(
de: &'a mut Deserializer,
label: Option<String>,
fields: Option<&'static [&'static str]>,
) -> Self {
debug!("SectionAccess::new");
SectionAccess {
label,
de,
first: true,
fields,
}
}
}
impl<'de, 'a> MapAccess<'de> for SectionAccess<'a> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
debug!("SectionAccess::MapAccess::next_key_seed");
if self.first && self.label.is_some() {
debug!(
"SectionAccess::MapAccess::next_key_seed: insert label {:?}",
self.label
);
let de = "__label__".into_deserializer();
return seed.deserialize(de).map(Some);
}
if !self.first {
if !self.de.is_closed {
self.de.parser.expect(self.de.eov)?;
}
}
self.first = false;
self.de.check_include()?;
debug!("check for EOF");
if self.de.ctx.level == 1 && self.de.parser.is_eof() {
return Ok(None);
}
debug!("check for EOF done");
let mut continuation = false;
let mut lookahead = self.de.parser.lookaheadnl(2);
if let Some(ident) = lookahead.peek2(self.de.eov, TokenType::Ident)? {
if self.de.current_section(&ident) {
lookahead.advance(&mut self.de.parser);
continuation = true;
}
}
let mut lookahead = self.de.parser.lookahead(1);
if !continuation {
let closed = if self.de.mode == Mode::Diablo {
lookahead.peek(TokenType::End)?.is_some()
} else {
lookahead.peek(TokenType::RcBrace)?.is_some()
};
if closed {
return Ok(None);
}
}
if let Some(token) = lookahead.peek(TokenType::Ident)? {
debug!("next_key_seed: key {:?}", token);
lookahead.advance(&mut self.de.parser);
let type_dot_field = format!("{}.{}", self.de.ctx.section_type(), token.value());
let name = self
.de
.aliases
.get(&type_dot_field)
.map(|s| s.as_str())
.unwrap_or(token.value());
let fields = self.fields.as_ref().unwrap();
if !fields.contains(&name) && !self.de.ignored.contains(&type_dot_field) {
return Err(Error::new(
format!("unknown field: `{}'", token.value()),
token.span(),
));
}
debug!("XXX set section_name_token to {}", token.value());
self.de.ctx.update_section_token(token.clone());
return seed.deserialize(name.into_deserializer()).map(Some);
}
lookahead.error()
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
debug!(
"SectionAccess::MapAccess::next_value_seed {}",
std::any::type_name::<V::Value>()
);
if let Some(label) = self.label.take() {
let mut de = Deserializer::from_str(label, Mode::Newline, HashMap::new(), HashSet::new(), self.de.parser.watcher.clone());
return seed.deserialize(&mut de);
}
self.de.is_closed = false;
let token = self.de.parser.peek()?;
seed.deserialize(&mut *self.de)
.map_err(|e| update_tspan(e, &token))
}
}
struct HashMapAccess<'a> {
de: &'a mut Deserializer,
first: bool,
subsection: Option<Token>,
typename: &'static str,
}
impl<'a> HashMapAccess<'a> {
fn new<T>(de: &'a mut Deserializer) -> Self {
debug!("HashMapAccess::new");
let typename = std::any::type_name::<T>();
HashMapAccess { de, first: true, subsection: None, typename }
}
}
impl<'de, 'a> MapAccess<'de> for HashMapAccess<'a> {
type Error = Error;
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
where
K: DeserializeSeed<'de>,
{
debug!("HashMapAccess::MapAccess::next_key_seed");
if !self.first {
let mut continuation = false;
let mut lookahead = self.de.parser.lookaheadnl(2);
if self.de.is_closed {
if self.de.mode == Mode::Diablo {
if let Some(ident) = lookahead.peek2(TokenType::Nl, TokenType::Ident)? {
if self.de.current_section(&ident) {
lookahead.advance(&mut self.de.parser);
continuation = true;
}
}
} else {
if let Some(ident) = lookahead.peek(TokenType::Ident)? {
if self.de.current_section(&ident) {
lookahead.advance(&mut self.de.parser);
continuation = true;
}
}
}
} else {
if let Some(ident) = lookahead.peek2(self.de.eov, TokenType::Ident)? {
if self.de.current_section(&ident) {
lookahead.advance(&mut self.de.parser);
continuation = true;
}
}
}
if !continuation {
if !self.de.is_closed {
self.de.parser.expect(self.de.eov)?;
}
return Ok(None);
}
}
self.first = false;
let mut lookahead = self.de.parser.lookaheadnl(2);
let ttype = if self.de.mode == Mode::Diablo {
TokenType::Nl
} else {
TokenType::LcBrace
};
if let Some(_) = lookahead.peek2(TokenType::Expr, ttype)? {
let saved_pos = self.de.parser.save_pos();
let result: Result<K::Value> = seed.deserialize(&mut *self.de);
match result {
Ok(res) => {
self.de.parser.restore_pos(saved_pos);
return Ok(Some(res));
},
Err(e) => return Err(e),
}
}
if let Some(key) = lookahead.peek(TokenType::Expr)? {
if let Some(ctx_token) = self.de.ctx.token.as_ref() {
let mut token = ctx_token.clone();
token.value = Some(format!("{}.{}", self.de.ctx.subsection_name(), key.value()));
self.subsection = Some(token);
}
}
seed.deserialize(&mut *self.de).map(Some)
}
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
where
V: DeserializeSeed<'de>,
{
debug!(
"HashMapAccess::MapAccess::next_value_seed {}",
std::any::type_name::<V::Value>()
);
self.de.is_closed = false;
let token = self.de.parser.peek()?;
let saved = match self.subsection.take() {
Some(subsection) => {
let saved = self.de.ctx.new2(self.typename);
self.de.ctx.update_section_token(subsection);
Some(saved)
},
None => None,
};
let result = seed.deserialize(&mut *self.de).map_err(|e| update_tspan(e, &token));
if let Some(saved) = saved {
self.de.ctx.restore(saved);
}
result
}
}
struct Enum<'a> {
de: &'a mut Deserializer,
}
impl<'a> Enum<'a> {
fn new(de: &'a mut Deserializer) -> Self {
Enum { de }
}
}
impl<'de, 'a> EnumAccess<'de> for Enum<'a> {
type Error = Error;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: DeserializeSeed<'de>,
{
let val = seed.deserialize(&mut *self.de)?;
Ok((val, self))
}
}
impl<'de, 'a> VariantAccess<'de> for Enum<'a> {
type Error = Error;
fn unit_variant(self) -> Result<()> {
Ok(())
}
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self.de)
}
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
de::Deserializer::deserialize_tuple(self.de, _len, visitor)
}
fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
de::Deserializer::deserialize_struct(self.de, "", fields, visitor)
}
}
fn update_span(mut e: Error, span: TokenSpan) -> Error {
if e.span.is_none() {
e.span = Some(span);
}
e
}
fn update_tspan(mut e: Error, token: &Option<Token>) -> Error {
if e.span.is_none() {
if let Some(token) = token.as_ref() {
e.span = Some(token.span());
}
}
e
}