pub use serde::{Deserialize, Serialize};
pub fn to_string<T: Serialize>(value: &T) -> Result<String, ron::Error> {
ron::to_string(value)
}
pub fn to_string_pretty<T: Serialize>(value: &T) -> Result<String, ron::Error> {
ron::ser::to_string_pretty(value, ron::ser::PrettyConfig::default())
}
pub fn to_writer<W: std::io::Write, T: Serialize>(
mut writer: W,
value: &T,
) -> Result<(), ron::Error> {
let serialized = ron::to_string(value)?;
writer.write_all(serialized.as_bytes()).map_err(|error| {
eprintln!(
"lgwks_std::ron: to_writer failed writing {} bytes: {error}",
serialized.len()
);
ron::Error::Message(error.to_string())
})
}
pub fn from_str<T: serde::de::DeserializeOwned>(s: &str) -> Result<T, ron::error::SpannedError> {
ron::from_str(s)
}
pub fn from_slice<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> Result<T, FromSliceError> {
let text = std::str::from_utf8(bytes).map_err(FromSliceError::Utf8)?;
ron::from_str(text).map_err(FromSliceError::Ron)
}
#[derive(Debug)]
pub enum FromSliceError {
Utf8(std::str::Utf8Error),
Ron(ron::error::SpannedError),
}
impl core::fmt::Display for FromSliceError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Utf8(e) => write!(f, "RON input is not valid UTF-8: {e}"),
Self::Ron(e) => write!(f, "{e}"),
}
}
}
impl std::error::Error for FromSliceError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Utf8(e) => Some(e),
Self::Ron(e) => Some(e),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
struct Point {
x: i32,
y: i32,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
enum Shape {
Circle(u32),
Rect { w: u32, h: u32 },
}
#[test]
fn struct_roundtrips_through_string() {
let p = Point { x: 1, y: 2 };
let s = to_string(&p).unwrap();
let q: Point = from_str(&s).unwrap();
assert_eq!(p, q);
}
#[test]
fn enum_roundtrips() {
let shapes = vec![Shape::Circle(5), Shape::Rect { w: 10, h: 20 }];
for shape in &shapes {
let s = to_string(shape).unwrap();
let back: Shape = from_str(&s).unwrap();
assert_eq!(*shape, back);
}
}
#[test]
fn pretty_output_has_indentation() {
let p = Point { x: 1, y: 2 };
let s = to_string_pretty(&p).unwrap();
assert!(s.contains('\n'));
}
#[test]
fn from_str_rejects_invalid() {
let result: Result<Point, _> = from_str("{{{");
assert!(result.is_err());
}
#[test]
fn from_slice_rejects_invalid_utf8() {
let result: Result<Point, _> = from_slice(&[0xFF, 0xFE]);
assert!(matches!(result, Err(FromSliceError::Utf8(_))));
}
}