use std::{
borrow::Cow,
iter::Peekable,
ops::{Deref, DerefMut},
};
#[cfg(doc)]
use crate::tokens::Token;
use crate::{Error, Result};
use keyvalues_parser::{Key, Obj, Value, Vdf};
use serde_core::ser::Error as _;
#[derive(Debug, Default)]
pub struct NaiveTokenStream(pub Vec<NaiveToken>);
impl Deref for NaiveTokenStream {
type Target = Vec<NaiveToken>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for NaiveTokenStream {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a> TryFrom<&'a NaiveTokenStream> for Vdf<'a> {
type Error = Error;
fn try_from(naive_token_stream: &'a NaiveTokenStream) -> Result<Self> {
fn process_key_values<'a, I>(
mut tokens: Peekable<I>,
) -> Result<(Peekable<I>, Key<'a>, Vec<Value<'a>>)>
where
I: Iterator<Item = &'a NaiveToken>,
{
let key = match tokens.peek() {
Some(NaiveToken::Str(s)) => {
let _ = tokens.next().unwrap();
Cow::from(s)
}
Some(NaiveToken::ObjBegin) => Cow::from(""),
other => {
return Err(Error::custom(format!("Expected key, found: {other:?}")));
}
};
let res = process_values(tokens)?;
tokens = res.0;
let values = res.1;
Ok((tokens, key, values))
}
fn process_values<'a, I>(mut tokens: Peekable<I>) -> Result<(Peekable<I>, Vec<Value<'a>>)>
where
I: Iterator<Item = &'a NaiveToken>,
{
let pair = match tokens.next() {
Some(NaiveToken::Str(s)) => (tokens, vec![Value::Str(Cow::from(s.clone()))]),
Some(NaiveToken::ObjBegin) => {
let (tokens, value) = process_obj(tokens)?;
(tokens, vec![value])
}
Some(NaiveToken::SeqBegin) => {
let mut values = Vec::new();
loop {
if let Some(NaiveToken::SeqEnd) = tokens.peek() {
tokens.next();
break;
} else {
let res = process_non_seq_value(tokens)?;
tokens = res.0;
if let Some(val) = res.1 {
values.push(val);
}
}
}
(tokens, values)
}
Some(NaiveToken::Null) => (tokens, Vec::new()),
_ => return Err(Error::ExpectedSomeValue),
};
Ok(pair)
}
fn process_non_seq_value<'a, I>(
mut tokens: Peekable<I>,
) -> Result<(Peekable<I>, Option<Value<'a>>)>
where
I: Iterator<Item = &'a NaiveToken>,
{
let pair = match tokens.next() {
Some(NaiveToken::Str(s)) => (tokens, Some(Value::Str(Cow::from(s)))),
Some(NaiveToken::ObjBegin) => {
let (tokens, value) = process_obj(tokens)?;
(tokens, Some(value))
}
Some(NaiveToken::Null) => (tokens, None),
_ => return Err(Error::ExpectedSomeNonSeqValue),
};
Ok(pair)
}
fn process_obj<'a, I>(mut tokens: Peekable<I>) -> Result<(Peekable<I>, Value<'a>)>
where
I: Iterator<Item = &'a NaiveToken>,
{
let mut obj = Obj::new();
loop {
match tokens.peek() {
Some(NaiveToken::ObjEnd) => {
tokens.next();
break;
}
Some(_) => {
let res = process_key_values(tokens)?;
tokens = res.0;
let key = res.1;
let values = res.2;
obj.insert(key, values);
}
_ => return Err(Error::ExpectedObjectStart),
}
}
Ok((tokens, Value::Obj(obj)))
}
let tokens = naive_token_stream.iter().peekable();
let (mut tokens, key, mut values) = process_key_values(tokens)?;
if tokens.next().is_some() {
return Err(Error::TrailingTokens);
}
let value = values.pop().ok_or_else(|| {
Error::custom("Syntax error: Serialized multiple values when there should only be one")
})?;
Ok(Self::new(key, value))
}
}
#[derive(Debug)]
pub enum NaiveToken {
Str(String),
ObjBegin,
ObjEnd,
SeqBegin,
SeqEnd,
Null,
}
impl NaiveToken {
pub fn str<S: ToString>(s: S) -> Self {
Self::Str(s.to_string())
}
}