npy/
serializable.rs

1
2use std::io::{Write,Result};
3use byteorder::{WriteBytesExt, LittleEndian};
4use header::DType;
5use byteorder::ByteOrder;
6
7/// This trait contains information on how to serialize and deserialize a type.
8///
9/// An example illustrating a `Serializable` implementation for a fixed-size vector is in
10/// [the roundtrip test](https://github.com/potocpav/npy-rs/tree/master/tests/roundtrip.rs).
11/// It is strongly advised to annotate the `Serializable` functions as `#[inline]` for good
12/// performance.
13pub trait Serializable : Sized {
14    /// Convert a type to a structure representing a Numpy type
15    fn dtype() -> DType;
16
17    /// Get the number of bytes of the binary repr
18    fn n_bytes() -> usize;
19
20    /// Deserialize a single data field, advancing the cursor in the process.
21    fn read(c: &[u8]) -> Self;
22
23    /// Serialize a single data field into a writer.
24    fn write<W: Write>(&self, writer: &mut W) -> Result<()>;
25}
26
27impl Serializable for i8 {
28    #[inline]
29    fn dtype() -> DType {
30        DType::Plain { ty: "<i1".to_string(), shape: vec![] }
31    }
32    #[inline]
33    fn n_bytes() -> usize { 1 }
34    #[inline]
35    fn read(buf: &[u8]) -> Self {
36        unsafe { ::std::mem::transmute(buf[0]) } // TODO: a better way
37    }
38    #[inline]
39    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
40        writer.write_i8(*self)
41    }
42}
43
44impl Serializable for i16 {
45    #[inline]
46    fn dtype() -> DType {
47        DType::Plain { ty: "<i2".to_string(), shape: vec![] }
48    }
49    #[inline]
50    fn n_bytes() -> usize { 2 }
51    #[inline]
52    fn read(buf: &[u8]) -> Self {
53        LittleEndian::read_i16(buf)
54    }
55    #[inline]
56    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
57        writer.write_i16::<LittleEndian>(*self)
58    }
59}
60
61impl Serializable for i32 {
62    #[inline]
63    fn dtype() -> DType {
64        DType::Plain { ty: "<i4".to_string(), shape: vec![] }
65    }
66    #[inline]
67    fn n_bytes() -> usize { 4 }
68    #[inline]
69    fn read(buf: &[u8]) -> Self {
70        LittleEndian::read_i32(buf)
71    }
72    #[inline]
73    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
74        writer.write_i32::<LittleEndian>(*self)
75    }
76}
77
78impl Serializable for i64 {
79    #[inline]
80    fn dtype() -> DType {
81        DType::Plain { ty: "<i8".to_string(), shape: vec![] }
82    }
83    #[inline]
84    fn n_bytes() -> usize { 8 }
85    #[inline]
86    fn read(buf: &[u8]) -> Self {
87        LittleEndian::read_i64(buf)
88    }
89    #[inline]
90    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
91        writer.write_i64::<LittleEndian>(*self)
92    }
93}
94
95impl Serializable for u8 {
96    #[inline]
97    fn dtype() -> DType {
98        DType::Plain { ty: "<u1".to_string(), shape: vec![] }
99    }
100    #[inline]
101    fn n_bytes() -> usize { 1 }
102    #[inline]
103    fn read(buf: &[u8]) -> Self {
104        buf[0]
105    }
106    #[inline]
107    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
108        writer.write_u8(*self)
109    }
110}
111
112impl Serializable for u16 {
113    #[inline]
114    fn dtype() -> DType {
115        DType::Plain { ty: "<u2".to_string(), shape: vec![] }
116    }
117    #[inline]
118    fn n_bytes() -> usize { 2 }
119    #[inline]
120    fn read(buf: &[u8]) -> Self {
121        LittleEndian::read_u16(buf)
122    }
123    #[inline]
124    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
125        writer.write_u16::<LittleEndian>(*self)
126    }
127}
128
129impl Serializable for u32 {
130    #[inline]
131    fn dtype() -> DType {
132        DType::Plain { ty: "<u4".to_string(), shape: vec![] }
133    }
134    #[inline]
135    fn n_bytes() -> usize { 4 }
136    #[inline]
137    fn read(buf: &[u8]) -> Self {
138        LittleEndian::read_u32(buf)
139    }
140    #[inline]
141    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
142        writer.write_u32::<LittleEndian>(*self)
143    }
144}
145
146impl Serializable for u64 {
147    #[inline]
148    fn dtype() -> DType {
149        DType::Plain { ty: "<u8".to_string(), shape: vec![] }
150    }
151    #[inline]
152    fn n_bytes() -> usize { 8 }
153    #[inline]
154    fn read(buf: &[u8]) -> Self {
155        LittleEndian::read_u64(buf)
156    }
157    #[inline]
158    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
159        writer.write_u64::<LittleEndian>(*self)
160    }
161}
162
163impl Serializable for f32 {
164    #[inline]
165    fn dtype() -> DType {
166        DType::Plain { ty: "<f4".to_string(), shape: vec![] }
167    }
168    #[inline]
169    fn n_bytes() -> usize { 4 }
170    #[inline]
171    fn read(buf: &[u8]) -> Self {
172        LittleEndian::read_f32(buf)
173    }
174    #[inline]
175    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
176        writer.write_f32::<LittleEndian>(*self)
177    }
178}
179
180impl Serializable for f64 {
181    #[inline]
182    fn dtype() -> DType {
183        DType::Plain { ty: "<f8".to_string(), shape: vec![] }
184    }
185    #[inline]
186    fn n_bytes() -> usize { 8 }
187    #[inline]
188    fn read(buf: &[u8]) -> Self {
189        LittleEndian::read_f64(buf)
190    }
191    #[inline]
192    fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
193        writer.write_f64::<LittleEndian>(*self)
194    }
195}
196
197macro_rules! gen_array_serializable {
198    ($($n:tt),+) => { $(
199        impl<T: Serializable + Default + Copy> Serializable for [T; $n] {
200            #[inline]
201            fn dtype() -> DType {
202                use DType::*;
203                match T::dtype() {
204                    Plain { ref ty, ref shape } => DType::Plain {
205                        ty: ty.clone(),
206                        shape: shape.clone().into_iter().chain(Some($n)).collect()
207                    },
208                    Record(_) => unimplemented!("arrays of nested records")
209                }
210            }
211            #[inline]
212            fn n_bytes() -> usize { T::n_bytes() * $n }
213            #[inline]
214            fn read(buf: &[u8]) -> Self {
215                let mut a = [T::default(); $n];
216                let mut off = 0;
217                for x in &mut a {
218                    *x = T::read(&buf[off..]);
219                    off += T::n_bytes();
220                }
221                a
222            }
223            #[inline]
224            fn write<W: Write>(&self, writer: &mut W) -> Result<()> {
225                for item in self {
226                    item.write(writer)?;
227                }
228                Ok(())
229            }
230        }
231    )+ }
232}
233
234gen_array_serializable!(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);