local_store/
format_convert.rs1use serde_json::Value as JsonValue;
7use thiserror::Error;
8
9#[derive(Debug, Error)]
13#[non_exhaustive]
14pub enum FormatConvertError {
15 #[error("json→toml serialize: {0}")]
17 Serialize(String),
18
19 #[error("json→toml deserialize: {0}")]
21 Deserialize(String),
22
23 #[error("toml parse: {0}")]
27 TomlParse(String),
28}
29
30pub fn json_to_toml(json_value: &JsonValue) -> Result<toml::Value, FormatConvertError> {
49 let json_str = serde_json::to_string(json_value)
50 .map_err(|e| FormatConvertError::Serialize(e.to_string()))?;
51 let toml_value: toml::Value = serde_json::from_str(&json_str)
52 .map_err(|e| FormatConvertError::Deserialize(e.to_string()))?;
53 Ok(toml_value)
54}
55
56#[cfg(test)]
61mod tests {
62 use super::*;
63 use serde_json::json;
64
65 #[test]
70 fn test_json_to_toml_simple_object() {
71 let json = json!({"key": "value", "count": 42});
72 let toml_val = json_to_toml(&json).expect("conversion must succeed");
73 assert_eq!(toml_val["key"].as_str(), Some("value"));
74 assert_eq!(toml_val["count"].as_integer(), Some(42));
75 }
76
77 #[test]
78 fn test_json_to_toml_empty_object() {
79 let json = json!({});
80 let result = json_to_toml(&json);
82 assert!(result.is_ok(), "empty object must convert successfully");
83 let toml_val = result.unwrap();
84 assert!(toml_val.as_table().map(|t| t.is_empty()).unwrap_or(false));
86 }
87
88 #[test]
89 fn test_json_to_toml_nested_object() {
90 let json = json!({"outer": {"inner": true}});
91 let toml_val = json_to_toml(&json).expect("nested object must convert");
92 let outer = toml_val.get("outer").expect("outer key must exist");
93 assert_eq!(outer["inner"].as_bool(), Some(true));
94 }
95
96 #[test]
101 fn test_json_to_toml_null_value_is_boundary() {
102 let json = json!(null);
106 let _ = json_to_toml(&json); }
108
109 #[test]
110 fn test_json_to_toml_string_with_unicode() {
111 let json = json!({"emoji": "🦀", "text": "日本語"});
112 let toml_val = json_to_toml(&json).expect("unicode must convert");
113 assert_eq!(toml_val["emoji"].as_str(), Some("🦀"));
114 assert_eq!(toml_val["text"].as_str(), Some("日本語"));
115 }
116
117 #[test]
122 fn test_format_convert_error_serialize_display() {
123 let err = FormatConvertError::Serialize("bad input".to_string());
124 assert!(err.to_string().contains("serialize"));
125 assert!(err.to_string().contains("bad input"));
126 }
127
128 #[test]
129 fn test_format_convert_error_deserialize_display() {
130 let err = FormatConvertError::Deserialize("unexpected char".to_string());
131 assert!(err.to_string().contains("deserialize"));
132 assert!(err.to_string().contains("unexpected char"));
133 }
134
135 #[test]
136 fn test_format_convert_error_toml_parse_display() {
137 let err = FormatConvertError::TomlParse("invalid toml".to_string());
138 assert!(err.to_string().contains("toml parse"));
139 assert!(err.to_string().contains("invalid toml"));
140 }
141
142 #[test]
143 fn test_format_convert_error_is_std_error() {
144 let err = FormatConvertError::Serialize("x".to_string());
145 let _: &dyn std::error::Error = &err;
146 }
147}