ndarray_npy/npy/elements/
primitive.rs1use super::{bytes_as_mut_slice, bytes_as_slice, check_for_extra_bytes};
4use crate::{ReadDataError, ReadableElement, ViewDataError, ViewElement, ViewMutElement};
5use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
6use py_literal::Value as PyValue;
7use std::error::Error;
8use std::fmt;
9use std::io;
10use std::mem;
11
12macro_rules! impl_readable_primitive_one_byte {
13 ($elem:ty, [$($desc:expr),*], $zero:expr, $read_into:ident) => {
14 impl ReadableElement for $elem {
15 fn read_to_end_exact_vec<R: io::Read>(
16 mut reader: R,
17 type_desc: &PyValue,
18 len: usize,
19 ) -> Result<Vec<Self>, ReadDataError> {
20 match *type_desc {
21 PyValue::String(ref s) if $(s == $desc)||* => {
22 let mut out = vec![$zero; len];
23 reader.$read_into(&mut out)?;
24 check_for_extra_bytes(&mut reader)?;
25 Ok(out)
26 }
27 ref other => Err(ReadDataError::WrongDescriptor(other.clone())),
28 }
29 }
30 }
31 };
32}
33
34macro_rules! impl_view_and_view_mut_primitive_one_byte {
35 ($elem:ty, [$($desc:expr),*]) => {
36 impl ViewElement for $elem {
37 fn bytes_as_slice<'a>(
38 bytes: &'a [u8],
39 type_desc: &PyValue,
40 len: usize,
41 ) -> Result<&'a [Self], ViewDataError> {
42 match *type_desc {
43 PyValue::String(ref s) if $(s == $desc)||* => unsafe {
44 bytes_as_slice(bytes, len)
45 }
46 ref other => Err(ViewDataError::WrongDescriptor(other.clone())),
47 }
48 }
49 }
50
51 impl ViewMutElement for $elem {
52 fn bytes_as_mut_slice<'a>(
53 bytes: &'a mut [u8],
54 type_desc: &PyValue,
55 len: usize,
56 ) -> Result<&'a mut [Self], ViewDataError> {
57 match *type_desc {
58 PyValue::String(ref s) if $(s == $desc)||* => unsafe {
59 bytes_as_mut_slice(bytes, len)
60 }
61 ref other => Err(ViewDataError::WrongDescriptor(other.clone())),
62 }
63 }
64 }
65 };
66}
67
68macro_rules! impl_primitive_one_byte {
69 ($elem:ty, $write_desc:expr, [$($read_desc:expr),*], $zero:expr, $read_into:ident) => {
70 impl_writable_element_always_valid_cast!($elem, $write_desc, $write_desc);
71 impl_readable_primitive_one_byte!($elem, [$($read_desc),*], $zero, $read_into);
72 impl_view_and_view_mut_primitive_one_byte!($elem, [$($read_desc),*]);
73 };
74}
75
76impl_primitive_one_byte!(i8, "|i1", ["|i1", "i1", "b"], 0, read_i8_into);
77impl_primitive_one_byte!(u8, "|u1", ["|u1", "u1", "B"], 0, read_exact);
78
79macro_rules! impl_readable_primitive_multi_byte {
80 ($elem:ty, $little_desc:expr, $big_desc:expr, $zero:expr, $read_into:ident) => {
81 impl ReadableElement for $elem {
82 fn read_to_end_exact_vec<R: io::Read>(
83 mut reader: R,
84 type_desc: &PyValue,
85 len: usize,
86 ) -> Result<Vec<Self>, ReadDataError> {
87 let mut out = vec![$zero; len];
88 match *type_desc {
89 PyValue::String(ref s) if s == $little_desc => {
90 reader.$read_into::<LittleEndian>(&mut out)?;
91 }
92 PyValue::String(ref s) if s == $big_desc => {
93 reader.$read_into::<BigEndian>(&mut out)?;
94 }
95 ref other => {
96 return Err(ReadDataError::WrongDescriptor(other.clone()));
97 }
98 }
99 check_for_extra_bytes(&mut reader)?;
100 Ok(out)
101 }
102 }
103 };
104}
105
106macro_rules! impl_primitive_multi_byte {
107 ($elem:ty, $little_desc:expr, $big_desc:expr, $zero:expr, $read_into:ident) => {
108 impl_writable_element_always_valid_cast!($elem, $little_desc, $big_desc);
109 impl_readable_primitive_multi_byte!($elem, $little_desc, $big_desc, $zero, $read_into);
110 #[cfg(target_endian = "little")]
111 impl_view_and_view_mut_always_valid_cast_multi_byte!($elem, $little_desc, $big_desc);
112 #[cfg(target_endian = "big")]
113 impl_view_and_view_mut_always_valid_cast_multi_byte!($elem, $big_desc, $little_desc);
114 };
115}
116
117impl_primitive_multi_byte!(i16, "<i2", ">i2", 0, read_i16_into);
118impl_primitive_multi_byte!(i32, "<i4", ">i4", 0, read_i32_into);
119impl_primitive_multi_byte!(i64, "<i8", ">i8", 0, read_i64_into);
120
121impl_primitive_multi_byte!(u16, "<u2", ">u2", 0, read_u16_into);
122impl_primitive_multi_byte!(u32, "<u4", ">u4", 0, read_u32_into);
123impl_primitive_multi_byte!(u64, "<u8", ">u8", 0, read_u64_into);
124
125impl_primitive_multi_byte!(f32, "<f4", ">f4", 0., read_f32_into);
126impl_primitive_multi_byte!(f64, "<f8", ">f8", 0., read_f64_into);
127
128#[derive(Debug)]
130struct ParseBoolError {
131 bad_value: u8,
132}
133
134impl Error for ParseBoolError {
135 fn source(&self) -> Option<&(dyn Error + 'static)> {
136 None
137 }
138}
139
140impl fmt::Display for ParseBoolError {
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 write!(f, "error parsing value {:#04x} as a bool", self.bad_value)
143 }
144}
145
146impl From<ParseBoolError> for ReadDataError {
147 fn from(err: ParseBoolError) -> ReadDataError {
148 ReadDataError::ParseData(Box::new(err))
149 }
150}
151
152impl From<ParseBoolError> for ViewDataError {
153 fn from(err: ParseBoolError) -> ViewDataError {
154 ViewDataError::InvalidData(Box::new(err))
155 }
156}
157
158fn check_valid_for_bool(bytes: &[u8]) -> Result<(), ParseBoolError> {
166 for &byte in bytes {
167 if byte > 1 {
168 return Err(ParseBoolError { bad_value: byte });
169 }
170 }
171 Ok(())
172}
173
174impl ReadableElement for bool {
175 fn read_to_end_exact_vec<R: io::Read>(
176 mut reader: R,
177 type_desc: &PyValue,
178 len: usize,
179 ) -> Result<Vec<Self>, ReadDataError> {
180 match *type_desc {
181 PyValue::String(ref s) if s == "|b1" => {
182 let mut bytes: Vec<u8> = vec![0; len];
184 reader.read_exact(&mut bytes)?;
185 check_for_extra_bytes(&mut reader)?;
186
187 check_valid_for_bool(&bytes)?;
189
190 {
192 let ptr: *mut u8 = bytes.as_mut_ptr();
193 let len: usize = bytes.len();
194 let cap: usize = bytes.capacity();
195 mem::forget(bytes);
196 Ok(unsafe { Vec::from_raw_parts(ptr.cast::<bool>(), len, cap) })
209 }
210 }
211 ref other => Err(ReadDataError::WrongDescriptor(other.clone())),
212 }
213 }
214}
215
216impl_writable_element_always_valid_cast!(bool, "|b1", "|b1");
220
221impl ViewElement for bool {
222 fn bytes_as_slice<'a>(
223 bytes: &'a [u8],
224 type_desc: &PyValue,
225 len: usize,
226 ) -> Result<&'a [Self], ViewDataError> {
227 match *type_desc {
228 PyValue::String(ref s) if s == "|b1" => {
229 check_valid_for_bool(bytes)?;
230 unsafe { bytes_as_slice(bytes, len) }
231 }
232 ref other => Err(ViewDataError::WrongDescriptor(other.clone())),
233 }
234 }
235}
236
237impl ViewMutElement for bool {
238 fn bytes_as_mut_slice<'a>(
239 bytes: &'a mut [u8],
240 type_desc: &PyValue,
241 len: usize,
242 ) -> Result<&'a mut [Self], ViewDataError> {
243 match *type_desc {
244 PyValue::String(ref s) if s == "|b1" => {
245 check_valid_for_bool(bytes)?;
246 unsafe { bytes_as_mut_slice(bytes, len) }
247 }
248 ref other => Err(ViewDataError::WrongDescriptor(other.clone())),
249 }
250 }
251}