use crate::ocp1::{
parser::{self, Error},
pdu::{Message, MessagePdu, PduType},
};
#[derive(Debug)]
pub struct MessageIterator<'a> {
state: State<'a>,
}
impl MessageIterator<'static> {
pub fn empty() -> Self {
Self { state: State::Done }
}
}
#[derive(Debug)]
enum State<'a> {
Iterating { data: &'a [u8], pdu_type: PduType },
Done,
}
impl<'a> Iterator for MessageIterator<'a> {
type Item = Result<Message<'a>, Error>;
fn next(&mut self) -> Option<Self::Item> {
match self.state {
State::Iterating { data, pdu_type } => match parser::message(pdu_type, data) {
Ok((message, remaining)) => {
self.state = if remaining.is_empty() {
State::Done
} else {
State::Iterating {
data: remaining,
pdu_type,
}
};
Some(Ok(message))
}
Err(err) => {
self.state = State::Done;
Some(Err(err))
}
},
State::Done => None,
}
}
}
impl<'a> IntoIterator for MessagePdu<'a> {
type Item = Result<Message<'a>, Error>;
type IntoIter = MessageIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter {
state: State::Iterating {
data: self.data,
pdu_type: self.header.pdu_type,
},
}
}
}
#[cfg(test)]
mod tests {
use {
super::*,
crate::{
ocp1::{
decoder::decode,
encoder::encode_messages,
pdu::{Command, Parameters},
},
types::OcaMethod,
},
alloc::{vec, vec::Vec},
};
#[test]
fn iterating_over_messages() {
let commands = vec![
Command {
handle: 101.into(),
method: OcaMethod {
object: 531.into(),
id: (4, 1).into(),
},
parameters: Parameters {
count: 0,
parameters: &[],
},
},
Command {
handle: 102.into(),
method: OcaMethod {
object: 532.into(),
id: (2, 3).into(),
},
parameters: Parameters {
count: 1,
parameters: b"foobar",
},
},
];
let mut buffer = [0_u8; 512];
let encoded = encode_messages(&commands, &mut buffer).unwrap();
let decoded = decode(encoded)
.unwrap()
.map(|(decoded, _)| decoded)
.unwrap();
let decoded_commands = decoded.into_iter().collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(commands.len(), decoded_commands.len());
assert_eq!(Message::Command(commands[0]), decoded_commands[0]);
assert_eq!(Message::Command(commands[1]), decoded_commands[1]);
}
}