1use crate::Vec3;
8
9pub fn toml_f64(v: &toml::Value) -> Option<f64> {
11 v.as_float().or_else(|| v.as_integer().map(|i| i as f64))
12}
13
14pub fn toml_f32(v: &toml::Value) -> Option<f32> {
16 toml_f64(v).map(|f| f as f32)
17}
18
19pub fn toml_vec3(v: &toml::Value) -> Option<[f32; 3]> {
21 let arr = v.as_array()?;
22 if arr.len() >= 3 {
23 Some([toml_f32(&arr[0])?, toml_f32(&arr[1])?, toml_f32(&arr[2])?])
24 } else {
25 None
26 }
27}
28
29pub fn toml_vec4(v: &toml::Value) -> Option<[f32; 4]> {
31 let arr = v.as_array()?;
32 if arr.len() >= 4 {
33 Some([
34 toml_f32(&arr[0])?,
35 toml_f32(&arr[1])?,
36 toml_f32(&arr[2])?,
37 toml_f32(&arr[3])?,
38 ])
39 } else {
40 None
41 }
42}
43
44pub fn toml_color(v: &toml::Value) -> Option<[f32; 4]> {
46 let arr = v.as_array()?;
47 if arr.len() < 3 {
48 return None;
49 }
50 let r = toml_f32(&arr[0])?;
51 let g = toml_f32(&arr[1])?;
52 let b = toml_f32(&arr[2])?;
53 let a = if arr.len() >= 4 {
54 toml_f32(&arr[3]).unwrap_or(1.0)
55 } else {
56 1.0
57 };
58 Some([r, g, b, a])
59}
60
61pub fn toml_f32_slice(arr: &[toml::Value]) -> Option<Vec<f32>> {
63 arr.iter().map(toml_f32).collect()
64}
65
66pub fn toml_to_vec3(v: &toml::Value) -> Option<Vec3> {
69 if let Some(arr) = v.as_array() {
70 if arr.len() >= 3 {
71 return Some(Vec3::new(
72 toml_f32(&arr[0])?,
73 toml_f32(&arr[1])?,
74 toml_f32(&arr[2])?,
75 ));
76 }
77 }
78 if let Some(table) = v.as_table() {
79 let x = table.get("x").and_then(toml_f32)?;
80 let y = table.get("y").and_then(toml_f32)?;
81 let z = table.get("z").and_then(toml_f32)?;
82 return Some(Vec3::new(x, y, z));
83 }
84 None
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use toml::Value;
91
92 #[test]
93 fn f64_from_float() {
94 let v: Value = 3.14.into();
95 assert_eq!(toml_f64(&v), Some(3.14));
96 }
97
98 #[test]
99 fn f64_from_integer() {
100 let v: Value = 42.into();
101 assert_eq!(toml_f64(&v), Some(42.0));
102 }
103
104 #[test]
105 fn f64_from_string_returns_none() {
106 let v: Value = "hello".into();
107 assert_eq!(toml_f64(&v), None);
108 }
109
110 #[test]
111 fn f32_coercion() {
112 let v: Value = 1.5.into();
113 assert_eq!(toml_f32(&v), Some(1.5f32));
114 let v: Value = 7.into();
115 assert_eq!(toml_f32(&v), Some(7.0f32));
116 }
117
118 #[test]
119 fn vec3_from_array() {
120 let v: Value = toml::toml! { x = [1.0, 2, 3.5] }.get("x").unwrap().clone();
121 assert_eq!(toml_vec3(&v), Some([1.0, 2.0, 3.5]));
122 }
123
124 #[test]
125 fn vec3_too_short() {
126 let v: Value = toml::toml! { x = [1.0, 2.0] }.get("x").unwrap().clone();
127 assert_eq!(toml_vec3(&v), None);
128 }
129
130 #[test]
131 fn vec4_from_array() {
132 let v: Value = toml::toml! { x = [1, 2, 3, 4] }.get("x").unwrap().clone();
133 assert_eq!(toml_vec4(&v), Some([1.0, 2.0, 3.0, 4.0]));
134 }
135
136 #[test]
137 fn color_rgb_defaults_alpha() {
138 let v: Value = toml::toml! { c = [0.5, 0.6, 0.7] }
139 .get("c")
140 .unwrap()
141 .clone();
142 assert_eq!(toml_color(&v), Some([0.5, 0.6, 0.7, 1.0]));
143 }
144
145 #[test]
146 fn color_rgba() {
147 let v: Value = toml::toml! { c = [0.1, 0.2, 0.3, 0.4] }
148 .get("c")
149 .unwrap()
150 .clone();
151 assert_eq!(toml_color(&v), Some([0.1, 0.2, 0.3, 0.4]));
152 }
153
154 #[test]
155 fn f32_slice() {
156 let arr = vec![Value::from(1), Value::from(2.5), Value::from(3)];
157 assert_eq!(toml_f32_slice(&arr), Some(vec![1.0, 2.5, 3.0]));
158 }
159
160 #[test]
161 fn f32_slice_with_bad_element() {
162 let arr = vec![Value::from(1), Value::from("x")];
163 assert_eq!(toml_f32_slice(&arr), None);
164 }
165
166 #[test]
167 fn to_vec3_from_array() {
168 let v: Value = toml::toml! { p = [1, 2.0, 3] }.get("p").unwrap().clone();
169 assert_eq!(toml_to_vec3(&v), Some(Vec3::new(1.0, 2.0, 3.0)));
170 }
171
172 #[test]
173 fn to_vec3_from_table() {
174 let v: Value = toml::toml! {
175 [p]
176 x = 4
177 y = 5.0
178 z = 6
179 }
180 .get("p")
181 .unwrap()
182 .clone();
183 assert_eq!(toml_to_vec3(&v), Some(Vec3::new(4.0, 5.0, 6.0)));
184 }
185
186 #[test]
187 fn to_vec3_invalid() {
188 let v: Value = "not a vec3".into();
189 assert_eq!(toml_to_vec3(&v), None);
190 }
191}