erased_cells/
encoding.rs

1use super::*;
2use num_traits::{One, Zero};
3use std::fmt::Debug;
4
5/// Trait for marking Rust primitives as having a corresponding [`CellType`].
6///
7/// For example, [`f64`] is [`CellEncoding`] through [`CellType::Float64`],
8/// but [`isize`] is not `CellEncoding`.
9pub trait CellEncoding: Copy + Debug + Default + Zero + One + PartialEq {
10    /// Returns the [`CellType`] covering `Self`.
11    fn cell_type() -> CellType;
12    /// Converts `self` into a [`CellValue`].
13    fn into_cell_value(self) -> CellValue;
14    /// Convert dynamic type to static type when logically known.
15    /// Returns `None` if given value isn't actually the <u>exact</u> same
16    /// type as encoding.
17    fn static_cast<T: CellEncoding + Sized>(value: T) -> Option<Self> {
18        if Self::cell_type() == T::cell_type() {
19            Some(unsafe { std::mem::transmute_copy::<T, Self>(&value) })
20        } else {
21            None
22        }
23    }
24}
25
26/// Implements [`CellEncoding`] for each cell type.
27macro_rules! encoding {
28    ( $( ($ct:ident, $prim:ident) ),* ) => { $(
29        impl CellEncoding for $prim {
30            fn cell_type() -> CellType {
31                CellType::$ct
32            }
33            fn into_cell_value(self) -> CellValue {
34                CellValue::$ct(self)
35            }
36        } )*
37    };
38}
39
40with_ct!(encoding);
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    #[test]
46    fn casting() {
47        assert!(<f64>::static_cast(34f64).is_some());
48        assert!(<f64>::static_cast(34f32).is_none());
49    }
50}