oxihuman_export/
ron_export.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
8pub enum RonValue {
9 Bool(bool),
10 Int(i64),
11 Float(f64),
12 Str(String),
13 Option(Option<Box<RonValue>>),
14 List(Vec<RonValue>),
15 Map(Vec<(String, RonValue)>),
16 Struct {
17 name: String,
18 fields: Vec<(String, RonValue)>,
19 },
20}
21
22pub fn ron_bool(b: bool) -> RonValue {
23 RonValue::Bool(b)
24}
25pub fn ron_int(i: i64) -> RonValue {
26 RonValue::Int(i)
27}
28pub fn ron_float(f: f64) -> RonValue {
29 RonValue::Float(f)
30}
31pub fn ron_str(s: &str) -> RonValue {
32 RonValue::Str(s.to_string())
33}
34pub fn ron_none() -> RonValue {
35 RonValue::Option(None)
36}
37pub fn ron_some(v: RonValue) -> RonValue {
38 RonValue::Option(Some(Box::new(v)))
39}
40pub fn ron_list(items: Vec<RonValue>) -> RonValue {
41 RonValue::List(items)
42}
43pub fn ron_map(entries: Vec<(String, RonValue)>) -> RonValue {
44 RonValue::Map(entries)
45}
46pub fn ron_struct(name: &str, fields: Vec<(String, RonValue)>) -> RonValue {
47 RonValue::Struct {
48 name: name.to_string(),
49 fields,
50 }
51}
52
53fn render_ron_value(v: &RonValue) -> String {
54 match v {
55 RonValue::Bool(b) => b.to_string(),
56 RonValue::Int(i) => i.to_string(),
57 RonValue::Float(f) => format!("{:?}", f),
58 RonValue::Str(s) => format!("\"{}\"", s.replace('"', "\\\"")),
59 RonValue::Option(None) => "None".to_string(),
60 RonValue::Option(Some(inner)) => format!("Some({})", render_ron_value(inner)),
61 RonValue::List(items) => {
62 let inner: Vec<String> = items.iter().map(render_ron_value).collect();
63 format!("[{}]", inner.join(", "))
64 }
65 RonValue::Map(entries) => {
66 let inner: Vec<String> = entries
67 .iter()
68 .map(|(k, v)| format!("\"{}\": {}", k, render_ron_value(v)))
69 .collect();
70 format!("{{{}}}", inner.join(", "))
71 }
72 RonValue::Struct { name, fields } => {
73 let inner: Vec<String> = fields
74 .iter()
75 .map(|(k, v)| format!("{}: {}", k, render_ron_value(v)))
76 .collect();
77 format!("{}({})", name, inner.join(", "))
78 }
79 }
80}
81
82pub fn render_ron(root: &RonValue) -> String {
83 format!("(\n {}\n)\n", render_ron_value(root))
84}
85
86pub fn export_ron(root: &RonValue) -> Vec<u8> {
87 render_ron(root).into_bytes()
88}
89pub fn ron_size_bytes(root: &RonValue) -> usize {
90 render_ron(root).len()
91}
92pub fn validate_ron_value(v: &RonValue) -> bool {
93 match v {
94 RonValue::Float(f) => f.is_finite(),
95 _ => true,
96 }
97}
98
99pub fn scene_to_ron(name: &str, mesh_count: usize) -> RonValue {
100 ron_struct(
101 "Scene",
102 vec![
103 ("name".to_string(), ron_str(name)),
104 ("mesh_count".to_string(), ron_int(mesh_count as i64)),
105 ],
106 )
107}
108
109pub fn ron_list_len(v: &RonValue) -> usize {
110 if let RonValue::List(items) = v {
111 items.len()
112 } else {
113 0
114 }
115}
116
117pub fn ron_map_get<'a>(v: &'a RonValue, key: &str) -> Option<&'a RonValue> {
118 if let RonValue::Map(entries) = v {
119 entries.iter().find(|(k, _)| k == key).map(|(_, v)| v)
120 } else {
121 None
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_ron_bool() {
131 let s = render_ron_value(&ron_bool(true));
132 assert_eq!(s, "true");
133 }
134
135 #[test]
136 fn test_ron_int() {
137 let s = render_ron_value(&ron_int(99));
138 assert!(s.contains("99"));
139 }
140
141 #[test]
142 fn test_ron_option_none() {
143 let s = render_ron_value(&ron_none());
144 assert_eq!(s, "None");
145 }
146
147 #[test]
148 fn test_ron_option_some() {
149 let s = render_ron_value(&ron_some(ron_int(1)));
150 assert!(s.starts_with("Some("));
151 }
152
153 #[test]
154 fn test_ron_struct() {
155 let v = ron_struct("Foo", vec![("x".to_string(), ron_int(1))]);
156 let s = render_ron_value(&v);
157 assert!(s.contains("Foo"));
158 }
159
160 #[test]
161 fn test_export_ron_nonempty() {
162 let v = ron_bool(false);
163 assert!(!export_ron(&v).is_empty());
164 }
165
166 #[test]
167 fn test_validate_ron_value() {
168 assert!(validate_ron_value(&ron_float(1.0)));
169 }
170
171 #[test]
172 fn test_scene_to_ron() {
173 let v = scene_to_ron("MyScene", 5);
174 let s = render_ron_value(&v);
175 assert!(s.contains("MyScene"));
176 }
177}