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