Skip to main content

ploteria/
data.rs

1#![allow(deprecated)]
2
3use std::mem;
4
5use byteorder::{LittleEndian, WriteBytesExt};
6use cast::From as _0;
7
8use traits::Data;
9
10macro_rules! impl_data {
11    ($($ty:ty),+) => {
12        $(
13            impl Data for $ty {
14                fn f64(self) -> f64 {
15                    f64::cast(self)
16                }
17            }
18
19            impl<'a> Data for &'a $ty {
20                fn f64(self) -> f64 {
21                    f64::cast(*self)
22                }
23            }
24        )+
25    }
26}
27
28impl_data!(f32, f64, i16, i32, i64, i8, isize, u16, u32, u64, u8, usize);
29
30#[derive(Clone)]
31pub struct Matrix {
32    bytes: Vec<u8>,
33    ncols: usize,
34    nrows: usize,
35}
36
37impl Matrix {
38    pub fn new<I>(rows: I, scale: <I::Item as Row>::Scale) -> Matrix
39    where
40        I: Iterator,
41        I::Item: Row,
42    {
43        let ncols = I::Item::ncols();
44        let bytes_per_row = ncols * mem::size_of::<f64>();
45        let mut bytes = Vec::with_capacity(rows.size_hint().0 * bytes_per_row);
46
47        let mut nrows = 0;
48        for row in rows {
49            nrows += 1;
50            row.append_to(&mut bytes, scale);
51        }
52
53        Matrix {
54            bytes,
55            ncols,
56            nrows,
57        }
58    }
59
60    pub fn bytes(&self) -> &[u8] {
61        &self.bytes
62    }
63
64    pub fn ncols(&self) -> usize {
65        self.ncols
66    }
67
68    pub fn nrows(&self) -> usize {
69        self.nrows
70    }
71}
72
73/// Data that can serve as a row of the data matrix
74pub trait Row {
75    /// Private
76    type Scale: Copy;
77
78    /// Append this row to a buffer
79    fn append_to(self, buffer: &mut Vec<u8>, scale: Self::Scale);
80    /// Number of columns of the row
81    fn ncols() -> usize;
82}
83
84impl<A, B> Row for (A, B)
85where
86    A: Data,
87    B: Data,
88{
89    type Scale = (f64, f64);
90
91    fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64)) {
92        let (a, b) = self;
93
94        buffer.write_f64::<LittleEndian>(a.f64() * scale.0).unwrap();
95        buffer.write_f64::<LittleEndian>(b.f64() * scale.1).unwrap();
96    }
97
98    fn ncols() -> usize {
99        2
100    }
101}
102
103impl<A, B, C> Row for (A, B, C)
104where
105    A: Data,
106    B: Data,
107    C: Data,
108{
109    type Scale = (f64, f64, f64);
110
111    fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64)) {
112        let (a, b, c) = self;
113
114        buffer.write_f64::<LittleEndian>(a.f64() * scale.0).unwrap();
115        buffer.write_f64::<LittleEndian>(b.f64() * scale.1).unwrap();
116        buffer.write_f64::<LittleEndian>(c.f64() * scale.2).unwrap();
117    }
118
119    fn ncols() -> usize {
120        3
121    }
122}
123
124impl<A, B, C, D> Row for (A, B, C, D)
125where
126    A: Data,
127    B: Data,
128    C: Data,
129    D: Data,
130{
131    type Scale = (f64, f64, f64, f64);
132
133    fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64, f64)) {
134        let (a, b, c, d) = self;
135
136        buffer.write_f64::<LittleEndian>(a.f64() * scale.0).unwrap();
137        buffer.write_f64::<LittleEndian>(b.f64() * scale.1).unwrap();
138        buffer.write_f64::<LittleEndian>(c.f64() * scale.2).unwrap();
139        buffer.write_f64::<LittleEndian>(d.f64() * scale.3).unwrap();
140    }
141
142    fn ncols() -> usize {
143        4
144    }
145}
146
147impl<A, B, C, D, E> Row for (A, B, C, D, E)
148where
149    A: Data,
150    B: Data,
151    C: Data,
152    D: Data,
153    E: Data,
154{
155    type Scale = (f64, f64, f64, f64, f64);
156
157    #[allow(clippy::many_single_char_names)]
158    fn append_to(self, buffer: &mut Vec<u8>, scale: (f64, f64, f64, f64, f64)) {
159        let (a, b, c, d, e) = self;
160
161        buffer.write_f64::<LittleEndian>(a.f64() * scale.0).unwrap();
162        buffer.write_f64::<LittleEndian>(b.f64() * scale.1).unwrap();
163        buffer.write_f64::<LittleEndian>(c.f64() * scale.2).unwrap();
164        buffer.write_f64::<LittleEndian>(d.f64() * scale.3).unwrap();
165        buffer.write_f64::<LittleEndian>(e.f64() * scale.4).unwrap();
166    }
167
168    fn ncols() -> usize {
169        5
170    }
171}