rimu_value/serde/
mod.rs

1mod convert;
2mod de;
3mod error;
4mod from;
5mod ser;
6
7use std::fmt::{Debug, Display};
8
9use indexmap::IndexMap;
10use serde::de::DeserializeOwned;
11use serde::ser::Serialize;
12
13use crate::{Function, Number};
14
15pub use self::convert::convert;
16pub use self::error::SerdeValueError;
17
18use self::ser::Serializer;
19
20pub type SerdeValueList = Vec<SerdeValue>;
21pub type SerdeValueObject = IndexMap<String, SerdeValue>;
22
23#[derive(Default, Clone, PartialEq)]
24pub enum SerdeValue {
25    #[default]
26    Null,
27    Boolean(bool),
28    String(String),
29    Number(Number),
30    Function(Function),
31    List(SerdeValueList),
32    Object(SerdeValueObject),
33}
34
35pub fn to_serde_value<T>(value: T) -> Result<SerdeValue, SerdeValueError>
36where
37    T: Serialize,
38{
39    value.serialize(Serializer)
40}
41
42pub fn from_serde_value<T>(value: SerdeValue) -> Result<T, SerdeValueError>
43where
44    T: DeserializeOwned,
45{
46    T::deserialize(value)
47}
48
49impl Debug for SerdeValue {
50    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        match self {
52            SerdeValue::Null => formatter.write_str("Null"),
53            SerdeValue::Boolean(boolean) => match boolean {
54                true => formatter.write_str("true"),
55                false => formatter.write_str("false"),
56            },
57            SerdeValue::String(string) => write!(formatter, "String({:?})", string),
58            SerdeValue::Number(number) => write!(formatter, "Number({})", number),
59            SerdeValue::Function(function) => {
60                write!(formatter, "Function({:?})", function)
61            }
62            SerdeValue::List(list) => {
63                formatter.write_str("List ")?;
64                formatter.debug_list().entries(list).finish()
65            }
66            SerdeValue::Object(object) => {
67                formatter.write_str("Object ")?;
68                formatter.debug_map().entries(object).finish()
69            }
70        }
71    }
72}
73
74impl Display for SerdeValue {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        match self {
77            SerdeValue::Null => write!(f, "null"),
78            SerdeValue::Boolean(boolean) => write!(f, "{}", boolean),
79            SerdeValue::String(string) => write!(f, "{}", string),
80            SerdeValue::Number(number) => write!(f, "{}", number),
81            SerdeValue::Function(function) => write!(f, "{}", function),
82            SerdeValue::List(list) => {
83                let items = list
84                    .iter()
85                    .map(|value| value.to_string())
86                    .collect::<Vec<String>>()
87                    .join(", ");
88                write!(f, "[{}]", items)
89            }
90            SerdeValue::Object(object) => {
91                let entries = object
92                    .iter()
93                    .map(|(key, value)| format!("\"{}\": {}", key, value))
94                    .collect::<Vec<String>>()
95                    .join(", ");
96                write!(f, "{{{}}}", entries)
97            }
98        }
99    }
100}
101
102pub fn value_get_in<'a>(value: &'a SerdeValue, keys: &[&str]) -> Option<&'a SerdeValue> {
103    let Some((first, rest)) = keys.split_first() else {
104        return Some(value);
105    };
106    match value {
107        SerdeValue::Object(object) => match object.get(*first) {
108            Some(value) => value_get_in(value, rest),
109            None => None,
110        },
111        _ => None,
112    }
113}
114
115#[cfg(test)]
116mod test {
117    use std::{borrow::Cow, ffi::OsString, path::PathBuf};
118
119    use crate::SerdeValue;
120    use pretty_assertions::assert_eq;
121    use rust_decimal_macros::dec;
122
123    #[test]
124    fn from_string_tests() {
125        assert_eq!(
126            SerdeValue::from("John Sheppard"),
127            SerdeValue::String("John Sheppard".to_string())
128        );
129
130        assert_eq!(
131            SerdeValue::from("Elizabeth Weir".to_string()),
132            SerdeValue::String("Elizabeth Weir".to_string())
133        );
134
135        assert_eq!(
136            SerdeValue::from(PathBuf::new()),
137            SerdeValue::String("".to_string())
138        );
139
140        assert_eq!(
141            SerdeValue::from(Cow::from("Samantha Carter")),
142            SerdeValue::String("Samantha Carter".to_string())
143        );
144
145        assert_eq!(
146            SerdeValue::from(OsString::from("Jennifer Keller")),
147            SerdeValue::String("Jennifer Keller".to_string())
148        );
149    }
150
151    #[test]
152    fn from_vec_test() {
153        assert_eq!(
154            SerdeValue::from(vec!["Aiden Ford", "Rodney McKay", "Ronon Dex"]),
155            SerdeValue::List(vec![
156                SerdeValue::String("Aiden Ford".to_string()),
157                SerdeValue::String("Rodney McKay".to_string()),
158                SerdeValue::String("Ronon Dex".to_string())
159            ])
160        );
161    }
162
163    #[test]
164    fn debug_tests() {
165        assert_eq!(format!("{:?}", SerdeValue::Null), "Null".to_string());
166
167        assert_eq!(
168            format!("{:?}", SerdeValue::String("Richard Woolsey".to_string())),
169            "String(\"Richard Woolsey\")".to_string()
170        );
171
172        assert_eq!(
173            format!(
174                "{:?}",
175                SerdeValue::List(vec![
176                    SerdeValue::String("Aiden Ford".to_string()),
177                    SerdeValue::String("Rodney McKay".to_string()),
178                    SerdeValue::String("Ronon Dex".to_string())
179                ])
180            ),
181            "List [String(\"Aiden Ford\"), String(\"Rodney McKay\"), String(\"Ronon Dex\")]"
182                .to_string()
183        );
184
185        assert_eq!(
186            format!("{:?}", SerdeValue::Number(dec!(2).into())),
187            "Number(2)".to_string()
188        );
189    }
190}