Skip to content

Commit

Permalink
fix: Support Ron values
Browse files Browse the repository at this point in the history
- `Char` variant needed to be converted to `String`.
- `Option` variant could be introduced generically.

NOTE: With `v0.9` of Ron, more types are introduced. Without tests, if these
do not deserialize into a supported type they will be treated as `Nil` type.

Signed-off-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com>
  • Loading branch information
polarathene committed Oct 9, 2023
1 parent dd15797 commit 1c8ed59
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 56 deletions.
54 changes: 2 additions & 52 deletions src/file/format/ron.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,12 @@ use std::error::Error;

use crate::format;
use crate::map::Map;
use crate::value::{Value, ValueKind};
use crate::value::Value;

pub fn parse(
uri: Option<&String>,
text: &str,
) -> Result<Map<String, Value>, Box<dyn Error + Send + Sync>> {
let value = from_ron_value(uri, ron::from_str(text)?)?;
let value = format::from_parsed_value(uri, ron::from_str(text)?);
format::extract_root_table(uri, value)
}

fn from_ron_value(
uri: Option<&String>,
value: ron::Value,
) -> Result<Value, Box<dyn Error + Send + Sync>> {
let kind = match value {
ron::Value::Option(value) => match value {
Some(value) => from_ron_value(uri, *value)?.kind,
None => ValueKind::Nil,
},

ron::Value::Unit => ValueKind::Nil,

ron::Value::Bool(value) => ValueKind::Boolean(value),

ron::Value::Number(value) => match value {
ron::Number::Float(value) => ValueKind::Float(value.get()),
ron::Number::Integer(value) => ValueKind::I64(value),
},

ron::Value::Char(value) => ValueKind::String(value.to_string()),

ron::Value::String(value) => ValueKind::String(value),

ron::Value::Seq(values) => {
let array = values
.into_iter()
.map(|value| from_ron_value(uri, value))
.collect::<Result<Vec<_>, _>>()?;

ValueKind::Array(array)
}

ron::Value::Map(values) => {
let map = values
.iter()
.map(|(key, value)| -> Result<_, Box<dyn Error + Send + Sync>> {
let key = key.clone().into_rust::<String>()?;
let value = from_ron_value(uri, value.clone())?;

Ok((key, value))
})
.collect::<Result<Map<_, _>, _>>()?;

ValueKind::Table(map)
}
};

Ok(Value::new(uri, kind))
}
22 changes: 18 additions & 4 deletions src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub enum ParsedValue {
String(String),
Table(Map<String, Self>),
Array(Vec<Self>),
Option(Option<Box<Self>>),
// If nothing else above matched, use Nil:
#[serde(deserialize_with = "deserialize_ignore_any")]
Nil,
Expand Down Expand Up @@ -97,6 +98,12 @@ pub fn from_parsed_value(uri: Option<&String>, value: ParsedValue) -> Value {

ValueKind::Array(l)
}

// Boxed value must be dereferenced:
ParsedValue::Option(v) => match v {
Some(boxed) => from_parsed_value(uri, *boxed).kind,
None => ValueKind::Nil,
}
};

Value::new(uri, vk)
Expand All @@ -115,11 +122,18 @@ where
// Config specific support for types that need string conversion:
#[cfg(feature = "toml")]
TomlDateTime(toml::value::Datetime),
#[cfg(feature = "ron")]
RonChar(ron::Value),
}

Ok(match ParsedString::deserialize(deserializer)? {
ParsedString::String(v) => v,
match ParsedString::deserialize(deserializer)? {
ParsedString::String(v) => Ok(v),
#[cfg(feature = "toml")]
ParsedString::TomlDateTime(v) => v.to_string(),
})
ParsedString::TomlDateTime(v) => Ok(v.to_string()),
#[cfg(feature = "ron")]
ParsedString::RonChar(variant) => match variant {
ron::Value::Char(v) => Ok(v.to_string()),
_ => Err(serde::de::Error::custom("should not be serialized to string"))
}
}
}

0 comments on commit 1c8ed59

Please sign in to comment.