1use std::collections::HashMap;
2use std::io::Write;
3pub mod dynread;
4pub mod flags;
5pub mod pretty_print;
6pub mod redbcontrol;
7
8macro_rules! write_io {
9 ($func_name:ident, $prefix:literal) => {
10 pub fn $func_name(data: String) -> Result<(), String> {
11 let out_data = format!("{}-> {} \n", $prefix, data);
12 write!(std::io::stdout(), "{}", out_data).map_err(|e| e.to_string())?;
13 std::io::stdout().flush().map_err(|e| e.to_string())?;
14 Ok(())
15 }
16 };
17}
18
19write_io!(write_io_error, "error:");
20write_io!(write_io_success, "success:");
21write_io!(write_io_info, "info:");
22
23#[derive(Debug, Default)]
24pub struct TableMeta {
25 pub name: String,
26 pub key_type: String,
27 pub value_type: String,
28}
29
30#[derive(Debug, Default)]
31pub struct TableInfo {
32 pub tables: Vec<TableMeta>,
33}
34
35#[derive(Debug, Default)]
36pub struct KvInfo {
37 pub kvdatas: Vec<(String, String)>,
38 pub key_type: String,
39 pub value_type: String,
40}
41
42pub type StrKvData = HashMap<String, String>;
43
44pub fn rows_to_json(rows: &[(String, String)]) -> Result<String, String> {
47 let mut map = serde_json::Map::new();
48 for (k, v) in rows {
49 map.insert(k.clone(), serde_json::Value::String(v.clone()));
50 }
51 serde_json::to_string_pretty(&serde_json::Value::Object(map)).map_err(|e| e.to_string())
52}
53
54pub fn json_to_rows(json: &str) -> Result<Vec<(String, String)>, String> {
57 let value: serde_json::Value =
58 serde_json::from_str(json).map_err(|e| format!("invalid json: {e}"))?;
59 let object = value
60 .as_object()
61 .ok_or_else(|| "edited data must be a json object".to_string())?;
62 let mut rows = Vec::with_capacity(object.len());
63 for (k, v) in object {
64 let text = v
65 .as_str()
66 .ok_or_else(|| format!("value for key '{k}' must be a json string"))?;
67 rows.push((k.clone(), text.to_string()));
68 }
69 Ok(rows)
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn json_roundtrip_is_deterministic() {
78 let rows = vec![
79 ("zebra".to_string(), "2".to_string()),
80 ("apple".to_string(), "1".to_string()),
81 ];
82 let json = rows_to_json(&rows).unwrap();
83 assert_eq!(json, "{\n \"apple\": \"1\",\n \"zebra\": \"2\"\n}");
84 let parsed = json_to_rows(&json).unwrap();
85 assert_eq!(
86 parsed,
87 vec![
88 ("apple".to_string(), "1".to_string()),
89 ("zebra".to_string(), "2".to_string())
90 ]
91 );
92 }
93
94 #[test]
95 fn json_rejects_non_object() {
96 assert!(json_to_rows("[1, 2]").is_err());
97 assert!(json_to_rows("\"str\"").is_err());
98 }
99
100 #[test]
101 fn json_rejects_non_string_values() {
102 let err = json_to_rows("{\"a\": 42}").unwrap_err();
103 assert!(err.contains("must be a json string"), "got: {err}");
104 }
105
106 #[test]
107 fn json_preserves_tuple_and_hex_cells() {
108 let rows = vec![
109 ("(1, 2)".to_string(), "0x01abff".to_string()),
110 ("(3, 4)".to_string(), "100".to_string()),
111 ];
112 let parsed = json_to_rows(&rows_to_json(&rows).unwrap()).unwrap();
113 assert_eq!(parsed, rows);
114 }
115}