pub(crate) mod json;
pub(crate) mod toml;
pub(crate) mod yaml;
use std::fmt;
use crate::value::{AttrPath, Value};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Format {
Json,
Toml,
Yaml,
}
impl fmt::Display for Format {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Format::Json => "JSON",
Format::Toml => "TOML",
Format::Yaml => "YAML",
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RenderError {
pub path: AttrPath,
pub message: String,
}
impl fmt::Display for RenderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.path.keys().is_empty() {
f.write_str(&self.message)
} else {
write!(f, "`{}`: {}", self.path, self.message)
}
}
}
impl std::error::Error for RenderError {}
pub(crate) fn text(value: &Value) -> Option<std::borrow::Cow<'_, str>> {
Some(match value {
Value::Str(s) | Value::Ref(s) | Value::Symbol { text: s, .. } => s.as_str().into(),
Value::Path(p) => p.to_string_lossy(),
Value::Variant {
name, fields: None, ..
} => name.as_str().into(),
_ => return None,
})
}
pub(crate) enum Entries<'a> {
Fields(&'a [(String, Value)]),
Variant(&'a str, &'a [(String, Value)]),
}
impl<'a> Entries<'a> {
pub(crate) fn of(value: &'a Value) -> Option<Self> {
match value {
Value::Struct { fields, .. } | Value::Map(fields) => Some(Entries::Fields(fields)),
Value::Variant {
name,
fields: Some(fields),
..
} => Some(Entries::Variant(name, fields)),
_ => None,
}
}
pub(crate) fn len(&self) -> usize {
match self {
Entries::Fields(fields) => fields.len(),
Entries::Variant(..) => 1,
}
}
pub(crate) fn each<E>(
&self,
mut f: impl FnMut(&'a str, Item<'a>) -> Result<(), E>,
) -> Result<(), E> {
match self {
Entries::Fields(fields) => {
for (key, value) in fields.iter() {
f(key, Item::Value(value))?;
}
Ok(())
}
Entries::Variant(name, fields) => f(name, Item::Payload(fields)),
}
}
}
#[derive(Clone, Copy)]
pub(crate) enum Item<'a> {
Value(&'a Value),
Payload(&'a [(String, Value)]),
}
impl<'a> Item<'a> {
pub(crate) fn entries(self) -> Option<Entries<'a>> {
match self {
Item::Value(value) => Entries::of(value),
Item::Payload(fields) => Some(Entries::Fields(fields)),
}
}
pub(crate) fn value(self) -> Option<&'a Value> {
match self {
Item::Value(value) => Some(value),
Item::Payload(_) => None,
}
}
}
#[cfg(test)]
#[path = "render_tests.rs"]
mod tests;