use core::iter::FusedIterator;
use super::error::KcpSegmentsParseError;
use super::segment::KcpSegment;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct KcpSegments<'a> {
bytes: &'a [u8],
}
impl<'a> KcpSegments<'a> {
pub fn parse(bytes: &'a [u8]) -> Result<Self, KcpSegmentsParseError> {
if bytes.is_empty() {
return Err(KcpSegmentsParseError::EmptySequence);
}
for segment in KcpSegmentIter::new(bytes) {
segment?;
}
Ok(Self { bytes })
}
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn iter(self) -> KcpSegmentIter<'a> {
KcpSegmentIter::new(self.bytes)
}
}
#[derive(Clone, Debug)]
pub struct KcpSegmentIter<'a> {
remaining: &'a [u8],
offset: usize,
exhausted: bool,
}
impl<'a> KcpSegmentIter<'a> {
pub const fn new(bytes: &'a [u8]) -> Self {
Self {
remaining: bytes,
offset: 0,
exhausted: false,
}
}
}
impl<'a> Iterator for KcpSegmentIter<'a> {
type Item = Result<KcpSegment<'a>, KcpSegmentsParseError>;
fn next(&mut self) -> Option<Self::Item> {
if self.exhausted || self.remaining.is_empty() {
self.exhausted = true;
return None;
}
match KcpSegment::parse(self.remaining) {
Ok((segment, suffix)) => {
let length = segment.as_bytes().len();
self.offset += length;
self.remaining = suffix;
Some(Ok(segment))
}
Err(error) => self.fail(KcpSegmentsParseError::Segment {
offset: self.offset,
error,
}),
}
}
}
impl FusedIterator for KcpSegmentIter<'_> {}
impl<'a> KcpSegmentIter<'a> {
fn fail(
&mut self,
error: KcpSegmentsParseError,
) -> Option<Result<KcpSegment<'a>, KcpSegmentsParseError>> {
self.remaining = &[];
self.exhausted = true;
Some(Err(error))
}
}