use crate::prelude::*;
use serde::de::DeserializeOwned;
pub fn type_name<T>() -> String {
std::any::type_name::<T>().to_string()
}
pub fn deserialize_contents_of_ron<T: DeserializeOwned>(path: impl AsRef<Path>) -> Result<T> {
use std::fs;
let path = path.as_ref();
let ron_str = fs::read_to_string(path).map_err(|e| Error::FileNotFound {
path: path.display().to_string(),
underlying: format!("{:?}", e),
})?;
deserialize_ron_str(&ron_str)
}
pub fn deserialize_ron_str<T: DeserializeOwned>(ron_str: &str) -> Result<T> {
use ron::de::from_str;
let type_name = type_name::<T>();
trace!("☑️ Deserializing {} from RON str", type_name);
let result = from_str(ron_str)
.inspect(|_| trace!("✅ Deserialized {} from RON str", type_name))
.map_err(|e| Error::Deserialize {
type_name,
error: e.to_string(),
})?;
Ok(result)
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
#[test]
fn test_type_name() {
let type_name = type_name::<CompanyInformation>();
assert!(type_name.ends_with("CompanyInformation"));
}
#[test]
fn deserialize_contents_of_ron_fail_file_not_found() {
let result: Result<CompanyInformation> =
deserialize_contents_of_ron(Path::new("non_existent_file.ron"));
assert!(result.is_err(), "Expected error, got: {:?}", result);
if let Err(Error::FileNotFound {
path: _,
underlying: _,
}) = result
{
} else {
panic!("Expected FileNotFound error, got: {:?}", result);
}
}
#[test]
fn deserialize_contents_of_ron_fail() {
let tempfile = tempfile::NamedTempFile::new().unwrap();
let path = tempfile.path();
let result: Result<CompanyInformation> = deserialize_contents_of_ron(path);
assert!(result.is_err(), "Expected error, got: {:?}", result);
if let Err(Error::Deserialize { type_name, error }) = result {
assert!(
type_name.contains("CompanyInformation"),
"Expected type name to contain 'CompanyInformation', got: {}",
type_name
);
assert!(
error.contains("Expected opening"),
"Expected deserialization error, got: {}",
error
);
} else {
panic!("Expected Deserialize error, got: {:?}", result);
}
}
#[test]
fn deseralize_ron_success() {
let tempfile = tempfile::NamedTempFile::new().unwrap();
let path = tempfile.path();
fs::write(
path,
r#"
ServiceFees(
name: "Agreed Consulting Service",
rate: Daily(UnitPrice(777.0)),
cadence: Monthly,
)
"#,
)
.unwrap();
let result: Result<ServiceFees> = deserialize_contents_of_ron(path);
assert!(result.is_ok(), "Expected success, got: {:?}", result);
let consulting_service = result.unwrap();
assert_eq!(consulting_service.name(), "Agreed Consulting Service");
assert_eq!(*consulting_service.rate(), Rate::daily(dec!(777.0)));
}
}