block_device_driver/
lib.rs1#![cfg_attr(not(test), no_std)]
4#![warn(missing_docs)]
5#![allow(async_fn_in_trait)]
6
7use aligned::Aligned;
8
9pub trait BlockDevice<const SIZE: usize> {
28 type Error: core::fmt::Debug;
30
31 type Align: aligned::Alignment;
33
34 async fn read(
36 &mut self,
37 block_address: u32,
38 data: &mut [Aligned<Self::Align, [u8; SIZE]>],
39 ) -> Result<(), Self::Error>;
40
41 async fn write(
43 &mut self,
44 block_address: u32,
45 data: &[Aligned<Self::Align, [u8; SIZE]>],
46 ) -> Result<(), Self::Error>;
47
48 async fn size(&mut self) -> Result<u64, Self::Error>;
50}
51
52impl<T: BlockDevice<SIZE>, const SIZE: usize> BlockDevice<SIZE> for &mut T {
53 type Error = T::Error;
54 type Align = T::Align;
55
56 async fn read(
57 &mut self,
58 block_address: u32,
59 data: &mut [Aligned<Self::Align, [u8; SIZE]>],
60 ) -> Result<(), Self::Error> {
61 (*self).read(block_address, data).await
62 }
63
64 async fn write(
65 &mut self,
66 block_address: u32,
67 data: &[Aligned<Self::Align, [u8; SIZE]>],
68 ) -> Result<(), Self::Error> {
69 (*self).write(block_address, data).await
70 }
71
72 async fn size(&mut self) -> Result<u64, Self::Error> {
73 (*self).size().await
74 }
75}
76
77pub fn slice_to_blocks<ALIGN, const SIZE: usize>(slice: &[u8]) -> &[Aligned<ALIGN, [u8; SIZE]>]
85where
86 ALIGN: aligned::Alignment,
87{
88 let align: usize = core::mem::align_of::<Aligned<ALIGN, ()>>();
89 assert!(slice.len() % SIZE == 0);
90 assert!(slice.len() % align == 0);
91 assert!(slice.as_ptr().cast::<u8>() as usize % align == 0);
92 unsafe {
94 core::slice::from_raw_parts(
95 slice.as_ptr() as *const Aligned<ALIGN, [u8; SIZE]>,
96 slice.len() / SIZE,
97 )
98 }
99}
100
101pub fn slice_to_blocks_mut<ALIGN, const SIZE: usize>(
109 slice: &mut [u8],
110) -> &mut [Aligned<ALIGN, [u8; SIZE]>]
111where
112 ALIGN: aligned::Alignment,
113{
114 let align: usize = core::mem::align_of::<Aligned<ALIGN, [u8; SIZE]>>();
115 assert!(slice.len() % SIZE == 0);
116 assert!(slice.len() % align == 0);
117 assert!(slice.as_ptr().cast::<u8>() as usize % align == 0);
118 unsafe {
120 core::slice::from_raw_parts_mut(
121 slice.as_mut_ptr() as *mut Aligned<ALIGN, [u8; SIZE]>,
122 slice.len() / SIZE,
123 )
124 }
125}
126
127pub fn blocks_to_slice<ALIGN, const SIZE: usize>(buf: &[Aligned<ALIGN, [u8; SIZE]>]) -> &[u8]
133where
134 ALIGN: aligned::Alignment,
135{
136 let align: usize = core::mem::align_of::<Aligned<ALIGN, ()>>();
139 assert!(SIZE % align == 0);
140 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * SIZE) }
142}
143
144pub fn blocks_to_slice_mut<ALIGN, const SIZE: usize>(
150 buf: &mut [Aligned<ALIGN, [u8; SIZE]>],
151) -> &mut [u8]
152where
153 ALIGN: aligned::Alignment,
154{
155 let align: usize = core::mem::align_of::<Aligned<ALIGN, ()>>();
158 assert!(SIZE % align == 0);
159 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len() * SIZE) }
161}
162
163#[cfg(test)]
164mod test {
165 use super::*;
166
167 #[test]
168 fn test_conversion_round_trip() {
169 let blocks = &mut [
170 Aligned::<aligned::A4, _>([0; 512]),
171 Aligned::<aligned::A4, _>([0; 512]),
172 ];
173 let slice = blocks_to_slice_mut(blocks);
174 assert!(slice.len() == 1024);
175 let blocks: &mut [Aligned<aligned::A4, [u8; 512]>] = slice_to_blocks_mut(slice);
176 assert!(blocks.len() == 2);
177 }
178}