use crate::{igmp::*, *};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MembershipQueryWithSourcesSlice<'a> {
slice: &'a [u8],
}
impl<'a> MembershipQueryWithSourcesSlice<'a> {
#[inline]
pub(crate) unsafe fn from_slice_unchecked(
slice: &'a [u8],
) -> MembershipQueryWithSourcesSlice<'a> {
debug_assert!(slice.len() >= MembershipQueryWithSourcesHeader::LEN);
debug_assert!(
slice.len()
>= MembershipQueryWithSourcesHeader::LEN
+ usize::from(u16::from_be_bytes([slice[10], slice[11]])) * 4
);
MembershipQueryWithSourcesSlice { slice }
}
#[inline]
pub fn max_response_code(&self) -> MaxResponseCode {
MaxResponseCode(unsafe { *self.slice.get_unchecked(1) })
}
#[inline]
pub fn checksum(&self) -> u16 {
unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(2)) }
}
#[inline]
pub fn group_address(&self) -> GroupAddress {
GroupAddress::new(unsafe {
[
*self.slice.get_unchecked(4),
*self.slice.get_unchecked(5),
*self.slice.get_unchecked(6),
*self.slice.get_unchecked(7),
]
})
}
#[inline]
pub fn raw_byte_8(&self) -> u8 {
unsafe { *self.slice.get_unchecked(8) }
}
#[inline]
pub fn flags(&self) -> u8 {
(self.raw_byte_8() & MembershipQueryWithSourcesHeader::RAW_BYTE_8_MASK_FLAGS)
>> MembershipQueryWithSourcesHeader::RAW_BYTE_8_OFFSET_FLAGS
}
#[inline]
pub fn s_flag(&self) -> bool {
0 != (self.raw_byte_8() & MembershipQueryWithSourcesHeader::RAW_BYTE_8_MASK_S_FLAG)
}
#[inline]
pub fn qrv(&self) -> Qrv {
unsafe {
Qrv::new_unchecked(
self.raw_byte_8() & MembershipQueryWithSourcesHeader::RAW_BYTE_8_MASK_QRV,
)
}
}
#[inline]
pub fn qqic(&self) -> u8 {
unsafe { *self.slice.get_unchecked(9) }
}
#[inline]
pub fn num_of_sources(&self) -> u16 {
unsafe { get_unchecked_be_u16(self.slice.as_ptr().add(10)) }
}
#[inline]
pub fn to_header(&self) -> MembershipQueryWithSourcesHeader {
MembershipQueryWithSourcesHeader {
max_response_code: self.max_response_code(),
group_address: self.group_address(),
raw_byte_8: self.raw_byte_8(),
qqic: self.qqic(),
num_of_sources: self.num_of_sources(),
}
}
#[inline]
pub fn source_addrs_bytes(&self) -> &'a [u8] {
let payload = self.payload();
let len = usize::from(self.num_of_sources()) * 4;
unsafe { core::slice::from_raw_parts(payload.as_ptr(), len) }
}
#[inline]
pub fn source_addresses(&self) -> impl ExactSizeIterator<Item = [u8; 4]> + 'a {
self.source_addrs_bytes()
.chunks_exact(4)
.map(|c| [c[0], c[1], c[2], c[3]])
}
#[inline]
pub fn payload(&self) -> &'a [u8] {
unsafe {
core::slice::from_raw_parts(
self.slice
.as_ptr()
.add(MembershipQueryWithSourcesHeader::LEN),
self.slice.len() - MembershipQueryWithSourcesHeader::LEN,
)
}
}
#[inline]
pub fn slice(&self) -> &'a [u8] {
self.slice
}
}