1use crate::encoding::Encoding;
2use crate::error::MarcError;
3use crate::raw::{RawRecord, RawRecordView};
4
5pub struct BinaryReader<'a> {
10 data: &'a [u8],
11 pos: usize,
12 encoding_override: Option<Encoding>,
13}
14
15impl<'a> BinaryReader<'a> {
16 pub fn new(data: &'a [u8]) -> Self {
17 Self {
18 data,
19 pos: 0,
20 encoding_override: None,
21 }
22 }
23
24 pub fn with_encoding(data: &'a [u8], encoding_override: Option<Encoding>) -> Self {
25 Self { data, pos: 0, encoding_override }
26 }
27}
28
29impl<'a> Iterator for BinaryReader<'a> {
30 type Item = Result<RawRecordView<'a>, MarcError>;
31
32 fn next(&mut self) -> Option<Self::Item> {
33 if self.pos >= self.data.len() {
34 return None;
35 }
36 if self.data.len() - self.pos < 24 {
37 return Some(Err(MarcError::InvalidRecord("trailing bytes shorter than leader")));
38 }
39 let leader = &self.data[self.pos..self.pos + 24];
40 let len = match std::str::from_utf8(&leader[0..5]).ok().and_then(|s| s.trim().parse::<usize>().ok()) {
41 Some(l) if l >= 24 && self.pos + l <= self.data.len() => l,
42 _ => return Some(Err(MarcError::InvalidRecord("invalid record length in leader"))),
43 };
44 let start = self.pos;
45 let end = self.pos + len;
46 self.pos = end;
47 let raw = RawRecord(&self.data[start..end]);
48 Some(Ok(RawRecordView::new(raw, self.encoding_override)))
49 }
50}