table statement handling

This commit is contained in:
Robin Appelman 2023-12-15 18:07:47 +01:00
commit 28469fde0f
7 changed files with 379 additions and 24 deletions

View file

@ -16,6 +16,15 @@ pub enum Entry {
Value(Value),
}
impl From<Item<'_>> for Entry {
fn from(item: Item) -> Self {
match item {
Item::Item { content, .. } => Entry::Value(content.into()),
Item::Statement { content, .. } => Entry::Statement(content.into()),
}
}
}
impl Entry {
/// Lookup an entry with a path.
pub fn lookup<S: AsRef<str>>(&self, path: S) -> Option<&Entry> {
@ -152,4 +161,5 @@ mod statement;
pub use statement::Statement;
mod value;
use crate::Item;
pub use value::Value;

View file

@ -1,4 +1,5 @@
use super::{Array, Entry, Statement, Value};
use super::{Array, Entry};
use crate::entry::{Statement, Value};
use crate::{Event, Item, Reader, Result};
use serde::{Serialize, Serializer};
use std::collections::HashMap;
@ -20,7 +21,9 @@ where
ordered.serialize(serializer)
}
fn insert(map: &mut HashMap<String, Entry>, key: String, value: Entry) {
fn insert<K: Into<String>, V: Into<Entry>>(map: &mut HashMap<String, Entry>, key: K, value: V) {
let key = key.into();
let value = value.into();
if !map.contains_key(&key) {
map.insert(key, value);
return;
@ -44,21 +47,19 @@ impl Table {
while let Some(event) = reader.event() {
match event? {
Event::Entry {
key: Item::Item { content: key, .. },
value,
..
} => insert(&mut map, key, Value::from(value.into_content())),
Event::Entry {
key: Item::Statement { content: key, .. },
value,
..
} => insert(&mut map, key.into(), Statement::from(value.content).into()),
} => insert(&mut map, key, Statement::from(value.into_content())),
Event::Entry {
key: Item::Key { content: key, .. },
value,
..
} => insert(&mut map, key.into(), Value::from(value.content).into()),
Event::GroupStart { name, .. } => {
insert(&mut map, name.into(), Table::load(reader)?.into())
}
Event::GroupStart { name, .. } => insert(&mut map, name, Table::load(reader)?),
Event::GroupEnd { .. } => break,
}

View file

@ -10,31 +10,25 @@ pub enum Item<'a> {
Statement { content: Cow<'a, str>, span: Span },
/// A value.
Key { content: Cow<'a, str>, span: Span },
Item { content: Cow<'a, str>, span: Span },
}
impl<'a> Item<'a> {
pub fn span(&self) -> Span {
match self {
Item::Statement { span, .. } => span.clone(),
Item::Key { span, .. } => span.clone(),
Item::Item { span, .. } => span.clone(),
}
}
pub fn into_content(self) -> Cow<'a, str> {
match self {
Item::Statement { content, .. } => content,
Item::Key { content, .. } => content,
Item::Item { content, .. } => content,
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Value<'a> {
pub content: Cow<'a, str>,
pub span: Span,
}
/// Reader event.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Event<'a> {
@ -47,7 +41,7 @@ pub enum Event<'a> {
/// An entry.
Entry {
key: Item<'a>,
value: Value<'a>,
value: Item<'a>,
span: Span,
},
}
@ -134,12 +128,12 @@ impl<'a> Reader<'a> {
}
Some((Ok(Token::GroupEnd), span)) => return Some(Ok(Event::GroupEnd { span })),
Some((Ok(Token::Item), span)) => Item::Key {
Some((Ok(Token::Item), span)) => Item::Item {
content: string(self.lexer.slice()),
span,
},
Some((Ok(Token::QuotedItem), span)) => Item::Key {
Some((Ok(Token::QuotedItem), span)) => Item::Item {
content: quoted_string(self.lexer.slice()),
span,
},
@ -233,12 +227,22 @@ impl<'a> Reader<'a> {
}))
}
Some((Ok(Token::QuotedItem), span)) => Value {
Some((Ok(Token::QuotedItem), span)) => Item::Item {
content: quoted_string(self.lexer.slice()),
span,
},
Some((Ok(Token::Item), span)) => Value {
Some((Ok(Token::Item), span)) => Item::Item {
content: string(self.lexer.slice()),
span,
},
Some((Ok(Token::QuotedStatement), span)) => Item::Statement {
content: quoted_string(self.lexer.slice()),
span,
},
Some((Ok(Token::Statement), span)) => Item::Statement {
content: string(self.lexer.slice()),
span,
},
@ -254,7 +258,7 @@ impl<'a> Reader<'a> {
}
};
let span = key.span().start..value.span.end;
let span = key.span().start..value.span().end;
Some(Ok(Event::Entry { key, value, span }))
}
}