pub struct Frame<'a> {
pub(crate) data: &'a [u8],
pub width: u32,
pub height: u32,
pub pixel_format: PixelFormat,
pub timestamp_ns: u64,
pub frame_id: u64,
}
impl<'a> Frame<'a> {
pub fn new(
data: &'a [u8],
width: u32,
height: u32,
pixel_format: PixelFormat,
timestamp_ns: u64,
frame_id: u64,
) -> Self {
Self {
data,
width,
height,
pixel_format,
timestamp_ns,
frame_id,
}
}
pub fn data(&self) -> &[u8] {
self.data
}
pub fn to_vec(&self) -> Vec<u8> {
self.data.to_vec()
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PixelFormat {
Mono8,
Bgr8,
Other(u32),
}
impl PixelFormat {
pub fn from_raw(raw: u32) -> Self {
match raw {
0x0108_0001 => PixelFormat::Mono8,
0x0218_0015 => PixelFormat::Bgr8,
other => PixelFormat::Other(other),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pixel_format_maps_known_codes() {
assert_eq!(PixelFormat::from_raw(0x0108_0001), PixelFormat::Mono8);
assert_eq!(PixelFormat::from_raw(0x0218_0015), PixelFormat::Bgr8);
}
#[test]
fn pixel_format_preserves_unknown_codes() {
assert_eq!(
PixelFormat::from_raw(0xdead_beef),
PixelFormat::Other(0xdead_beef)
);
}
#[test]
fn frame_basic_accessors() {
let data = [1u8, 2, 3, 4, 5, 6, 7, 8];
let frame = Frame::new(&data, 2, 4, PixelFormat::Mono8, 123, 7);
assert_eq!(frame.len(), 8);
assert!(!frame.is_empty());
assert_eq!(frame.to_vec(), vec![1, 2, 3, 4, 5, 6, 7, 8]);
assert_eq!(frame.data(), &data);
assert_eq!(frame.width, 2);
assert_eq!(frame.height, 4);
assert_eq!(frame.pixel_format, PixelFormat::Mono8);
assert_eq!(frame.timestamp_ns, 123);
assert_eq!(frame.frame_id, 7);
}
#[test]
fn frame_is_empty_when_no_bytes() {
let frame = Frame::new(&[], 0, 0, PixelFormat::Mono8, 0, 0);
assert_eq!(frame.len(), 0);
assert!(frame.is_empty());
assert_eq!(frame.to_vec(), Vec::<u8>::new());
}
}