1use crate::Timestamp;
4use rrd_sys::rrd_double;
5use std::{fmt, ops::Deref, time::Duration};
6
7pub struct Data<T> {
11 start: Timestamp,
12 end: Timestamp,
13 step: Duration,
14 names: Vec<String>,
15 data: T,
16 row_count: usize,
17}
18
19impl<T> Data<T>
20where
21 T: Deref<Target = [rrd_double]>,
22{
23 pub(crate) fn new(
24 start: Timestamp,
25 end: Timestamp,
26 step: Duration,
27 names: Vec<String>,
28 data: T,
29 ) -> Self {
30 assert_eq!(data.len() % names.len(), 0);
31 let row_count = data.len() / names.len();
32 Self {
33 start,
34 end,
35 step,
36 names,
37 data,
38 row_count,
39 }
40 }
41
42 pub fn start(&self) -> Timestamp {
44 self.start
45 }
46
47 pub fn end(&self) -> Timestamp {
49 self.end
50 }
51
52 pub fn step(&self) -> Duration {
54 self.step
55 }
56
57 pub fn row_count(&self) -> usize {
59 self.row_count
60 }
61
62 pub fn ds_names(&self) -> &[String] {
66 &self.names
67 }
68
69 pub fn rows(&self) -> Rows<'_, T> {
71 Rows { data: self }
72 }
73}
74
75pub struct Rows<'data, T> {
77 data: &'data Data<T>,
78}
79
80impl<'data, T> Rows<'data, T>
81where
82 T: Deref<Target = [rrd_double]>,
83{
84 pub fn len(&self) -> usize {
86 self.data.row_count()
87 }
88
89 pub fn is_empty(&self) -> bool {
91 self.data.row_count() == 0
92 }
93
94 pub fn iter(&self) -> RowsIter<'data, T> {
96 RowsIter::new(self.data)
97 }
98}
99
100impl<'data, T> IntoIterator for Rows<'data, T>
101where
102 T: Deref<Target = [rrd_double]>,
103{
104 type Item = Row<'data, T>;
105
106 type IntoIter = RowsIter<'data, T>;
107
108 fn into_iter(self) -> Self::IntoIter {
109 RowsIter::new(self.data)
110 }
111}
112
113impl<T> fmt::Debug for Rows<'_, T>
114where
115 T: Deref<Target = [rrd_double]> + fmt::Debug,
116{
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.debug_list().entries(self.iter()).finish()
119 }
120}
121
122pub struct RowsIter<'data, T> {
126 data: &'data Data<T>,
127 max_index: usize,
128 next_index: usize,
129}
130
131impl<'data, T> RowsIter<'data, T>
132where
133 T: Deref<Target = [rrd_double]>,
134{
135 fn new(data: &'data Data<T>) -> Self {
136 Self {
137 data,
138 max_index: data.row_count(),
139 next_index: 0,
140 }
141 }
142}
143
144impl<'data, T> Iterator for RowsIter<'data, T>
145where
146 T: Deref<Target = [rrd_double]>,
147{
148 type Item = Row<'data, T>;
149
150 fn next(&mut self) -> Option<Self::Item> {
151 if self.next_index < self.max_index {
152 let index = self.next_index;
153 self.next_index += 1;
154 Some(Row::new(self.data, index))
155 } else {
156 None
157 }
158 }
159
160 fn size_hint(&self) -> (usize, Option<usize>) {
161 (self.max_index, Some(self.max_index))
162 }
163}
164
165impl<T> ExactSizeIterator for RowsIter<'_, T> where T: Deref<Target = [rrd_double]> {}
166
167pub struct Row<'data, T> {
169 data: &'data Data<T>,
170 data_offset: usize,
171 timestamp: Timestamp,
172}
173
174impl<'data, T> Row<'data, T>
175where
176 T: Deref<Target = [rrd_double]>,
177{
178 fn new(data: &'data Data<T>, row_index: usize) -> Self {
179 Self {
180 data,
181 data_offset: data.names.len() * row_index,
182 timestamp: data.start()
183 + data.step() * row_index.try_into().expect("Row index exceeds u32"),
184 }
185 }
186
187 pub fn timestamp(&self) -> Timestamp {
189 self.timestamp
190 }
191
192 pub fn as_slice(&self) -> &[f64] {
196 &self.data.data.as_ref()[self.data_offset..self.data_offset + self.data.names.len()]
197 }
198
199 pub fn iter_cells(&self) -> impl Iterator<Item = Cell<'_>> {
201 self.data
202 .names
203 .iter()
204 .zip(self.as_slice())
205 .map(|(name, value)| Cell {
206 name,
207 value: *value,
208 })
209 }
210}
211
212impl<T> Deref for Row<'_, T>
213where
214 T: Deref<Target = [rrd_double]>,
215{
216 type Target = [rrd_double];
217
218 fn deref(&self) -> &Self::Target {
219 self.as_slice()
220 }
221}
222
223impl<T> fmt::Debug for Row<'_, T>
224where
225 T: Deref<Target = [rrd_double]>,
226{
227 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228 struct RowDataDebug<'d> {
229 row_data: &'d [rrd_double],
230 }
231 impl fmt::Debug for RowDataDebug<'_> {
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 f.debug_list().entries(self.row_data.iter()).finish()
234 }
235 }
236
237 f.debug_struct("Row")
238 .field("ts", &self.timestamp)
239 .field("ts_int", &self.timestamp.timestamp())
240 .field(
241 "data",
242 &RowDataDebug {
243 row_data: self.as_slice(),
244 },
245 )
246 .finish()
247 }
248}
249
250#[derive(Debug)]
252pub struct Cell<'data> {
253 pub name: &'data str,
255 pub value: f64,
257}