use serde::Serialize;
use serde::de::DeserializeOwned;
use crate::error::{Error, Result};
pub(crate) fn decode<T: DeserializeOwned, E>(
value: Option<&str>,
what: &'static str,
) -> Result<T, E> {
serde_json::from_str(value.unwrap_or("null")).map_err(|source| Error::Deserialization {
what: what.into(),
message: source.to_string(),
source: Some(source),
})
}
pub(crate) fn encode<T: Serialize, E>(value: &T, what: &'static str) -> Result<String, E> {
serde_json::to_string(value).map_err(|source| Error::Serialization {
what: what.into(),
message: source.to_string(),
source: Some(source),
})
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use super::*;
use crate::error::EngineOnly;
#[test]
fn an_absent_value_decodes_as_the_unit() {
assert_eq!(decode::<(), EngineOnly>(None, "argument").unwrap(), ());
assert_eq!(
decode::<Option<u32>, EngineOnly>(None, "argument").unwrap(),
None
);
}
#[test]
fn a_value_round_trips() {
let encoded = encode::<_, EngineOnly>(&(1u32, "two"), "argument").unwrap();
assert_eq!(encoded, r#"[1,"two"]"#);
assert_eq!(
decode::<(u32, String), EngineOnly>(Some(&encoded), "argument").unwrap(),
(1, "two".to_owned())
);
}
#[test]
fn the_unit_encodes_as_a_value_rather_than_an_absence() {
assert_eq!(encode::<_, EngineOnly>(&(), "argument").unwrap(), "null");
}
#[test]
fn a_mismatch_names_the_half_that_failed() {
let err = decode::<u32, EngineOnly>(Some(r#""not a number""#), "result").unwrap_err();
assert!(
matches!(
err,
Error::Deserialization {
what: Cow::Borrowed("result"),
..
}
),
"{err}"
);
}
}