1#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Frame {
12 pub time: std::time::Duration,
16
17 pub data: Vec<u8>,
19}
20
21impl TryFrom<Frame> for Vec<u8> {
22 type Error = crate::error::Error;
23
24 fn try_from(frame: Frame) -> crate::error::Result<Self> {
25 let secs = u32::try_from(frame.time.as_secs()).map_err(|_| {
26 crate::error::Error::FrameTooLong {
27 input: frame.time.as_secs(),
28 }
29 })?;
30 let micros = frame.time.subsec_micros();
31 let len = u32::try_from(frame.data.len()).map_err(|_| {
32 crate::error::Error::FrameTooBig {
33 input: frame.data.len(),
34 }
35 })?;
36 let mut bytes = vec![];
37 bytes.extend(secs.to_le_bytes().iter());
38 bytes.extend(micros.to_le_bytes().iter());
39 bytes.extend(len.to_le_bytes().iter());
40 bytes.extend(frame.data.iter());
41 Ok(bytes)
42 }
43}
44
45#[cfg(test)]
46#[allow(clippy::unwrap_used)]
47mod test {
48 use super::*;
49
50 #[test]
51 fn test_basic() {
52 let tests = vec![
53 (
54 Frame {
55 time: std::time::Duration::new(0, 0),
56 data: vec![],
57 },
58 vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
59 ),
60 (
61 Frame {
62 time: std::time::Duration::new(38, 123_456_000),
63 data: b"\x1b[2Jfoobar".to_vec(),
64 },
65 vec![
66 38, 0, 0, 0, 64, 226, 1, 0, 10, 0, 0, 0, 27, 91, 50, 74,
67 102, 111, 111, 98, 97, 114,
68 ],
69 ),
70 ];
71 for (frame, bytes) in tests {
72 assert_eq!(Vec::<u8>::try_from(frame).unwrap(), bytes);
73 }
74 }
75}