oxihuman_export/
sat_export.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct SatEntity {
10 pub index: u32,
11 pub entity_type: String,
12 pub fields: Vec<String>,
13}
14
15#[derive(Debug, Clone, Default)]
17pub struct SatExport {
18 pub header_version: u32,
19 pub entities: Vec<SatEntity>,
20 pub unit_scale: f64,
21}
22
23pub fn new_sat_export(version: u32, unit_scale: f64) -> SatExport {
25 SatExport {
26 header_version: version,
27 entities: Vec::new(),
28 unit_scale,
29 }
30}
31
32pub fn add_sat_entity(export: &mut SatExport, entity_type: &str, fields: Vec<String>) -> u32 {
34 let idx = export.entities.len() as u32;
35 export.entities.push(SatEntity {
36 index: idx,
37 entity_type: entity_type.to_string(),
38 fields,
39 });
40 idx
41}
42
43pub fn sat_entity_count(export: &SatExport) -> usize {
45 export.entities.len()
46}
47
48pub fn sat_header(export: &SatExport) -> String {
50 format!(
51 "{} 0 0 0\n400 0 1 0\n{}",
52 export.header_version, export.unit_scale
53 )
54}
55
56pub fn sat_entity_line(entity: &SatEntity) -> String {
58 format!(
59 "-{} {} {} #",
60 entity.index,
61 entity.entity_type,
62 entity.fields.join(" ")
63 )
64}
65
66pub fn find_sat_entity<'a>(export: &'a SatExport, entity_type: &str) -> Option<&'a SatEntity> {
68 export
69 .entities
70 .iter()
71 .find(|e| e.entity_type == entity_type)
72}
73
74pub fn validate_sat(export: &SatExport) -> bool {
76 export.entities.iter().all(|e| !e.entity_type.is_empty())
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_new_sat_export_empty() {
85 let exp = new_sat_export(700, 1.0);
86 assert_eq!(sat_entity_count(&exp), 0);
87 }
88
89 #[test]
90 fn test_add_entity_returns_index() {
91 let mut exp = new_sat_export(700, 1.0);
92 let idx = add_sat_entity(&mut exp, "body", vec![]);
93 assert_eq!(idx, 0);
94 }
95
96 #[test]
97 fn test_entity_count_increments() {
98 let mut exp = new_sat_export(700, 1.0);
99 add_sat_entity(&mut exp, "body", vec![]);
100 add_sat_entity(&mut exp, "lump", vec![]);
101 assert_eq!(sat_entity_count(&exp), 2);
102 }
103
104 #[test]
105 fn test_sat_header_contains_version() {
106 let exp = new_sat_export(700, 25.4);
107 assert!(sat_header(&exp).contains("700"));
108 }
109
110 #[test]
111 fn test_sat_entity_line_contains_type() {
112 let e = SatEntity {
113 index: 0,
114 entity_type: "face".into(),
115 fields: vec![],
116 };
117 assert!(sat_entity_line(&e).contains("face"));
118 }
119
120 #[test]
121 fn test_find_entity_existing() {
122 let mut exp = new_sat_export(700, 1.0);
123 add_sat_entity(&mut exp, "body", vec![]);
124 assert!(find_sat_entity(&exp, "body").is_some());
125 }
126
127 #[test]
128 fn test_find_entity_missing() {
129 let exp = new_sat_export(700, 1.0);
130 assert!(find_sat_entity(&exp, "body").is_none());
131 }
132
133 #[test]
134 fn test_validate_valid() {
135 let mut exp = new_sat_export(700, 1.0);
136 add_sat_entity(&mut exp, "body", vec![]);
137 assert!(validate_sat(&exp));
138 }
139
140 #[test]
141 fn test_unit_scale_stored() {
142 let exp = new_sat_export(700, 25.4);
143 assert!((exp.unit_scale - 25.4).abs() < 1e-9);
144 }
145
146 #[test]
147 fn test_version_stored() {
148 let exp = new_sat_export(700, 1.0);
149 assert_eq!(exp.header_version, 700);
150 }
151}