use bytes::Bytes;
use tracing::trace;
use crate::base::message::RecordIter;
use crate::base::{Message, ParsedName};
use crate::rdata::ZoneRecordData;
use crate::zonetree::types::ZoneUpdate;
use super::interpreter::RecordProcessor;
use super::types::{Error, IterationError, ParsedRecord, XfrType};
pub struct XfrZoneUpdateIterator<'a, 'b> {
processor: &'a mut RecordProcessor,
iter: RecordIter<'b, Bytes, ZoneRecordData<Bytes, ParsedName<Bytes>>>,
held_update: Option<ZoneUpdate<ParsedRecord>>,
}
impl<'a, 'b> XfrZoneUpdateIterator<'a, 'b> {
pub(super) fn new(
processor: &'a mut RecordProcessor,
resp: &'b Message<Bytes>,
) -> Result<Self, Error> {
let answer = resp.answer().map_err(Error::ParseError)?;
let iter = answer.limit_to();
Ok(Self {
processor,
iter,
held_update: None,
})
}
}
impl Iterator for XfrZoneUpdateIterator<'_, '_> {
type Item = Result<ZoneUpdate<ParsedRecord>, IterationError>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(update) = self.held_update.take() {
return Some(Ok(update));
}
loop {
match self.iter.next() {
Some(Ok(record)) => {
trace!(
"XFR record {}: {record:?}",
self.processor.rr_count()
);
match self.processor.process_record(record).transpose() {
None => {
continue;
}
Some(Ok((update, extra_update))) => {
self.held_update = extra_update;
return Some(Ok(update));
}
Some(Err(err)) => {
return Some(Err(err));
}
}
}
Some(Err(err)) => {
trace!(
"XFR record {}: parsing error: {err}",
self.processor.rr_count()
);
return Some(Err(IterationError::ParseError(err)));
}
None => {
if !self.processor.is_finished()
&& self.processor.actual_xfr_type() == XfrType::Ixfr
&& self.processor.rr_count() == 1
{
self.processor.finish();
return Some(Err(
IterationError::SingleSoaIxfrTcpRetrySignal,
));
} else {
return None;
}
}
}
}
}
}