romp 0.5.2

STOMP server and WebSockets platform
Documentation

use crate::body_parser::{BodyParser, ParserState};
use crate::message::stomp_message::StompMessage;

/// STOMP protocol push parser, parses message body.
///
/// readonly bytes pushed in from the network and copied into the message


/// state of the loop
#[derive(Debug, PartialEq)]
enum State {
    Start,
    /// expecting trailing \0
    ReadingBody,
    Done
}

/// Body parser for binary data when we dont know the expected length of the data, data must be text so we can scan for \0
pub struct TextBodyParser {
    state: State,
    read: usize,
    max_len: usize,
}

/// reads up to \0
impl TextBodyParser {
    pub fn new(max_len: usize) -> TextBodyParser {
        TextBodyParser {
            state: State::Start,
            read: 0,
            max_len,
        }
    }

    /// how many bytes read form the stream this inlcudes \0
    pub fn bytes_read(&self) -> usize {
        self.read
    }

    /// must be called before use
    pub fn reinit(&mut self, max_len: usize) {
        self.state = State::Start;
        self.read = 0;
        self.max_len = max_len;
    }

}

impl BodyParser for TextBodyParser {

    fn push(&mut self, buffer: &[u8], message: &mut StompMessage) -> Result<usize, ParserState> {

        let mut p: usize = 0;
        for ch in buffer {
            p += 1;
            if *ch == b'\0' {
                message.add_body(&buffer[0..p - 1]);
                self.state = State::Done;
                self.read += p;
                return Ok(p);
            }
            if self.read + p > self.max_len {
                self.read += p;
                return Err(ParserState::BodyFlup);
            }
        }

        message.add_body(&buffer[0..p]);
        self.state = State::ReadingBody;
        self.read += p;

        Ok(p)
    }

    fn is_done(&self) -> bool {
        State::Done == self.state
    }
}

#[cfg(test)]
mod tests {
    use crate::message::stomp_message::Ownership;

    use super::*;

    #[test]
    fn test_text_happy() {
        let mut p = TextBodyParser::new(1048576);
        let mut m = StompMessage::new(Ownership::Session);

        p.reinit(1048576);

        match p.push(b"abcdefghij", &mut m) {
            Ok(10) => {
                assert!(!p.is_done());
            },
            Err(_) => panic!("parse error"),
            _ => panic!("unexpected")
        }
        match p.push(b"klmnopqrst", &mut m) {
            Ok(10) => {
                assert!(!p.is_done());
            },
            Err(_) => panic!("parse error"),
            _ => panic!("unexpected")
        }
        match p.push(b"uvw\0", &mut m) {
            Ok(4) => {
                assert!(p.is_done());
            },
            Err(_) => panic!("parse error"),
            _ => panic!("unexpected")
        }

        println!("parsed text message {:?}", m.as_string());
    }


    #[test]
    fn test_text_unhappy() {
        let mut p = TextBodyParser::new(10);
        let mut m = StompMessage::new(Ownership::Session);

        match p.push(b"abcdefghijk", &mut m) {
            Ok(_) => {
                panic!("should flup")
            },
            Err(ParserState::BodyFlup) => {}
            _ => panic!("unexpected")
        }
    }
}