use crate::ie::Ie;
use crate::ie::IeType;
#[derive(Debug)]
pub struct IeIter<'a> {
ie_type: IeType,
state: IeIterState<'a>,
}
#[derive(Debug)]
enum IeIterState<'a> {
Single(Option<&'a Ie>),
Multiple(std::slice::Iter<'a, Ie>),
Generic { all_ies: &'a [Ie], position: usize },
}
impl<'a> Iterator for IeIter<'a> {
type Item = &'a Ie;
fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
IeIterState::Single(opt) => opt.take(),
IeIterState::Multiple(iter) => iter.next(),
IeIterState::Generic { all_ies, position } => {
while *position < all_ies.len() {
let ie = &all_ies[*position];
*position += 1;
if ie.ie_type == self.ie_type {
return Some(ie);
}
}
None
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
match &self.state {
IeIterState::Single(Some(_)) => (1, Some(1)),
IeIterState::Single(None) => (0, Some(0)),
IeIterState::Multiple(iter) => iter.size_hint(),
IeIterState::Generic { all_ies, position } => {
let remaining = all_ies.len() - *position;
(0, Some(remaining))
}
}
}
}
impl<'a> IeIter<'a> {
pub fn single(ie: Option<&'a Ie>, ie_type: IeType) -> Self {
IeIter {
ie_type,
state: IeIterState::Single(ie),
}
}
pub fn multiple(ies: &'a [Ie], ie_type: IeType) -> Self {
IeIter {
ie_type,
state: IeIterState::Multiple(ies.iter()),
}
}
pub fn generic(all_ies: &'a [Ie], ie_type: IeType) -> Self {
IeIter {
ie_type,
state: IeIterState::Generic {
all_ies,
position: 0,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_single_ie_iterator_some() {
let ie = Ie::new(IeType::Cause, vec![0x01]);
let mut iter = IeIter::single(Some(&ie), IeType::Cause);
assert_eq!(iter.next().map(|i| &i.payload), Some(&vec![0x01]));
assert_eq!(iter.next(), None);
}
#[test]
fn test_single_ie_iterator_none() {
let mut iter = IeIter::single(None, IeType::PdnType);
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
}
#[test]
fn test_multiple_ie_iterator_empty() {
let ies: Vec<Ie> = vec![];
let mut iter = IeIter::multiple(&ies, IeType::CreatePdr);
assert_eq!(iter.next(), None);
}
#[test]
fn test_multiple_ie_iterator_three() {
let ies = vec![
Ie::new(IeType::CreatePdr, vec![1]),
Ie::new(IeType::CreatePdr, vec![2]),
Ie::new(IeType::CreatePdr, vec![3]),
];
let mut iter = IeIter::multiple(&ies, IeType::CreatePdr);
assert_eq!(iter.next().map(|ie| ie.payload[0]), Some(1));
assert_eq!(iter.next().map(|ie| ie.payload[0]), Some(2));
assert_eq!(iter.next().map(|ie| ie.payload[0]), Some(3));
assert_eq!(iter.next(), None);
}
#[test]
fn test_generic_ie_iterator_filters_correctly() {
let ies = vec![
Ie::new(IeType::Cause, vec![1]),
Ie::new(IeType::CreatePdr, vec![2]),
Ie::new(IeType::Cause, vec![3]),
Ie::new(IeType::CreateFar, vec![4]),
Ie::new(IeType::Cause, vec![5]),
];
let collected: Vec<_> = IeIter::generic(&ies, IeType::Cause)
.map(|ie| ie.payload[0])
.collect();
assert_eq!(collected, vec![1, 3, 5]);
}
#[test]
fn test_generic_ie_iterator_no_matches() {
let ies = vec![
Ie::new(IeType::Cause, vec![1]),
Ie::new(IeType::CreatePdr, vec![2]),
];
let collected: Vec<_> = IeIter::generic(&ies, IeType::NodeId).collect();
assert_eq!(collected.len(), 0);
}
#[test]
fn test_iterator_count() {
let ies = vec![
Ie::new(IeType::CreatePdr, vec![1]),
Ie::new(IeType::CreatePdr, vec![2]),
Ie::new(IeType::CreatePdr, vec![3]),
];
let count = IeIter::multiple(&ies, IeType::CreatePdr).count();
assert_eq!(count, 3);
}
#[test]
fn test_iterator_collect() {
let ies = vec![
Ie::new(IeType::CreateFar, vec![10]),
Ie::new(IeType::CreateFar, vec![20]),
];
let collected: Vec<_> = IeIter::multiple(&ies, IeType::CreateFar).collect();
assert_eq!(collected.len(), 2);
assert_eq!(collected[0].payload[0], 10);
assert_eq!(collected[1].payload[0], 20);
}
#[test]
fn test_size_hint_single_some() {
let ie = Ie::new(IeType::Cause, vec![0x01]);
let iter = IeIter::single(Some(&ie), IeType::Cause);
assert_eq!(iter.size_hint(), (1, Some(1)));
}
#[test]
fn test_size_hint_single_none() {
let iter = IeIter::single(None, IeType::PdnType);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
#[test]
fn test_size_hint_multiple() {
let ies = vec![
Ie::new(IeType::CreatePdr, vec![1]),
Ie::new(IeType::CreatePdr, vec![2]),
];
let iter = IeIter::multiple(&ies, IeType::CreatePdr);
assert_eq!(iter.size_hint(), (2, Some(2)));
}
#[test]
fn test_chaining_iterator_methods() {
let ies = vec![
Ie::new(IeType::CreateQer, vec![5]),
Ie::new(IeType::CreateQer, vec![10]),
Ie::new(IeType::CreateQer, vec![15]),
];
let sum: u8 = IeIter::multiple(&ies, IeType::CreateQer)
.map(|ie| ie.payload[0])
.sum();
assert_eq!(sum, 30);
}
}