spectrusty_core/clock/
packed.rs

1/*
2    Copyright (C) 2020-2022  Rafal Michalski
3
4    This file is part of SPECTRUSTY, a Rust library for building emulators.
5
6    For the full copyright notice, see the lib.rs file.
7*/
8use super::{Ts, FTs, VideoTs, VFrameTs, VideoFrame};
9
10macro_rules! video_ts_packed_data {
11    ($name:ident, $bits:literal) => {
12        /// A timestamp with packed N-bits of data.
13        #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Debug)]
14        pub struct $name {
15            pub vc: Ts,
16            hc_data: Ts,
17        }
18
19        impl From<(VideoTs, u8)> for $name {
20            fn from(tuple: (VideoTs, u8)) -> Self {
21                let (vts, data) = tuple;
22                $name::new(vts, data)
23            }
24        }
25
26        impl<V> From<(VFrameTs<V>, u8)> for $name {
27            fn from(tuple: (VFrameTs<V>, u8)) -> Self {
28                let (vts, data) = tuple;
29                $name::new(vts.into(), data)
30            }
31        }
32
33        impl From<$name> for (VideoTs, u8) {
34            fn from(vtsd: $name) -> Self {
35                let $name { vc, hc_data } = vtsd;
36                let data = (hc_data as u8) & ((1 << $bits) - 1);
37                (VideoTs { vc, hc: hc_data >> $bits}, data)
38            }
39        }
40
41        impl<V: VideoFrame> From<$name> for (VFrameTs<V>, u8) {
42            fn from(vtsd: $name) -> Self {
43                let $name { vc, hc_data } = vtsd;
44                let data = (hc_data as u8) & ((1 << $bits) - 1);
45                (VFrameTs::new(vc, hc_data >> $bits), data)
46            }
47        }
48
49        impl From<$name> for VideoTs {
50            fn from(vtsd: $name) -> Self {
51                let $name { vc, hc_data } = vtsd;
52                VideoTs { vc, hc: hc_data >> $bits}
53            }
54        }
55
56        impl<V: VideoFrame> From<$name> for VFrameTs<V> {
57            fn from(vtsd: $name) -> Self {
58                let $name { vc, hc_data } = vtsd;
59                VFrameTs::new(vc, hc_data >> $bits)
60            }
61        }
62
63        impl From<&$name> for VideoTs {
64            fn from(vtsd: &$name) -> Self {
65                Self::from(*vtsd)
66            }
67        }
68
69        impl<V: VideoFrame> From<&$name> for VFrameTs<V> {
70            fn from(vtsd: &$name) -> Self {
71                Self::from(*vtsd)
72            }
73        }
74
75        impl $name {
76            const DATA_MASK: Ts = (1 << $bits) - 1;
77            #[inline]
78            pub const fn new(vts: VideoTs, data: u8) -> Self {
79                let VideoTs { vc, hc } = vts;
80                let hc_data = (hc << $bits) | (data as Ts & Self::DATA_MASK) as Ts;
81                Self { vc, hc_data }
82            }
83
84            #[inline]
85            pub fn into_data(self) -> u8 {
86                (self.hc_data & Self::DATA_MASK) as u8
87            }
88
89            #[inline]
90            pub fn data(&self) -> u8 {
91                (self.hc_data & Self::DATA_MASK) as u8
92            }
93
94            #[inline]
95            pub fn set_data(&mut self, data: u8) {
96                self.hc_data = (self.hc_data & !Self::DATA_MASK) | (data as Ts & Self::DATA_MASK);
97            }
98
99            #[inline]
100            pub fn hc(&self) -> Ts {
101                self.hc_data >> $bits
102            }
103        }
104    }
105}
106
107video_ts_packed_data! { VideoTsData1, 1 }
108video_ts_packed_data! { VideoTsData2, 2 }
109video_ts_packed_data! { VideoTsData3, 3 }
110video_ts_packed_data! { VideoTsData6, 6 }
111
112macro_rules! fts_packed_data {
113    ($name:ident, $bits:literal) => {
114        /// A timestamp with packed N-bits of data.
115        #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Debug)]
116        pub struct $name(FTs);
117
118        impl From<(FTs, u8)> for $name {
119            fn from(tuple: (FTs, u8)) -> Self {
120                let (ts, data) = tuple;
121                $name::new(ts, data)
122            }
123        }
124
125        impl From<$name> for (FTs, u8) {
126            fn from(ftsd: $name) -> Self {
127                let $name(pack) = ftsd;
128                let data = (pack as u8) & ((1 << $bits) - 1);
129                (pack >> $bits, data)
130            }
131        }
132
133        impl From<$name> for FTs {
134            fn from(ftsd: $name) -> Self {
135                let $name(pack) = ftsd;
136                pack >> $bits
137            }
138        }
139
140        impl $name {
141            const DATA_MASK: FTs = (1 << $bits) - 1;
142            #[inline]
143            pub const fn new(fts: FTs, data: u8) -> Self {
144                let pack = (fts << $bits) | (data as FTs & Self::DATA_MASK);
145                Self(pack)
146            }
147
148            #[inline]
149            pub fn into_data(self) -> u8 {
150                (self.0 & Self::DATA_MASK) as u8
151            }
152
153            #[inline]
154            pub fn data(&self) -> u8 {
155                (self.0 & Self::DATA_MASK) as u8
156            }
157
158            #[inline]
159            pub fn set_data(&mut self, data: u8) {
160                self.0 = (self.0 & !Self::DATA_MASK) | (data as FTs & Self::DATA_MASK);
161            }
162        }
163    }
164}
165
166fts_packed_data! { FTsData1, 1 }
167fts_packed_data! { FTsData2, 2 }
168fts_packed_data! { FTsData3, 3 }