use crate::core::{ChannelId, Error, ErrorKind, MessageFrame, MessageId, Result};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct MessageKey {
pub channel_id: ChannelId,
pub message_id: MessageId,
}
impl MessageKey {
#[must_use]
pub const fn new(channel_id: ChannelId, message_id: MessageId) -> Self {
Self {
channel_id,
message_id,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct FragmentRange {
pub offset: u32,
pub len: u32,
}
impl FragmentRange {
#[must_use]
pub const fn new(offset: u32, len: u32) -> Self {
Self { offset, len }
}
#[must_use]
pub const fn end(self) -> u32 {
self.offset.saturating_add(self.len)
}
#[must_use]
pub const fn is_empty(self) -> bool {
self.len == 0
}
#[must_use]
pub const fn fits_in(self, message_len: u32) -> bool {
self.offset <= message_len && self.end() <= message_len
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct MessageFragment {
pub key: MessageKey,
pub message_len: u32,
pub range: FragmentRange,
}
impl MessageFragment {
#[must_use]
pub const fn new(key: MessageKey, message_len: u32, range: FragmentRange) -> Self {
Self {
key,
message_len,
range,
}
}
pub fn try_from_message_frame(frame: MessageFrame<'_>) -> Result<Self> {
let len =
u32::try_from(frame.data.len()).map_err(|_| Error::new(ErrorKind::Reliability))?;
let range = FragmentRange::new(frame.fragment_offset, len);
if !range.fits_in(frame.message_len) {
return Err(Error::new(ErrorKind::Reliability));
}
Ok(Self::new(
MessageKey::new(frame.channel_id, frame.message_id),
frame.message_len,
range,
))
}
}
#[cfg(test)]
mod tests {
use crate::core::{ChannelId, MessageFlags, MessageFrame, MessageId};
use super::{FragmentRange, MessageFragment, MessageKey};
#[test]
fn fragment_range_must_fit_message_len() {
assert!(FragmentRange::new(2, 3).fits_in(5));
assert!(!FragmentRange::new(3, 3).fits_in(5));
}
#[test]
fn message_frame_maps_to_message_fragment() {
let bytes = [1, 2, 3];
let frame = MessageFrame::new(
ChannelId::new(7),
MessageId::new(9),
8,
2,
MessageFlags::EMPTY,
&bytes,
);
let fragment = MessageFragment::try_from_message_frame(frame).unwrap();
assert_eq!(
fragment.key,
MessageKey::new(ChannelId::new(7), MessageId::new(9))
);
assert_eq!(fragment.range, FragmentRange::new(2, 3));
}
}