r701/src/record_iterator.rs
Nicola Belluti b2b5f0c66c
Some checks failed
Check, format and test / build (push) Failing after 49s
Removed Nix and the sample-main, added a CI/CD pipeline and updated the README.md
2024-07-31 12:00:34 +02:00

87 lines
2.6 KiB
Rust

use crate::{Record, R701};
use std::io::Result;
#[derive(Debug)]
pub struct RecordIterator<'a> {
r701: &'a mut R701,
input_buffer: Vec<u8>,
sequence_number: u16,
total_records: u16,
record_count: u16,
}
impl<'a> RecordIterator<'a> {
pub fn from(r701: &'a mut R701) -> Result<Self> {
// Get the total number of records
let total_records = r701.get_total_record_count()?;
// Calculate the sequence number on which the last record resides and
// the index of the first `ff` byte, avoiding overflows
//
// TODO: Find a better way to do the multiplication and the division
// avoiding overflows
#[allow(clippy::cast_possible_truncation)]
let sequence_number = (u32::from(total_records) * 12 / 1024) as u16;
let first_useless_byte_index = total_records as usize * 12 % 1024;
// The endpoint expects the first block of records to be sent first
r701.get_record_bytes(total_records, 0)?;
// Get the last records and cut out all the trailing `ff` bytes
let input_buffer = r701
.get_record_bytes(total_records, sequence_number)?
.drain(..first_useless_byte_index)
.collect::<Vec<u8>>();
// Return a new Iterator
Ok(Self {
r701,
input_buffer,
sequence_number,
total_records,
record_count: total_records,
})
}
}
impl<'a> Iterator for RecordIterator<'a> {
type Item = Record;
fn next(&mut self) -> Option<Self::Item> {
// Stop iterating when there are no more records
if self.record_count == 0 {
return None;
}
self.record_count -= 1;
// If the input buffer is almost empty, make another request to the
// endpoint asking for more data
if self.input_buffer.len() < 12 {
// If the buffer is almost empty but the sequence number is already
// zero, stop iterating
if self.sequence_number == 0 {
return None;
}
self.sequence_number -= 1;
// Request new bytes
let bytes = self
.r701
.get_record_bytes(self.total_records, self.sequence_number)
.ok()?;
// Put the bytes at the start of the vector
self.input_buffer.splice(0..0, bytes.iter().copied());
}
// Return a new Record
self.input_buffer
.drain(self.input_buffer.len() - 12..)
.as_slice()
.try_into()
.ok()
}
}