use crate::body_parser::{BodyParser, ParserState};
use crate::message::stomp_message::StompMessage;
#[derive(Debug, PartialEq)]
enum State {
Start,
AlmostDone,
Done,
Error,
}
pub struct FixedLengthBodyParser {
state: State,
expected_len: usize,
remaining_len: usize,
}
impl FixedLengthBodyParser {
pub fn new() -> FixedLengthBodyParser {
FixedLengthBodyParser {
state: State::Start,
expected_len: 0,
remaining_len: 0,
}
}
pub fn reinit(&mut self, expected_len: usize) {
self.state = State::Start;
self.remaining_len = expected_len;
self.expected_len = expected_len;
}
pub fn expected_len(&self) -> usize {
self.expected_len
}
}
impl BodyParser for FixedLengthBodyParser {
fn push(&mut self, buffer: &[u8], message: &mut StompMessage) -> Result<usize, ParserState> {
let len = buffer.len();
if State::AlmostDone == self.state {
let zero = buffer[0];
if zero != b'\0' {
self.state = State::Error;
return Err(ParserState::InvalidMessage);
}
else {
self.state = State::Done;
return Ok(1);
}
}
if len < self.remaining_len {
message.add_body(buffer);
self.remaining_len -= len;
return Ok(len);
}
else if len == self.remaining_len {
message.add_body(buffer);
self.remaining_len -= len;
self.state = State::AlmostDone;
return Ok(len);
}
else if len > self.remaining_len {
let to_read = self.remaining_len;
message.add_body(&buffer[0..to_read]);
self.remaining_len -= to_read;
match buffer[to_read] {
b'\0' => {
self.state = State::Done;
return Ok(to_read + 1);
}
_ => {
self.state = State::Error;
return Err(ParserState::InvalidMessage);
}
}
}
return Err(ParserState::InvalidMessage);
}
fn is_done(&self) -> bool {
State::Done == self.state
}
}
#[cfg(test)]
mod tests {
use crate::message::stomp_message::Ownership;
use super::*;
#[test]
fn test_fixed_length_happy() {
let mut p = FixedLengthBodyParser::new();
let mut message = StompMessage::new(Ownership::Session);
p.reinit(23);
match p.push(b"abcdefghij", &mut message) {
Ok(10) => { assert!(!p.is_done()); },
Err(_) => panic!("parse error"),
_ => panic!("unexpected")
}
match p.push(b"klmnopqrst", &mut message) {
Ok(10) => { assert!(!p.is_done()); },
Err(_) => panic!("parse error"),
_ => panic!("unexpected")
}
match p.push(b"uvw\0", &mut message) {
Ok(4) => { assert!(p.is_done()); },
Err(_) => panic!("parse error"),
_ => panic!("unexpected")
}
}
#[test]
fn test_fixed_length_unhappy() {
let mut p = FixedLengthBodyParser::new();
let mut message = StompMessage::new(Ownership::Session);
p.reinit(22);
match p.push(b"abcdefghij", &mut message) {
Ok(10) => { assert!(!p.is_done()); },
Err(_) => panic!("parse error"),
_ => panic!("unexpected")
}
match p.push(b"klmnopqrst", &mut message) {
Ok(10) => { assert!(!p.is_done()); },
Err(_) => panic!("parse error"),
_ => panic!("unexpected")
}
match p.push(b"uvw\0", &mut message) {
Err(ParserState::InvalidMessage) => {
assert!(! p.is_done());
match p.state {
State::Error => {
}
_ => {
panic!("unexpected parser state")
}
}
},
Ok(4) => { panic!("unexpected") },
_ => panic!("unexpected")
}
}
}