use byteorder::{ByteOrder, NativeEndian};
use netlink_packet_utils::{
traits::{Emitable, Parseable},
DecodeError,
};
use crate::Field;
const MASK: Field = 0..4;
const ENABLED: Field = 4..8;
const FAILURE: Field = 8..12;
const PID: Field = 12..16;
const RATE_LIMITING: Field = 16..20;
const BACKLOG_LIMIT: Field = 20..24;
const LOST: Field = 24..28;
const BACKLOG: Field = 28..32;
const FEATURE_BITMAP: Field = 32..36;
const BACKLOG_WAIT_TIME: Field = 36..40;
pub const STATUS_MESSAGE_LEN: usize = BACKLOG_WAIT_TIME.end;
#[derive(Debug, PartialEq, Eq, Clone, Default)]
#[non_exhaustive]
pub struct StatusMessage {
pub mask: u32,
pub enabled: u32,
pub failure: u32,
pub pid: u32,
pub rate_limiting: u32,
pub backlog_limit: u32,
pub lost: u32,
pub backlog: u32,
pub feature_bitmap: u32,
pub backlog_wait_time: u32,
}
impl StatusMessage {
pub fn new() -> Self {
Default::default()
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[non_exhaustive]
pub struct StatusMessageBuffer<T> {
buffer: T,
}
impl<T: AsRef<[u8]>> StatusMessageBuffer<T> {
pub fn new(buffer: T) -> StatusMessageBuffer<T> {
StatusMessageBuffer { buffer }
}
pub fn new_checked(
buffer: T,
) -> Result<StatusMessageBuffer<T>, DecodeError> {
let buf = Self::new(buffer);
buf.check_buffer_length()?;
Ok(buf)
}
fn check_buffer_length(&self) -> Result<(), DecodeError> {
let len = self.buffer.as_ref().len();
if len < STATUS_MESSAGE_LEN {
return Err(format!(
"invalid StatusMessageBuffer buffer: length is {len} \
instead of {STATUS_MESSAGE_LEN}"
)
.into());
}
Ok(())
}
pub fn into_inner(self) -> T {
self.buffer
}
pub fn mask(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[MASK])
}
pub fn enabled(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[ENABLED])
}
pub fn failure(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[FAILURE])
}
pub fn pid(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[PID])
}
pub fn rate_limiting(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[RATE_LIMITING])
}
pub fn backlog_limit(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[BACKLOG_LIMIT])
}
pub fn lost(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[LOST])
}
pub fn backlog(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[BACKLOG])
}
pub fn feature_bitmap(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[FEATURE_BITMAP])
}
pub fn backlog_wait_time(&self) -> u32 {
NativeEndian::read_u32(&self.buffer.as_ref()[BACKLOG_WAIT_TIME])
}
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> StatusMessageBuffer<T> {
pub fn set_mask(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[MASK], value)
}
pub fn set_enabled(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[ENABLED], value)
}
pub fn set_failure(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[FAILURE], value)
}
pub fn set_pid(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[PID], value)
}
pub fn set_rate_limiting(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[RATE_LIMITING], value)
}
pub fn set_backlog_limit(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[BACKLOG_LIMIT], value)
}
pub fn set_lost(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[LOST], value)
}
pub fn set_backlog(&mut self, value: u32) {
NativeEndian::write_u32(&mut self.buffer.as_mut()[BACKLOG], value)
}
pub fn set_feature_bitmap(&mut self, value: u32) {
NativeEndian::write_u32(
&mut self.buffer.as_mut()[FEATURE_BITMAP],
value,
)
}
pub fn set_backlog_wait_time(&mut self, value: u32) {
NativeEndian::write_u32(
&mut self.buffer.as_mut()[BACKLOG_WAIT_TIME],
value,
)
}
}
impl<T: AsRef<[u8]>> Parseable<StatusMessageBuffer<T>> for StatusMessage {
fn parse(buf: &StatusMessageBuffer<T>) -> Result<Self, DecodeError> {
buf.check_buffer_length()?;
Ok(StatusMessage {
mask: buf.mask(),
enabled: buf.enabled(),
failure: buf.failure(),
pid: buf.pid(),
rate_limiting: buf.rate_limiting(),
backlog_limit: buf.backlog_limit(),
lost: buf.lost(),
backlog: buf.backlog(),
feature_bitmap: buf.feature_bitmap(),
backlog_wait_time: buf.backlog_wait_time(),
})
}
}
impl Emitable for StatusMessage {
fn buffer_len(&self) -> usize {
STATUS_MESSAGE_LEN
}
fn emit(&self, buffer: &mut [u8]) {
let mut buffer = StatusMessageBuffer::new(buffer);
buffer.set_mask(self.mask);
buffer.set_enabled(self.enabled);
buffer.set_failure(self.failure);
buffer.set_pid(self.pid);
buffer.set_rate_limiting(self.rate_limiting);
buffer.set_backlog_limit(self.backlog_limit);
buffer.set_lost(self.lost);
buffer.set_backlog(self.backlog);
buffer.set_feature_bitmap(self.feature_bitmap);
buffer.set_backlog_wait_time(self.backlog_wait_time);
}
}