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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::io::{self,Write,BufWriter,Seek,SeekFrom};
use std::fs::File;
use std::path::Path;
use std::marker::PhantomData;
use byteorder::{WriteBytesExt, LittleEndian};
use serializable::Serializable;
use header::DType;
const FILLER: &'static [u8] = &[42; 19];
pub struct OutFile<Row: Serializable> {
shape_pos: usize,
len: usize,
fw: BufWriter<File>,
_t: PhantomData<Row>
}
impl<Row: Serializable> OutFile<Row> {
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
let dtype = Row::dtype();
if let &DType::Plain { ref shape, .. } = &dtype {
assert!(shape.len() == 0, "plain non-scalar dtypes not supported");
}
let mut fw = BufWriter::new(File::create(path)?);
fw.write_all(&[0x93u8])?;
fw.write_all(b"NUMPY")?;
fw.write_all(&[0x01u8, 0x00])?;
let (header, shape_pos) = create_header(&dtype);
let mut padding: Vec<u8> = vec![];
padding.extend(&::std::iter::repeat(b' ').take(15 - ((header.len() + 10) % 16)).collect::<Vec<_>>());
padding.extend(&[b'\n']);
let len = header.len() + padding.len();
assert! (len <= ::std::u16::MAX as usize);
assert_eq!((len + 10) % 16, 0);
fw.write_u16::<LittleEndian>(len as u16)?;
fw.write_all(&header)?;
fw.write_all(&padding)?;
Ok(OutFile {
shape_pos: shape_pos,
len: 0,
fw: fw,
_t: PhantomData,
})
}
pub fn push(&mut self, row: &Row) -> io::Result<()> {
self.len += 1;
row.write(&mut self.fw)
}
fn close_(&mut self) -> io::Result<()> {
self.fw.seek(SeekFrom::Start(self.shape_pos as u64))?;
let length = format!("{}", self.len);
self.fw.write_all(length.as_bytes())?;
self.fw.write_all(&b",), }"[..])?;
self.fw.write_all(&::std::iter::repeat(b' ').take(FILLER.len() - length.len()).collect::<Vec<_>>())?;
Ok(())
}
pub fn close(mut self) -> io::Result<()> {
self.close_()
}
}
fn create_header(dtype: &DType) -> (Vec<u8>, usize) {
let mut header: Vec<u8> = vec![];
header.extend(&b"{'descr': "[..]);
header.extend(dtype.descr().as_bytes());
header.extend(&b", 'fortran_order': False, 'shape': ("[..]);
let shape_pos = header.len() + 10;
header.extend(FILLER);
header.extend(&b",), }"[..]);
(header, shape_pos)
}
impl<Row: Serializable> Drop for OutFile<Row> {
fn drop(&mut self) {
let _ = self.close_();
}
}
pub fn to_file<'a, S, T, P>(filename: P, data: T) -> ::std::io::Result<()> where
P: AsRef<Path>,
S: Serializable + 'a,
T: IntoIterator<Item=S> {
let mut of = OutFile::open(filename)?;
for row in data {
of.push(&row)?;
}
of.close()
}