1#[cfg(feature = "wasm")]
8use wasm_bindgen::prelude::*;
9
10use crate::{composition::CompKey, fpd::FpdKey, properties::PropKey};
11
12pub trait KeyAsStrings {
14 fn as_med_str(&self) -> &'static str;
16}
17
18impl KeyAsStrings for CompKey {
19 fn as_med_str(&self) -> &'static str {
20 match self {
21 Self::Energy => "Energy",
22
23 Self::MilkFat => "Milk Fat",
24 Self::MSNF => "MSNF",
25 Self::MilkSNFS => "Milk SNFS",
26 Self::MilkProteins => "Milk Proteins",
27 Self::MilkSolids => "Milk Solids",
28
29 Self::CocoaButter => "Cocoa Butter",
30 Self::CocoaSolids => "Cocoa Solids",
31 Self::CacaoSolids => "Cacao Solids",
32
33 Self::NutFat => "Nut Fat",
34 Self::NutSNF => "Nut SNF",
35 Self::NutSolids => "Nut Solids",
36
37 Self::EggFat => "Egg Fat",
38 Self::EggSNF => "Egg SNF",
39 Self::EggSolids => "Egg Solids",
40
41 Self::OtherFats => "Other Fats",
42 Self::OtherSNFS => "Other SNFS",
43
44 Self::TotalFats => "T. Fats",
45 Self::TotalSNF => "T. SNF",
46 Self::TotalSNFS => "T. SNFS",
47 Self::TotalProteins => "T. Proteins",
48 Self::TotalSolids => "T. Solids",
49
50 Self::Water => "Water",
51
52 Self::Fiber => "Fiber",
53 Self::Glucose => "Glucose",
54 Self::Fructose => "Fructose",
55 Self::Galactose => "Galactose",
56 Self::Sucrose => "Sucrose",
57 Self::Lactose => "Lactose",
58 Self::Maltose => "Maltose",
59 Self::Trehalose => "Trehalose",
60 Self::TotalSugars => "T. Sugars",
61 Self::Erythritol => "Erythritol",
62 Self::TotalPolyols => "T. Polyols",
63 Self::TotalArtificial => "T. Artificial",
64 Self::TotalSweeteners => "T. Sweeteners",
65 Self::TotalCarbohydrates => "T. Carbohydrates",
66
67 Self::Alcohol => "Alcohol",
68 Self::ABV => "ABV",
69
70 Self::Salt => "Salt",
71 Self::Lecithin => "Lecithin",
72 Self::Emulsifiers => "Emulsifiers",
73 Self::Stabilizers => "Stabilizers",
74 Self::EmulsifiersPerFat => "Emul./Fat",
75 Self::StabilizersPerWater => "Stab./Water",
76
77 Self::POD => "POD",
78
79 Self::PACsgr => "PACsgr",
80 Self::PACslt => "PACslt",
81 Self::PACmlk => "PACmlk",
82 Self::PACalc => "PACalc",
83 Self::PACtotal => "PAC",
84 Self::AbsPAC => "Abs.PAC",
85 Self::HF => "HF",
86 }
87 }
88}
89
90impl KeyAsStrings for FpdKey {
91 fn as_med_str(&self) -> &'static str {
92 match self {
93 Self::FPD => "FPD",
94 Self::ServingTemp => "Serving Temp",
95 Self::HardnessAt14C => "Hardness @-14°C",
96 }
97 }
98}
99
100impl KeyAsStrings for PropKey {
101 fn as_med_str(&self) -> &'static str {
102 match self {
103 Self::CompKey(comp_key) => comp_key.as_med_str(),
104 Self::FpdKey(fpd_key) => fpd_key.as_med_str(),
105 }
106 }
107}
108
109#[cfg_attr(feature = "wasm", wasm_bindgen)]
126#[must_use]
127pub fn composition_value_as_quantity(comp: f64, qty: f64) -> f64 {
128 (comp * qty) / 100.0
129}
130
131#[cfg_attr(feature = "wasm", wasm_bindgen)]
150#[must_use]
151pub fn composition_value_as_percentage(comp: f64, int_qty: f64, mix_total: f64) -> f64 {
152 (comp * int_qty) / mix_total
153}
154
155#[cfg(feature = "wasm")]
157#[cfg_attr(coverage, coverage(off))]
158pub mod wasm {
159 use wasm_bindgen::prelude::*;
160
161 use super::{CompKey, FpdKey, KeyAsStrings};
162
163 #[wasm_bindgen]
165 #[must_use]
166 pub fn comp_key_as_med_str(key: CompKey) -> String {
167 key.as_med_str().to_string()
168 }
169
170 #[wasm_bindgen]
172 #[must_use]
173 pub fn fpd_key_as_med_str(key: FpdKey) -> String {
174 key.as_med_str().to_string()
175 }
176}
177
178#[cfg(test)]
179#[cfg_attr(coverage, coverage(off))]
180#[allow(clippy::float_cmp)]
181mod tests {
182 use std::collections::HashSet;
183
184 use strum::IntoEnumIterator;
185
186 use crate::tests::asserts::shadow_asserts::assert_eq;
187 use crate::tests::asserts::*;
188
189 use super::*;
190
191 #[test]
192 fn comp_keys_as_med_str() {
193 let some_expected = vec![
194 "Energy",
195 "Milk Fat",
196 "MSNF",
197 "Milk SNFS",
198 "Milk Proteins",
199 "Milk Solids",
200 "Cocoa Butter",
201 "Cocoa Solids",
202 "Cacao Solids",
203 "Nut Fat",
204 "Nut SNF",
205 "Nut Solids",
206 "Egg Fat",
207 "Egg SNF",
208 "Egg Solids",
209 "Other Fats",
210 "Other SNFS",
211 "T. Fats",
212 "T. SNF",
213 "T. SNFS",
214 "T. Proteins",
215 "T. Solids",
216 "Water",
217 "Fiber",
218 "Glucose",
219 "Fructose",
220 "Galactose",
221 "Sucrose",
222 "Lactose",
223 "Maltose",
224 "Trehalose",
225 "T. Sugars",
226 "Erythritol",
227 "T. Polyols",
228 "T. Artificial",
229 "T. Sweeteners",
230 "T. Carbohydrates",
231 "Alcohol",
232 "ABV",
233 "Salt",
234 "Lecithin",
235 "Emulsifiers",
236 "Stabilizers",
237 "Emul./Fat",
238 "Stab./Water",
239 "POD",
240 "PACsgr",
241 "PACslt",
242 "PACmlk",
243 "PACalc",
244 "PAC",
245 "Abs.PAC",
246 "HF",
247 ];
248
249 let actual_set: HashSet<&'static str> = CompKey::iter().map(|h| h.as_med_str()).collect();
250
251 for expected in some_expected {
252 assert_true!(actual_set.contains(expected));
253 }
254 }
255
256 #[test]
257 fn fpd_keys_as_med_str() {
258 let expected_vec = vec!["FPD", "Serving Temp", "Hardness @-14°C"];
259
260 let actual_vec: Vec<&'static str> = FpdKey::iter().map(|h| h.as_med_str()).collect();
261 assert_eq!(actual_vec, expected_vec);
262 }
263
264 #[test]
265 fn prop_keys_as_med_str() {
266 assert_eq!(PropKey::CompKey(CompKey::MilkFat).as_med_str(), "Milk Fat");
267 assert_eq!(PropKey::FpdKey(FpdKey::FPD).as_med_str(), "FPD");
268 }
269
270 #[test]
271 fn composition_value_as_quantity() {
272 let comp = 2.0; let qty = 500.0;
274 let qty_result = super::composition_value_as_quantity(comp, qty);
275 assert_eq!(qty_result, 10.0);
276 }
277
278 #[test]
279 fn composition_value_as_percentage() {
280 let comp = 2.0; let ing_qty = 500.0;
282 let mix_total = 1000.0;
283 let milk_fat_percentage = super::composition_value_as_percentage(comp, ing_qty, mix_total);
284 assert_eq!(milk_fat_percentage, 1.0);
285 }
286}