use crate::{buffer::GenlBuffer, header::GenlHeader, traits::*};
use netlink_packet_core::{
DecodeError, Emitable, NetlinkDeserializable, NetlinkHeader,
NetlinkPayload, NetlinkSerializable, ParseableParametrized,
};
use std::fmt::Debug;
#[cfg(doc)]
use netlink_packet_core::NetlinkMessage;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GenlMessage<F> {
pub header: GenlHeader,
pub payload: F,
resolved_family_id: u16,
}
impl<F> GenlMessage<F>
where
F: Debug,
{
pub fn new(header: GenlHeader, payload: F, family_id: u16) -> Self {
Self {
header,
payload,
resolved_family_id: family_id,
}
}
pub fn from_parts(header: GenlHeader, payload: F) -> Self {
Self {
header,
payload,
resolved_family_id: 0,
}
}
pub fn into_parts(self) -> (GenlHeader, F) {
(self.header, self.payload)
}
pub fn resolved_family_id(&self) -> u16 {
self.resolved_family_id
}
pub fn set_resolved_family_id(&mut self, family_id: u16) {
self.resolved_family_id = family_id;
}
}
impl<F> GenlMessage<F>
where
F: GenlFamily + Debug,
{
pub fn from_payload(payload: F) -> Self {
Self {
header: GenlHeader {
cmd: payload.command(),
version: payload.version(),
},
payload,
resolved_family_id: 0,
}
}
pub fn finalize(&mut self) {
self.header.cmd = self.payload.command();
self.header.version = self.payload.version();
}
pub fn family_id(&self) -> u16 {
let static_id = self.payload.family_id();
if static_id == 0 {
self.resolved_family_id
} else {
static_id
}
}
}
impl<F> Emitable for GenlMessage<F>
where
F: GenlFamily + Emitable + Debug,
{
fn buffer_len(&self) -> usize {
self.header.buffer_len() + self.payload.buffer_len()
}
fn emit(&self, buffer: &mut [u8]) {
self.header.emit(buffer);
let buffer = &mut buffer[self.header.buffer_len()..];
self.payload.emit(buffer);
}
}
impl<F> NetlinkSerializable for GenlMessage<F>
where
F: GenlFamily + Emitable + Debug,
{
fn message_type(&self) -> u16 {
self.family_id()
}
fn buffer_len(&self) -> usize {
<Self as Emitable>::buffer_len(self)
}
fn serialize(&self, buffer: &mut [u8]) {
self.emit(buffer)
}
}
impl<F> NetlinkDeserializable for GenlMessage<F>
where
F: ParseableParametrized<[u8], GenlHeader> + Debug,
{
type Error = DecodeError;
fn deserialize(
header: &NetlinkHeader,
payload: &[u8],
) -> Result<Self, Self::Error> {
let buffer = GenlBuffer::new_checked(payload)?;
GenlMessage::parse_with_param(&buffer, header.message_type)
}
}
impl<F> From<GenlMessage<F>> for NetlinkPayload<GenlMessage<F>>
where
F: Debug,
{
fn from(message: GenlMessage<F>) -> Self {
NetlinkPayload::InnerMessage(message)
}
}