Skip to main content

sci_cream/
properties.rs

1//! Types that encapsulate various properties of ice cream mixes
2
3use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "wasm")]
6use wasm_bindgen::prelude::*;
7
8use crate::{
9    composition::{CompKey, Composition},
10    fpd::{FPD, FpdKey},
11};
12
13/// Keys for accessing specific property values from [`MixProperties`] via [`MixProperties::get()`]
14///
15/// This enum wraps both [`CompKey`] and [`FpdKey`] to allow accessing all properties from a single
16/// interface, which is helpful in downstream applications, to have a single flattened list of keys.
17/// There are [`From`] implementations for both key types to facilitate easy conversion.
18///
19/// # Example
20///
21/// ```
22/// use sci_cream::{CompKey, FpdKey, PropKey, MixProperties};
23/// let mix_props = MixProperties::empty();
24/// assert_eq!(mix_props.get(CompKey::MilkFat.into()), 0.0);
25/// assert_eq!(mix_props.get(FpdKey::FPD.into()), 0.0);
26/// ```
27#[derive(Hash, PartialEq, Eq, Serialize, Deserialize, Copy, Clone, Debug)]
28pub enum PropKey {
29    /// [`CompKey`] for [`Composition`] properties from [`MixProperties::composition`]
30    CompKey(CompKey),
31    /// [`FpdKey`] for [`FPD`] properties from [`MixProperties::fpd`]
32    FpdKey(FpdKey),
33}
34
35impl From<CompKey> for PropKey {
36    fn from(key: CompKey) -> Self {
37        Self::CompKey(key)
38    }
39}
40
41impl From<FpdKey> for PropKey {
42    fn from(key: FpdKey) -> Self {
43        Self::FpdKey(key)
44    }
45}
46
47/// Properties of an ice cream mix, including [`Composition`] and freezing point depression [`FPD`]
48#[cfg_attr(feature = "wasm", wasm_bindgen)]
49#[derive(Clone, Debug)]
50pub struct MixProperties {
51    /// Total amount of the mix in grams
52    pub total_amount: f64,
53    /// Composition properties of the mix
54    pub composition: Composition,
55    /// [Freezing Point Depression (FPD)](crate::docs#freezing-point-depression)
56    #[cfg_attr(feature = "wasm", wasm_bindgen(getter_with_clone))]
57    pub fpd: FPD,
58}
59
60impl MixProperties {
61    /// Creates an empty [`MixProperties`], with properties equivalent to those of 100% water.
62    #[must_use]
63    pub fn empty() -> Self {
64        Self {
65            total_amount: 0.0,
66            composition: Composition::empty(),
67            fpd: FPD::empty(),
68        }
69    }
70
71    /// Access specific mix property values via an [`PropKey`]
72    #[must_use]
73    pub fn get(&self, key: PropKey) -> f64 {
74        match key {
75            PropKey::CompKey(comp_key) => self.composition.get(comp_key),
76            PropKey::FpdKey(fpd_key) => self.fpd.get(fpd_key),
77        }
78    }
79}
80
81#[cfg_attr(feature = "wasm", wasm_bindgen)]
82impl MixProperties {
83    /// Creates a new empty [`MixProperties`], forwards to [`MixProperties::empty`].
84    #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
85    #[must_use]
86    pub fn new() -> Self {
87        Self::empty()
88    }
89}
90
91impl Default for MixProperties {
92    fn default() -> Self {
93        Self::empty()
94    }
95}