oxihuman_export/
proto_text_export.rs1#![allow(dead_code)]
7
8#[allow(dead_code)]
10#[derive(Debug, Clone)]
11pub struct ProtoField {
12 pub name: String,
13 pub value: String,
14}
15
16#[allow(dead_code)]
18#[derive(Debug, Clone, Default)]
19pub struct ProtoMessage {
20 pub name: String,
21 pub fields: Vec<ProtoField>,
22 pub nested: Vec<ProtoMessage>,
23}
24
25#[allow(dead_code)]
27pub fn new_proto_message(name: &str) -> ProtoMessage {
28 ProtoMessage {
29 name: name.to_string(),
30 fields: Vec::new(),
31 nested: Vec::new(),
32 }
33}
34
35#[allow(dead_code)]
37pub fn add_proto_string(msg: &mut ProtoMessage, name: &str, value: &str) {
38 msg.fields.push(ProtoField {
39 name: name.to_string(),
40 value: format!("\"{}\"", value),
41 });
42}
43
44#[allow(dead_code)]
46pub fn add_proto_int(msg: &mut ProtoMessage, name: &str, value: i64) {
47 msg.fields.push(ProtoField {
48 name: name.to_string(),
49 value: value.to_string(),
50 });
51}
52
53#[allow(dead_code)]
55pub fn add_proto_float(msg: &mut ProtoMessage, name: &str, value: f64) {
56 msg.fields.push(ProtoField {
57 name: name.to_string(),
58 value: format!("{:.6}", value),
59 });
60}
61
62#[allow(dead_code)]
64pub fn add_proto_bool(msg: &mut ProtoMessage, name: &str, value: bool) {
65 msg.fields.push(ProtoField {
66 name: name.to_string(),
67 value: if value {
68 "true".to_string()
69 } else {
70 "false".to_string()
71 },
72 });
73}
74
75#[allow(dead_code)]
77pub fn add_proto_nested(msg: &mut ProtoMessage, nested: ProtoMessage) {
78 msg.nested.push(nested);
79}
80
81#[allow(dead_code)]
83pub fn proto_field_count(msg: &ProtoMessage) -> usize {
84 msg.fields.len()
85}
86
87#[allow(dead_code)]
89pub fn find_proto_field<'a>(msg: &'a ProtoMessage, name: &str) -> Option<&'a str> {
90 msg.fields
91 .iter()
92 .find(|f| f.name == name)
93 .map(|f| f.value.as_str())
94}
95
96#[allow(dead_code)]
98pub fn to_proto_text(msg: &ProtoMessage, indent: usize) -> String {
99 let pad = " ".repeat(indent);
100 let mut out = if msg.name.is_empty() {
101 String::new()
102 } else {
103 format!("{}{} {{\n", pad, msg.name)
104 };
105 for f in &msg.fields {
106 out.push_str(&format!("{} {}: {}\n", pad, f.name, f.value));
107 }
108 for n in &msg.nested {
109 out.push_str(&to_proto_text(n, indent + 1));
110 }
111 if !msg.name.is_empty() {
112 out.push_str(&format!("{}}}\n", pad));
113 }
114 out
115}
116
117#[allow(dead_code)]
119pub fn export_mesh_stats_proto(vertex_count: usize, index_count: usize, name: &str) -> String {
120 let mut msg = new_proto_message("Mesh");
121 add_proto_string(&mut msg, "name", name);
122 add_proto_int(&mut msg, "vertex_count", vertex_count as i64);
123 add_proto_int(&mut msg, "index_count", index_count as i64);
124 to_proto_text(&msg, 0)
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn test_new_proto_message_empty() {
133 let msg = new_proto_message("Foo");
134 assert_eq!(proto_field_count(&msg), 0);
135 }
136
137 #[test]
138 fn test_add_string() {
139 let mut msg = new_proto_message("M");
140 add_proto_string(&mut msg, "name", "test");
141 assert_eq!(proto_field_count(&msg), 1);
142 }
143
144 #[test]
145 fn test_add_int() {
146 let mut msg = new_proto_message("M");
147 add_proto_int(&mut msg, "count", 42);
148 assert_eq!(find_proto_field(&msg, "count"), Some("42"));
149 }
150
151 #[test]
152 fn test_add_float() {
153 let mut msg = new_proto_message("M");
154 add_proto_float(&mut msg, "scale", 1.0);
155 assert!(find_proto_field(&msg, "scale").is_some());
156 }
157
158 #[test]
159 fn test_add_bool() {
160 let mut msg = new_proto_message("M");
161 add_proto_bool(&mut msg, "enabled", true);
162 assert_eq!(find_proto_field(&msg, "enabled"), Some("true"));
163 }
164
165 #[test]
166 fn test_to_proto_text_contains_name() {
167 let msg = new_proto_message("Mesh");
168 let s = to_proto_text(&msg, 0);
169 assert!(s.contains("Mesh"));
170 }
171
172 #[test]
173 fn test_to_proto_text_contains_field() {
174 let mut msg = new_proto_message("M");
175 add_proto_int(&mut msg, "vertices", 100);
176 let s = to_proto_text(&msg, 0);
177 assert!(s.contains("vertices: 100"));
178 }
179
180 #[test]
181 fn test_nested_message() {
182 let mut outer = new_proto_message("Outer");
183 let mut inner = new_proto_message("inner");
184 add_proto_string(&mut inner, "k", "v");
185 add_proto_nested(&mut outer, inner);
186 let s = to_proto_text(&outer, 0);
187 assert!(s.contains("inner"));
188 }
189
190 #[test]
191 fn test_export_mesh_stats_proto() {
192 let s = export_mesh_stats_proto(100, 300, "body");
193 assert!(s.contains("vertex_count"));
194 assert!(s.contains("body"));
195 }
196
197 #[test]
198 fn test_find_missing_field() {
199 let msg = new_proto_message("M");
200 assert!(find_proto_field(&msg, "ghost").is_none());
201 }
202}