use crate::error::{Error, Result};
use crate::io::Cursor;
#[derive(Debug, Clone)]
pub struct GroupInfoMessage {
pub max_compact_links: Option<u16>,
pub min_dense_links: Option<u16>,
pub est_num_entries: Option<u16>,
pub est_name_len: Option<u16>,
}
pub fn parse(
cursor: &mut Cursor<'_>,
_offset_size: u8,
_length_size: u8,
msg_size: usize,
) -> Result<GroupInfoMessage> {
let start = cursor.position();
let version = cursor.read_u8()?;
if version != 0 {
return Err(Error::InvalidData(format!(
"unsupported group info version: {}",
version
)));
}
let flags = cursor.read_u8()?;
let (max_compact_links, min_dense_links) = if (flags & 0x01) != 0 {
let max_compact = cursor.read_u16_le()?;
let min_dense = cursor.read_u16_le()?;
(Some(max_compact), Some(min_dense))
} else {
(None, None)
};
let (est_num_entries, est_name_len) = if (flags & 0x02) != 0 {
let num = cursor.read_u16_le()?;
let len = cursor.read_u16_le()?;
(Some(num), Some(len))
} else {
(None, None)
};
let consumed = (cursor.position() - start) as usize;
if consumed < msg_size {
cursor.skip(msg_size - consumed)?;
}
Ok(GroupInfoMessage {
max_compact_links,
min_dense_links,
est_num_entries,
est_name_len,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_group_info_all_present() {
let mut data = vec![
0x00, 0x03, ];
data.extend_from_slice(&8u16.to_le_bytes()); data.extend_from_slice(&6u16.to_le_bytes()); data.extend_from_slice(&4u16.to_le_bytes()); data.extend_from_slice(&18u16.to_le_bytes());
let mut cursor = Cursor::new(&data);
let msg = parse(&mut cursor, 8, 8, data.len()).unwrap();
assert_eq!(msg.max_compact_links, Some(8));
assert_eq!(msg.min_dense_links, Some(6));
assert_eq!(msg.est_num_entries, Some(4));
assert_eq!(msg.est_name_len, Some(18));
}
#[test]
fn test_parse_group_info_empty() {
let data = vec![0x00, 0x00];
let mut cursor = Cursor::new(&data);
let msg = parse(&mut cursor, 8, 8, data.len()).unwrap();
assert!(msg.max_compact_links.is_none());
assert!(msg.est_num_entries.is_none());
}
}