#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct ChannelId(pub u8);
impl ChannelId {
pub const DEFAULT: Self = Self(0);
pub const LOG: Self = Self(1);
pub const FIRST_APPLICATION_DEFINED: Self = Self(16);
#[must_use]
pub const fn new(raw: u8) -> Self {
Self(raw)
}
#[must_use]
pub const fn get(self) -> u8 {
self.0
}
#[must_use]
pub const fn is_default(self) -> bool {
self.0 == Self::DEFAULT.0
}
#[must_use]
pub const fn is_log(self) -> bool {
self.0 == Self::LOG.0
}
#[must_use]
pub const fn is_application_defined(self) -> bool {
self.0 >= Self::FIRST_APPLICATION_DEFINED.0
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct MessageId(pub u32);
impl MessageId {
pub const ZERO: Self = Self(0);
#[must_use]
pub const fn new(raw: u32) -> Self {
Self(raw)
}
#[must_use]
pub const fn get(self) -> u32 {
self.0
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct MessageFlags(pub u8);
impl MessageFlags {
pub const EMPTY: Self = Self(0);
pub const FIRST: Self = Self(1 << 0);
pub const LAST: Self = Self(1 << 1);
#[must_use]
pub const fn from_bits(bits: u8) -> Self {
Self(bits)
}
#[must_use]
pub const fn bits(self) -> u8 {
self.0
}
#[must_use]
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
#[must_use]
pub const fn union(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct MessageData<'a> {
bytes: &'a [u8],
}
impl<'a> MessageData<'a> {
pub const EMPTY: Self = Self { bytes: &[] };
#[must_use]
pub const fn new(bytes: &'a [u8]) -> Self {
Self { bytes }
}
#[must_use]
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
#[must_use]
pub const fn len(self) -> usize {
self.bytes.len()
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.bytes.is_empty()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct MessageFrame<'a> {
pub channel_id: ChannelId,
pub message_id: MessageId,
pub message_len: u32,
pub fragment_offset: u32,
pub flags: MessageFlags,
pub data: MessageData<'a>,
}
impl<'a> MessageFrame<'a> {
#[must_use]
pub const fn new(
channel_id: ChannelId,
message_id: MessageId,
message_len: u32,
fragment_offset: u32,
flags: MessageFlags,
data: &'a [u8],
) -> Self {
Self {
channel_id,
message_id,
message_len,
fragment_offset,
flags,
data: MessageData::new(data),
}
}
#[must_use]
pub const fn is_first(self) -> bool {
self.flags.contains(MessageFlags::FIRST)
}
#[must_use]
pub const fn is_last(self) -> bool {
self.flags.contains(MessageFlags::LAST)
}
}
#[cfg(test)]
mod tests {
use super::{ChannelId, MessageFlags, MessageFrame, MessageId};
#[test]
fn message_frame_carries_message_fragment() {
let data = [1, 2, 3];
let frame = MessageFrame::new(
ChannelId::new(9),
MessageId::new(7),
10,
0,
MessageFlags::FIRST,
&data,
);
assert_eq!(frame.channel_id.get(), 9);
assert_eq!(frame.message_id.get(), 7);
assert_eq!(frame.data.len(), 3);
assert!(frame.is_first());
assert!(!frame.is_last());
}
}