1use core::marker::PhantomData;
2
3use crate::{FieldSet, ReadCapability, WriteCapability};
4
5pub trait RegisterInterface {
9    type Error;
11    type AddressType: Copy;
13
14    fn write_register(
16        &mut self,
17        address: Self::AddressType,
18        size_bits: u32,
19        data: &[u8],
20    ) -> Result<(), Self::Error>;
21
22    fn read_register(
24        &mut self,
25        address: Self::AddressType,
26        size_bits: u32,
27        data: &mut [u8],
28    ) -> Result<(), Self::Error>;
29}
30
31pub trait AsyncRegisterInterface {
35    type Error;
37    type AddressType: Copy;
39
40    async fn write_register(
42        &mut self,
43        address: Self::AddressType,
44        size_bits: u32,
45        data: &[u8],
46    ) -> Result<(), Self::Error>;
47
48    async fn read_register(
50        &mut self,
51        address: Self::AddressType,
52        size_bits: u32,
53        data: &mut [u8],
54    ) -> Result<(), Self::Error>;
55}
56
57pub struct RegisterOperation<'i, Interface, AddressType: Copy, Register: FieldSet, Access> {
59    interface: &'i mut Interface,
60    address: AddressType,
61    register_new_with_reset: fn() -> Register,
62    _phantom: PhantomData<(Register, Access)>,
63}
64
65impl<'i, Interface, AddressType: Copy, Register: FieldSet, Access>
66    RegisterOperation<'i, Interface, AddressType, Register, Access>
67{
68    #[doc(hidden)]
69    pub fn new(
70        interface: &'i mut Interface,
71        address: AddressType,
72        register_new_with_reset: fn() -> Register,
73    ) -> Self {
74        Self {
75            interface,
76            address,
77            register_new_with_reset,
78            _phantom: PhantomData,
79        }
80    }
81}
82
83impl<Interface, AddressType: Copy, Register: FieldSet, Access>
84    RegisterOperation<'_, Interface, AddressType, Register, Access>
85where
86    Interface: RegisterInterface<AddressType = AddressType>,
87    Access: WriteCapability,
88{
89    pub fn write<R>(&mut self, f: impl FnOnce(&mut Register) -> R) -> Result<R, Interface::Error> {
94        let mut register = (self.register_new_with_reset)();
95        let returned = f(&mut register);
96
97        self.interface.write_register(
98            self.address,
99            Register::SIZE_BITS,
100            register.get_inner_buffer(),
101        )?;
102        Ok(returned)
103    }
104
105    pub fn write_with_zero<R>(
109        &mut self,
110        f: impl FnOnce(&mut Register) -> R,
111    ) -> Result<R, Interface::Error> {
112        let mut register = Register::new_with_zero();
113        let returned = f(&mut register);
114        self.interface.write_register(
115            self.address,
116            Register::SIZE_BITS,
117            register.get_inner_buffer_mut(),
118        )?;
119        Ok(returned)
120    }
121}
122
123impl<Interface, AddressType: Copy, Register: FieldSet, Access>
124    RegisterOperation<'_, Interface, AddressType, Register, Access>
125where
126    Interface: RegisterInterface<AddressType = AddressType>,
127    Access: ReadCapability,
128{
129    pub fn read(&mut self) -> Result<Register, Interface::Error> {
131        let mut register = Register::new_with_zero();
132
133        self.interface.read_register(
134            self.address,
135            Register::SIZE_BITS,
136            register.get_inner_buffer_mut(),
137        )?;
138        Ok(register)
139    }
140}
141
142impl<Interface, AddressType: Copy, Register: FieldSet, Access>
143    RegisterOperation<'_, Interface, AddressType, Register, Access>
144where
145    Interface: RegisterInterface<AddressType = AddressType>,
146    Access: ReadCapability + WriteCapability,
147{
148    pub fn modify<R>(&mut self, f: impl FnOnce(&mut Register) -> R) -> Result<R, Interface::Error> {
153        let mut register = self.read()?;
154        let returned = f(&mut register);
155        self.interface.write_register(
156            self.address,
157            Register::SIZE_BITS,
158            register.get_inner_buffer_mut(),
159        )?;
160        Ok(returned)
161    }
162}
163
164impl<Interface, AddressType: Copy, Register: FieldSet, Access>
165    RegisterOperation<'_, Interface, AddressType, Register, Access>
166where
167    Interface: AsyncRegisterInterface<AddressType = AddressType>,
168    Access: WriteCapability,
169{
170    pub async fn write_async<R>(
175        &mut self,
176        f: impl FnOnce(&mut Register) -> R,
177    ) -> Result<R, Interface::Error> {
178        let mut register = (self.register_new_with_reset)();
179        let returned = f(&mut register);
180
181        self.interface
182            .write_register(
183                self.address,
184                Register::SIZE_BITS,
185                register.get_inner_buffer(),
186            )
187            .await?;
188        Ok(returned)
189    }
190
191    pub async fn write_with_zero_async<R>(
195        &mut self,
196        f: impl FnOnce(&mut Register) -> R,
197    ) -> Result<R, Interface::Error> {
198        let mut register = Register::new_with_zero();
199        let returned = f(&mut register);
200        self.interface
201            .write_register(
202                self.address,
203                Register::SIZE_BITS,
204                register.get_inner_buffer_mut(),
205            )
206            .await?;
207        Ok(returned)
208    }
209}
210
211impl<Interface, AddressType: Copy, Register: FieldSet, Access>
212    RegisterOperation<'_, Interface, AddressType, Register, Access>
213where
214    Interface: AsyncRegisterInterface<AddressType = AddressType>,
215    Access: ReadCapability,
216{
217    pub async fn read_async(&mut self) -> Result<Register, Interface::Error> {
219        let mut register = Register::new_with_zero();
220
221        self.interface
222            .read_register(
223                self.address,
224                Register::SIZE_BITS,
225                register.get_inner_buffer_mut(),
226            )
227            .await?;
228        Ok(register)
229    }
230}
231
232impl<Interface, AddressType: Copy, Register: FieldSet, Access>
233    RegisterOperation<'_, Interface, AddressType, Register, Access>
234where
235    Interface: AsyncRegisterInterface<AddressType = AddressType>,
236    Access: ReadCapability + WriteCapability,
237{
238    pub async fn modify_async<R>(
243        &mut self,
244        f: impl FnOnce(&mut Register) -> R,
245    ) -> Result<R, Interface::Error> {
246        let mut register = self.read_async().await?;
247        let returned = f(&mut register);
248        self.interface
249            .write_register(
250                self.address,
251                Register::SIZE_BITS,
252                register.get_inner_buffer(),
253            )
254            .await?;
255        Ok(returned)
256    }
257}