use super::Encode;
use bytes::{BufMut, BytesMut};
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct U24(pub(crate) u8, pub(crate) u16);
impl U24 {
pub const MAX: u32 = u32::MAX >> 8;
pub const MIN: u32 = 0;
pub fn new(higher_bits: u8, lower_bits: u16) -> Self {
U24(higher_bits, lower_bits)
}
pub fn from_u32(val: u32) -> Self {
assert!(val <= U24::MAX);
U24((val >> 16) as u8, val as u16)
}
pub fn from_usize(val: usize) -> Self {
assert!(val <= U24::MAX as usize);
U24((val as u32 >> 16) as u8, (val as u32) as u16)
}
pub fn into_u32(self) -> u32 {
((self.0 as u32) << 16) | (self.1 as u32)
}
pub fn into_usize(self) -> usize {
((self.0 as usize) << 16) | (self.1 as usize)
}
}
impl Encode for U24 {
fn len(&self) -> usize {
3
}
fn encode(&self, buf: &mut BytesMut) {
buf.put_u8(self.0);
buf.put_u16(self.1);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_u24_min() {
assert_eq!(U24::MIN, 0);
}
#[test]
fn test_u24_max() {
assert_eq!(U24::MAX, 16_777_215);
}
#[test]
fn test_from_to_u32() {
assert_eq!(U24::from_u32(U24::MAX).into_u32(), U24::MAX);
}
#[test]
fn test_from_to_usize() {
assert_eq!(
U24::from_usize(U24::MAX as usize).into_usize(),
U24::MAX as usize
);
}
#[test]
#[should_panic]
fn test_from_invalid_u32() {
U24::from_u32(U24::MAX as u32 + 1);
}
#[test]
#[should_panic]
fn test_from_invalid_usize() {
U24::from_usize(U24::MAX as usize + 1);
}
}