wyrd/authoring/
serde_ron.rs1use core::fmt;
8
9use std::string::String;
10
11use crate::{ValidationError, Weave, WeaveDef};
12
13#[derive(Debug)]
15#[non_exhaustive]
16pub enum RonCodecError {
17 Parse {
19 source: ron::error::SpannedError,
21 line: usize,
23 column: usize,
25 },
26 Validation(ValidationError),
28 Serialize(ron::Error),
30}
31
32impl fmt::Display for RonCodecError {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 Self::Parse {
36 source,
37 line,
38 column,
39 } => write!(
40 f,
41 "RON parse error at line {line}, column {column}: {source}"
42 ),
43 Self::Validation(error) => write!(f, "invalid RON weave: {error}"),
44 Self::Serialize(error) => write!(f, "RON serialization error: {error}"),
45 }
46 }
47}
48
49impl std::error::Error for RonCodecError {
50 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
51 match self {
52 Self::Parse { source, .. } => Some(source),
53 Self::Validation(source) => Some(source),
54 Self::Serialize(source) => Some(source),
55 }
56 }
57}
58
59impl From<ValidationError> for RonCodecError {
60 fn from(value: ValidationError) -> Self {
61 Self::Validation(value)
62 }
63}
64
65pub fn from_ron(text: &str) -> Result<Weave, RonCodecError> {
67 let def: WeaveDef = ron::from_str(text).map_err(|source: ron::error::SpannedError| {
68 let line = source.span.start.line;
69 let column = source.span.start.col;
70 RonCodecError::Parse {
71 source,
72 line,
73 column,
74 }
75 })?;
76 Ok(Weave::try_from(def)?)
77}
78
79pub fn to_ron(weave: &Weave) -> Result<String, RonCodecError> {
81 ron::ser::to_string_pretty(&weave.to_def(), ron::ser::PrettyConfig::default())
82 .map_err(RonCodecError::Serialize)
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use std::error::Error as _;
89 use std::string::ToString;
90
91 struct FailingWriter;
92
93 impl fmt::Write for FailingWriter {
94 fn write_str(&mut self, _: &str) -> fmt::Result {
95 Err(fmt::Error)
96 }
97 }
98
99 #[test]
100 fn serialize_error_formats_and_retains_its_source() {
101 let source =
102 ron::ser::to_writer_pretty(FailingWriter, &"codec", ron::ser::PrettyConfig::default())
103 .expect_err("writer failure must be preserved as a RON error");
104 let error = RonCodecError::Serialize(source);
105
106 assert!(error.to_string().starts_with("RON serialization error: "));
107 assert!(error.source().is_some());
108 }
109}