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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use super::check_for_extra_bytes;
use crate::{ReadDataError, ReadableElement};
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use num_complex_0_4::Complex;
use py_literal::Value as PyValue;
use std::io;
use std::mem;
use std::slice;
fn complex_slice_as_inner_slice_mut<T>(slice: &mut [Complex<T>]) -> &mut [T] {
assert!(mem::size_of::<T>() > 0);
assert_eq!(
mem::size_of::<Complex<T>>(),
mem::size_of::<T>().checked_mul(2).unwrap()
);
assert_eq!(mem::align_of::<Complex<T>>(), mem::align_of::<T>());
let inner_len = slice.len().checked_mul(2).unwrap();
unsafe { slice::from_raw_parts_mut(slice.as_mut_ptr().cast(), inner_len) }
}
macro_rules! impl_readable_complex_multi_byte {
($elem:ty, $little_desc:expr, $big_desc:expr, $zero:expr, $inner_read_into:ident) => {
impl ReadableElement for $elem {
fn read_to_end_exact_vec<R: io::Read>(
mut reader: R,
type_desc: &PyValue,
len: usize,
) -> Result<Vec<Self>, ReadDataError> {
let mut out = vec![$zero; len];
let inner_slice = complex_slice_as_inner_slice_mut(&mut out);
match *type_desc {
PyValue::String(ref s) if s == $little_desc => {
reader.$inner_read_into::<LittleEndian>(inner_slice)?;
}
PyValue::String(ref s) if s == $big_desc => {
reader.$inner_read_into::<BigEndian>(inner_slice)?;
}
ref other => {
return Err(ReadDataError::WrongDescriptor(other.clone()));
}
}
check_for_extra_bytes(&mut reader)?;
Ok(out)
}
}
};
}
macro_rules! impl_complex_multi_byte {
($elem:ty, $little_desc:expr, $big_desc:expr, $zero:expr, $inner_read_into:ident) => {
impl_writable_element_always_valid_cast!($elem, $little_desc, $big_desc);
impl_readable_complex_multi_byte!($elem, $little_desc, $big_desc, $zero, $inner_read_into);
#[cfg(target_endian = "little")]
impl_view_and_view_mut_always_valid_cast_multi_byte!($elem, $little_desc, $big_desc);
#[cfg(target_endian = "big")]
impl_view_and_view_mut_always_valid_cast_multi_byte!($elem, $big_desc, $little_desc);
};
}
impl_complex_multi_byte!(
Complex<f32>,
"<c8",
">c8",
Complex::new(0., 0.),
read_f32_into
);
impl_complex_multi_byte!(
Complex<f64>,
"<c16",
">c16",
Complex::new(0., 0.),
read_f64_into
);