use std::borrow::Cow;
use crate::memory::{MSize, MemoryResult};
use crate::prelude::PageOffset;
pub const DEFAULT_ALIGNMENT: MSize = 32;
pub trait Encode: Clone {
const SIZE: DataSize;
const ALIGNMENT: PageOffset;
fn encode(&'_ self) -> Cow<'_, [u8]>;
fn decode(data: Cow<[u8]>) -> MemoryResult<Self>
where
Self: Sized;
fn size(&self) -> MSize;
}
pub(crate) fn saturating_size(header: MSize, payload_len: usize) -> MSize {
MSize::try_from(payload_len).map_or(MSize::MAX, |len| header.saturating_add(len))
}
pub(crate) fn length_prefix(len: usize) -> [u8; 2] {
u16::try_from(len).unwrap_or(u16::MAX).to_le_bytes()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataSize {
Fixed(MSize),
Dynamic,
}
impl DataSize {
pub fn get_fixed_size(&self) -> Option<MSize> {
match self {
DataSize::Fixed(size) => Some(*size),
DataSize::Dynamic => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_saturating_size_is_exact_when_it_fits() {
assert_eq!(saturating_size(2, 0), 2);
assert_eq!(saturating_size(2, 65_533), MSize::MAX);
assert_eq!(saturating_size(0, 65_535), MSize::MAX);
}
#[test]
fn test_saturating_size_saturates_when_it_does_not_fit() {
assert_eq!(saturating_size(2, 65_534), MSize::MAX);
assert_eq!(saturating_size(0, 65_536), MSize::MAX);
assert_eq!(saturating_size(2, usize::MAX), MSize::MAX);
}
#[test]
fn test_length_prefix_saturates_at_u16_max() {
assert_eq!(length_prefix(0), [0, 0]);
assert_eq!(length_prefix(65_535), [0xFF, 0xFF]);
assert_eq!(length_prefix(65_536), [0xFF, 0xFF]);
}
#[test]
fn test_should_get_data_size_fixed() {
let size = DataSize::Fixed(10);
assert_eq!(size.get_fixed_size(), Some(10));
let variable_size = DataSize::Dynamic;
assert_eq!(variable_size.get_fixed_size(), None);
}
}