oca 0.2.0

An experiment with no_std
Documentation
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]);
    }
}