Skip to content

Commit 2c14ca2

Browse files
refactor: Clean Up and Simplify
Added the block skip into the plan which allowed for a great simplification in many places.
1 parent 7775945 commit 2c14ca2

5 files changed

Lines changed: 168 additions & 158 deletions

File tree

‎src/io/data_types/mod.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl Display for DataType {
119119

120120
type StorageResult<T> = std::result::Result<T, TdmsError>;
121121

122-
pub trait TdmsStorageType: Sized {
122+
pub trait TdmsStorageType: Sized + 'static {
123123
/// The [`DataType`] that can be read as this storage type.
124124
const SUPPORTED_TYPES: &'static [DataType];
125125
/// The [`DataType`] that this storage type is naturally written as.

‎src/raw_data/contigious_multi_channel_read.rs‎

Lines changed: 89 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ use std::{
1111
marker::PhantomData,
1212
};
1313

14-
/// The multichannel contigious reader will read from an contigous block.
14+
/// The multichannel contiguous reader will read from a contiguous block.
1515
///
1616
/// We will assume a single datatype as it is unclear if multiple types exist in the wild.
17-
pub struct MultiChannelContigousReader<R: Read + Seek, T: TdmsReader<R>> {
17+
pub struct MultiChannelContiguousReader<R: Read + Seek, T: TdmsReader<R>> {
1818
reader: T,
1919
_marker: PhantomData<R>,
2020
block_size: NonZeroU64,
2121
block_start: u64,
2222
}
2323

24-
impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContigousReader<R, T> {
24+
impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContiguousReader<R, T> {
2525
pub fn new(reader: T, block_start: u64, block_size: NonZeroU64) -> Self {
2626
Self {
2727
reader,
@@ -75,10 +75,28 @@ impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContigousReader<R, T> {
7575
self.reader.move_position(skip_bytes)?;
7676
} else if sub_block_idx == sub_blocks_to_skip {
7777
// First sub-block to read - apply remainder skip
78-
length += self.read_sub_block_with_offset(&mut channels, remainder_skip)?;
78+
for channel in channels.read_instructions() {
79+
if let RecordEntryPlan::Read {
80+
block_skip: skip_first_samples,
81+
..
82+
} = &mut channel.plan
83+
{
84+
*skip_first_samples = remainder_skip;
85+
}
86+
}
87+
length += self.read_sub_block(&mut channels)?;
7988
} else {
89+
for channel in channels.read_instructions() {
90+
if let RecordEntryPlan::Read {
91+
block_skip: skip_first_samples,
92+
..
93+
} = &mut channel.plan
94+
{
95+
*skip_first_samples = 0;
96+
}
97+
}
8098
// Subsequent sub-blocks - no skip
81-
length += self.read_sub_block_with_offset(&mut channels, 0)?;
99+
length += self.read_sub_block(&mut channels)?;
82100
}
83101
}
84102

@@ -109,7 +127,6 @@ impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContigousReader<R, T> {
109127
.collect();
110128

111129
let mut length = 0;
112-
let mut sub_block_skips = Vec::with_capacity(skip_amounts.len());
113130

114131
for sub_block_idx in 0..total_sub_blocks {
115132
// Check if any channel needs to read from this sub-block
@@ -121,40 +138,69 @@ impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContigousReader<R, T> {
121138
self.reader.move_position(skip_bytes)?;
122139
} else {
123140
// Build skip amounts for this sub-block
124-
sub_block_skips.clear();
125-
for (idx, &blocks_to_skip) in sub_blocks_to_skip.iter().enumerate() {
126-
if sub_block_idx == blocks_to_skip {
127-
// First sub-block to read for this channel - use remainder
128-
sub_block_skips.push(remainder_skips[idx]);
129-
} else if sub_block_idx > blocks_to_skip {
130-
// Subsequent sub-blocks - no skip
131-
sub_block_skips.push(0);
132-
} else {
133-
// Should not happen if any_channel_reads is correct
134-
sub_block_skips.push(0);
135-
}
141+
let channel_skip_values =
142+
channels
143+
.read_instructions()
144+
.iter_mut()
145+
.filter_map(|instruction| {
146+
if let RecordEntryPlan::Read {
147+
block_skip: skip_first_samples,
148+
..
149+
} = &mut instruction.plan
150+
{
151+
Some(skip_first_samples)
152+
} else {
153+
None
154+
}
155+
});
156+
for ((blocks_to_skip, remainder_skip), sub_block_skip) in sub_blocks_to_skip
157+
.iter()
158+
.zip(remainder_skips.iter())
159+
.zip(channel_skip_values)
160+
{
161+
*sub_block_skip = Self::calculate_skip_for_this_block(
162+
sub_block_idx,
163+
*blocks_to_skip,
164+
*remainder_skip,
165+
);
136166
}
137-
length +=
138-
self.read_sub_block_with_per_channel_skip(&mut channels, &sub_block_skips)?;
167+
length += self.read_sub_block(&mut channels)?;
139168
}
140169
}
141170

142171
Ok(length)
143172
}
144173

145-
fn read_sub_block_with_per_channel_skip<D: TdmsStorageType>(
174+
fn calculate_skip_for_this_block(
175+
sub_block_idx: u64,
176+
blocks_to_skip: u64,
177+
remainder_skip: u64,
178+
) -> u64 {
179+
if sub_block_idx == blocks_to_skip {
180+
// First sub-block to read for this channel - use remainder
181+
remainder_skip
182+
} else if sub_block_idx > blocks_to_skip {
183+
// Subsequent sub-blocks - no skip
184+
0
185+
} else {
186+
// Should not happen if any_channel_reads is correct
187+
0
188+
}
189+
}
190+
191+
fn read_sub_block<D: TdmsStorageType>(
146192
&mut self,
147193
channels: &mut RecordPlan<'_, D>,
148-
skip_amounts: &[u64],
149194
) -> Result<usize, TdmsError> {
150195
let mut length = 0;
151-
let mut skip_idx = 0;
152196

153197
for read_instruction in channels.read_instructions().iter_mut() {
154198
match &mut read_instruction.plan {
155-
RecordEntryPlan::Read(output) => {
156-
let skip = skip_amounts[skip_idx].min(read_instruction.length as u64) as usize;
157-
skip_idx += 1;
199+
RecordEntryPlan::Read {
200+
output,
201+
block_skip: skip_first_samples,
202+
} => {
203+
let skip = (*skip_first_samples).min(read_instruction.length as u64) as usize;
158204

159205
let samples_to_read = read_instruction.length.saturating_sub(skip);
160206

@@ -165,12 +211,7 @@ impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContigousReader<R, T> {
165211
}
166212

167213
// Read the remaining samples
168-
for _ in 0..samples_to_read {
169-
let read_value = self.reader.read_value()?;
170-
if let Some(value) = output.next() {
171-
*value = read_value;
172-
}
173-
}
214+
self.read_sequential_samples(output, samples_to_read)?;
174215
length = samples_to_read;
175216
}
176217
RecordEntryPlan::Skip(bytes) => {
@@ -183,42 +224,18 @@ impl<R: Read + Seek, T: TdmsReader<R>> MultiChannelContigousReader<R, T> {
183224
Ok(length)
184225
}
185226

186-
fn read_sub_block_with_offset<D: TdmsStorageType>(
227+
fn read_sequential_samples<'a, D: TdmsStorageType, I: Iterator<Item = &'a mut D>>(
187228
&mut self,
188-
channels: &mut RecordPlan<'_, D>,
189-
start_sample: u64,
190-
) -> Result<usize, TdmsError> {
191-
let mut length = 0;
192-
for read_instruction in channels.read_instructions().iter_mut() {
193-
match &mut read_instruction.plan {
194-
RecordEntryPlan::Read(output) => {
195-
// Skip the specified number of samples at the start
196-
let samples_to_skip = start_sample.min(read_instruction.length as u64) as usize;
197-
let samples_to_read = read_instruction.length.saturating_sub(samples_to_skip);
198-
199-
// Skip samples by seeking
200-
if samples_to_skip > 0 {
201-
let skip_bytes = samples_to_skip as i64 * D::SIZE_BYTES as i64;
202-
self.reader.move_position(skip_bytes)?;
203-
}
204-
205-
// Read the remaining samples
206-
for _ in 0..samples_to_read {
207-
let read_value = self.reader.read_value()?;
208-
if let Some(value) = output.next() {
209-
*value = read_value;
210-
}
211-
}
212-
length = samples_to_read;
213-
}
214-
RecordEntryPlan::Skip(bytes) => {
215-
let skip_bytes = *bytes * read_instruction.length as i64;
216-
self.reader.move_position(skip_bytes)?;
217-
}
218-
};
229+
output: &mut I,
230+
samples_to_read: usize,
231+
) -> Result<(), TdmsError> {
232+
for _ in 0..samples_to_read {
233+
let read_value = self.reader.read_value()?;
234+
if let Some(value) = output.next() {
235+
*value = read_value;
236+
}
219237
}
220-
221-
Ok(length)
238+
Ok(())
222239
}
223240
}
224241

@@ -259,7 +276,7 @@ mod tests {
259276
let mut buffer = create_test_buffer();
260277
let meta = create_test_meta_data(2);
261278

262-
let mut reader = MultiChannelContigousReader::<_, _>::new(
279+
let mut reader = MultiChannelContiguousReader::<_, _>::new(
263280
BigEndianReader::from_reader(&mut buffer),
264281
0,
265282
800.try_into().unwrap(),
@@ -277,7 +294,7 @@ mod tests {
277294
let meta = create_test_meta_data(4);
278295
let length = meta.first().unwrap().number_of_values as f64;
279296

280-
let mut reader = MultiChannelContigousReader::<_, _>::new(
297+
let mut reader = MultiChannelContiguousReader::<_, _>::new(
281298
BigEndianReader::from_reader(&mut buffer),
282299
0,
283300
800.try_into().unwrap(),
@@ -312,7 +329,7 @@ mod tests {
312329
// ch3: 4, 5, 12, 13
313330
// ch4: 6, 7, 14, 15
314331

315-
let mut reader = MultiChannelContigousReader::<_, _>::new(
332+
let mut reader = MultiChannelContiguousReader::<_, _>::new(
316333
BigEndianReader::from_reader(&mut buffer),
317334
0,
318335
800.try_into().unwrap(),
@@ -333,7 +350,7 @@ mod tests {
333350
let meta = create_test_meta_data(4);
334351
let length = meta.first().unwrap().number_of_values as f64;
335352

336-
let mut reader = MultiChannelContigousReader::<_, _>::new(
353+
let mut reader = MultiChannelContiguousReader::<_, _>::new(
337354
BigEndianReader::from_reader(&mut buffer),
338355
0,
339356
800.try_into().unwrap(),
@@ -356,7 +373,7 @@ mod tests {
356373
let meta = create_test_meta_data(4);
357374
let length = meta.first().unwrap().number_of_values as f64;
358375

359-
let mut reader = MultiChannelContigousReader::<_, _>::new(
376+
let mut reader = MultiChannelContiguousReader::<_, _>::new(
360377
BigEndianReader::from_reader(&mut buffer),
361378
0,
362379
800.try_into().unwrap(),
@@ -391,7 +408,7 @@ mod tests {
391408
channel.number_of_values = 3;
392409
}
393410

394-
let mut reader = MultiChannelContigousReader::<_, _>::new(
411+
let mut reader = MultiChannelContiguousReader::<_, _>::new(
395412
BigEndianReader::from_reader(&mut buffer),
396413
0,
397414
800.try_into().unwrap(),

0 commit comments

Comments
 (0)