use crate::parser::bmp::error::ParserBmpError;
use crate::parser::ReadUtils;
use bytes::{Buf, Bytes};
use num_enum::{IntoPrimitive, TryFromPrimitive};
use std::convert::TryFrom;
#[derive(Debug)]
pub struct InitiationMessage {
pub tlvs: Vec<InitiationTlv>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct InitiationTlv {
pub info_type: InitiationTlvType,
pub info_len: u16,
pub info: String,
}
#[derive(Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Clone, Copy)]
#[repr(u16)]
pub enum InitiationTlvType {
String = 0,
SysDescr = 1,
SysName = 2,
}
pub fn parse_initiation_message(data: &mut Bytes) -> Result<InitiationMessage, ParserBmpError> {
let mut tlvs = vec![];
while data.remaining() > 4 {
let info_type: InitiationTlvType = InitiationTlvType::try_from(data.get_u16())?;
let info_len = data.get_u16();
if data.remaining() < info_len as usize {
break;
}
let info = data.read_n_bytes_to_string(info_len as usize)?;
tlvs.push(InitiationTlv {
info_type,
info_len,
info,
});
}
Ok(InitiationMessage { tlvs })
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::{BufMut, BytesMut};
#[test]
fn test_parse_initiation_message() {
let mut buffer = BytesMut::new();
buffer.put_u16(1); buffer.put_u16(5); buffer.put_slice(b"Test1"); let mut bytes = buffer.freeze();
match parse_initiation_message(&mut bytes) {
Ok(initiation_message) => {
for tlv in initiation_message.tlvs {
assert_eq!(tlv.info_type, InitiationTlvType::SysDescr);
assert_eq!(tlv.info_len, 5);
assert_eq!(tlv.info, "Test1".to_string());
}
}
Err(_) => panic!("Failed to parse initiation message"),
}
}
#[test]
fn test_debug() {
let initiation_message = InitiationMessage {
tlvs: vec![InitiationTlv {
info_type: InitiationTlvType::SysDescr,
info_len: 5,
info: "Test1".to_string(),
}],
};
assert_eq!(
format!("{:?}", initiation_message),
"InitiationMessage { tlvs: [InitiationTlv { info_type: SysDescr, info_len: 5, info: \"Test1\" }] }"
);
}
}