use crate::{
decoder::{sequence, Decodable, Decoder},
field::Tag,
Error, Message,
};
use core::marker::PhantomData;
use digest::Digest;
pub struct Iter<'a, 'b, T, D: Digest> {
decoder: &'a mut Decoder<D>,
tag: Tag,
data: &'b [u8],
decodable: PhantomData<T>,
}
impl<'a, 'b, T, D> Iter<'a, 'b, T, D>
where
D: Digest,
{
pub(crate) fn new(decoder: &'a mut Decoder<D>, tag: Tag, data: &'b [u8]) -> Self {
Self {
decoder,
tag,
data,
decodable: PhantomData,
}
}
fn seq_decoder(&mut self) -> &mut sequence::Decoder<D> {
self.decoder.peek_seq()
}
}
impl<'a, 'b, T, D> Iterator for Iter<'a, 'b, T, D>
where
T: Message,
D: Digest,
{
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Result<T, Error>> {
if self.seq_decoder().remaining() == 0 {
return None;
}
let mut input = &self.data[self.seq_decoder().position()..];
let result = self
.seq_decoder()
.decode_message(&mut input)
.and_then(|msg_bytes| {
self.decoder.push()?;
let msg = T::decode(&mut self.decoder, msg_bytes)?;
if let Some(digest) = self.decoder.pop() {
self.seq_decoder().hash_message_digest(&digest)?;
}
Ok(msg)
});
Some(result)
}
}
impl<'a, 'b, D> Iterator for Iter<'a, 'b, u64, D>
where
D: Digest,
{
type Item = Result<u64, Error>;
fn next(&mut self) -> Option<Result<u64, Error>> {
if self.seq_decoder().remaining() == 0 {
return None;
}
let mut input = &self.data[self.seq_decoder().position()..];
Some(self.seq_decoder().decode_uint64(&mut input))
}
}
impl<'a, 'b, D> Iterator for Iter<'a, 'b, i64, D>
where
D: Digest,
{
type Item = Result<i64, Error>;
fn next(&mut self) -> Option<Result<i64, Error>> {
if self.seq_decoder().remaining() == 0 {
return None;
}
let mut input = &self.data[self.seq_decoder().position()..];
Some(self.seq_decoder().decode_sint64(&mut input))
}
}
impl<'a, 'b, T, D> Drop for Iter<'a, 'b, T, D>
where
D: Digest,
{
fn drop(&mut self) {
if let Some(digest) = self.decoder.pop_seq() {
self.decoder
.peek()
.hash_sequence_digest(self.tag, &digest)
.unwrap();
}
}
}