array_object/convert/
into_real.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::adaptor::*;
use crate::error::ArrayObjectError;
use crate::storage::*;

macro_rules! into_float {
    ($($ty:tt),*) => {
        $(
            impl TryFrom<ArrayObject> for $ty {
                type Error = ArrayObjectError;
                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
                    if !val.shape.is_empty() || val.datatype != DataType::Real {
                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
                    }
                    match val.data.len() {
                        4 => {
                            let data = f32::from_le_bytes(val.data.try_into().unwrap()) as $ty;
                            Ok(data)
                        }
                        8 => {
                            #[cfg(not(feature = "allow_float_down_convert"))]
                            if size_of::<$ty>() < 8 {
                                return Err(ArrayObjectError::LossyConversion);
                            }
                            let data = f64::from_le_bytes(val.data.try_into().unwrap()) as $ty;
                            Ok(data)
                        }
                        _ => {panic!();}
                    }
                }
            }
            impl TryFrom<ArrayObject> for VecShape<$ty> {
                type Error = ArrayObjectError;
                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
                    if val.shape.is_empty() || val.datatype != DataType::Real {
                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
                    }
                    let len = val.len();
                    if len == 0 {
                        return Ok(VecShape(vec![], val.shape));
                    }
                    match val.data.len() / len {
                        4 => {
                            let data = val.data.chunks(4).map(|b| f32::from_le_bytes(b.try_into().unwrap()) as $ty).collect();
                            Ok(VecShape(data, val.shape))
                        }
                        8 => {
                            #[cfg(not(feature = "allow_float_down_convert"))]
                            if size_of::<$ty>() < 8 {
                                return Err(ArrayObjectError::LossyConversion);
                            }
                            let data = val.data.chunks(8).map(|b| f64::from_le_bytes(b.try_into().unwrap()) as $ty).collect();
                            Ok(VecShape(data, val.shape))
                        }
                        _ => {panic!();}
                    }
                }
            }
            impl TryFrom<ArrayObject> for Vec<$ty> {
                type Error = ArrayObjectError;
                fn try_from(val: ArrayObject) -> Result<Self, Self::Error> {
                    if val.shape.len() != 1 {
                        return Err(ArrayObjectError::WrongDataType(val.datatype, val.shape.len()));
                    }
                    let VecShape::<$ty>(data, _) = val.try_into()?;
                    Ok(data)
                }
            }
        )*
    };
}

into_float!(f32, f64);