1use core::convert::TryFrom;
22use core::fmt;
23use core::marker::PhantomData;
24use crate::bitfield::BitFieldTrait;
25
26pub trait BitFieldAccess : private::Sealed
32{
33 fn get_bitfield(&self, mask: Self, shift: u32) -> Self;
35
36 fn set_bitfield(&mut self, mask: Self, shift: u32, value: Self);
38}
39
40mod private {
42 pub trait Sealed {}
43
44 impl Sealed for u8 { }
45 impl Sealed for u16 { }
46 impl Sealed for u32 { }
47 impl Sealed for u64 { }
48 impl Sealed for usize { }
49}
50
51#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
54pub struct Storage<TMarker, TData>
55where TData: BitFieldAccess
56{
57 data: TData,
59
60 owner: PhantomData<TMarker>
62}
63
64macro_rules! impl_storage {
65 ($type:ident) => {
66 impl<TMarker> Storage<TMarker, $type>
67 {
68 pub fn new() -> Self {
70 Storage {
71 data: $type::default(),
72 owner: PhantomData,
73 }
74 }
75
76 pub fn get<TBitField>(&self) -> $type
78 where
79 TBitField: BitFieldTrait<Owner=Self>
80 {
81 self.data.get_bitfield(TBitField::MASK as $type, TBitField::SHIFT)
82 }
83
84 pub fn set<TBitField>(&mut self, value: $type)
86 where
87 TBitField: BitFieldTrait<Owner=Self>
88 {
89 self.data.set_bitfield(TBitField::MASK as $type, TBitField::SHIFT, value);
90 }
91 }
92
93 impl BitFieldAccess for $type {
94 fn get_bitfield(&self, mask: Self, shift: u32) -> Self {
95 (self & mask as $type).wrapping_shr(shift)
96 }
97
98 fn set_bitfield(&mut self, mask: Self, shift: u32, field: Self) {
99 *self = *self & !mask as $type | (field.wrapping_shl(shift) & mask as $type);
100 }
101 }
102
103 impl<TMarker> fmt::Display for Storage<TMarker, $type>
104 {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 write!(f, "{}", self.data)
107 }
108 }
109
110 impl<TMarker> fmt::UpperHex for Storage<TMarker, $type>
111 {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 fmt::UpperHex::fmt(&self, f)
114 }
115 }
116
117 impl<TMarker> fmt::LowerHex for Storage<TMarker, $type>
118 {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 fmt::LowerHex::fmt(&self, f)
121 }
122 }
123
124 impl<TMarker> fmt::Octal for Storage<TMarker, $type>
125 {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 fmt::Octal::fmt(&self, f)
128 }
129 }
130
131 impl<TMarker> fmt::Binary for Storage<TMarker, $type>
132 {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 fmt::Binary::fmt(&self, f)
135 }
136 }
137 };
138}
139
140macro_rules! impl_from {
141 ($type:ident, $from:ident) => {
142 impl<TMarker> From<$from> for Storage<TMarker, $type>
143 {
144 fn from(value: $from) -> Self {
145 Self {
146 data: value.into(),
147 owner: PhantomData,
148 }
149 }
150 }
151 };
152}
153
154macro_rules! impl_tryfrom {
155 ($type:ident, $from:ident) => {
156 impl<TMarker> TryFrom<$from> for Storage<TMarker, $type>
157 {
158 type Error = <$type as TryFrom<$from>>::Error;
159
160 fn try_from(value: $from) -> Result<Self, <$type as TryFrom<$from>>::Error> {
161 Ok(Self {
162 data: $type::try_from(value)?,
163 owner: PhantomData,
164 })
165 }
166 }
167 };
168}
169
170impl_storage!(u8);
171impl_from!(u8, u8);
172impl_tryfrom!(u8, u16);
173impl_tryfrom!(u8, u32);
174impl_tryfrom!(u8, u64);
175impl_tryfrom!(u8, usize);
176
177impl_storage!(u16);
178impl_from!(u16, u8);
179impl_from!(u16, u16);
180impl_tryfrom!(u16, u32);
181impl_tryfrom!(u16, u64);
182impl_tryfrom!(u16, usize);
183
184impl_storage!(u32);
185impl_from!(u32, u8);
186impl_from!(u32, u16);
187impl_from!(u32, u32);
188impl_tryfrom!(u32, u64);
189impl_tryfrom!(u32, usize);
190
191impl_storage!(u64);
192impl_from!(u64, u8);
193impl_from!(u64, u16);
194impl_from!(u64, u32);
195impl_from!(u64, u64);
196impl_tryfrom!(u64, usize);
197
198impl_storage!(usize);
199impl_from!(usize, u8);
200impl_from!(usize, u16);
201impl_tryfrom!(usize, u32);
202impl_tryfrom!(usize, u64);
203impl_from!(usize, usize);
204
205#[cfg(test)]
206mod test {
207 use super::*;
208
209 #[test]
210 fn test_send() {
211 struct Marker;
212
213 fn assert_send<T: Send>() {}
214 assert_send::<Storage<Marker, u8>>();
215 assert_send::<Storage<Marker, u16>>();
216 assert_send::<Storage<Marker, u32>>();
217 assert_send::<Storage<Marker, u64>>();
218 assert_send::<Storage<Marker, usize>>();
219 }
220
221 #[test]
222 fn test_sync() {
223 struct Marker;
224
225 fn assert_sync<T: Sync>() {}
226 assert_sync::<Storage<Marker, u8>>();
227 assert_sync::<Storage<Marker, u16>>();
228 assert_sync::<Storage<Marker, u32>>();
229 assert_sync::<Storage<Marker, u64>>();
230 assert_sync::<Storage<Marker, usize>>();
231 }
232}