array_object/convert/
into_real.rs

1use crate::adaptor::*;
2use crate::error::ArrayObjectError;
3use crate::storage::*;
4
5macro_rules! into_float {
6    ($($ty:tt),*) => {
7        $(
8            impl TryFrom<ArrayObject> for $ty {
9                type Error = ArrayObjectError;
10                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
11                    if !val.shape.is_empty() || val.datatype != DataType::Real {
12                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
13                    }
14                    match val.data.len() {
15                        4 => {
16                            let data = f32::from_le_bytes(val.data.try_into().unwrap()) as $ty;
17                            Ok(data)
18                        }
19                        8 => {
20                            #[cfg(not(feature = "allow_float_down_convert"))]
21                            if size_of::<$ty>() < 8 {
22                                return Err(ArrayObjectError::LossyConversion);
23                            }
24                            let data = f64::from_le_bytes(val.data.try_into().unwrap()) as $ty;
25                            Ok(data)
26                        }
27                        _ => {panic!();}
28                    }
29                }
30            }
31            impl TryFrom<ArrayObject> for VecShape<$ty> {
32                type Error = ArrayObjectError;
33                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
34                    if val.shape.is_empty() || val.datatype != DataType::Real {
35                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
36                    }
37                    let len = val.len();
38                    if len == 0 {
39                        return Ok(VecShape(vec![], val.shape));
40                    }
41                    match val.data.len() / len {
42                        4 => {
43                            let data = val.data.chunks(4).map(|b| f32::from_le_bytes(b.try_into().unwrap()) as $ty).collect();
44                            Ok(VecShape(data, val.shape))
45                        }
46                        8 => {
47                            #[cfg(not(feature = "allow_float_down_convert"))]
48                            if size_of::<$ty>() < 8 {
49                                return Err(ArrayObjectError::LossyConversion);
50                            }
51                            let data = val.data.chunks(8).map(|b| f64::from_le_bytes(b.try_into().unwrap()) as $ty).collect();
52                            Ok(VecShape(data, val.shape))
53                        }
54                        _ => {panic!();}
55                    }
56                }
57            }
58            impl TryFrom<ArrayObject> for Vec<$ty> {
59                type Error = ArrayObjectError;
60                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
61                    if val.shape.len() != 1 {
62                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
63                    }
64                    let VecShape::<$ty>(data, _) = val.try_into()?;
65                    Ok(data)
66                }
67            }
68            impl<const N: usize> TryFrom<ArrayObject> for [$ty; N] {
69                type Error = ArrayObjectError;
70                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
71                    if val.len() != N {
72                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
73                    }
74                    let data: Vec<$ty> = val.try_into()?;
75                    Ok(data.try_into().unwrap())
76                }
77            }
78        )*
79    };
80}
81
82into_float!(f32, f64);