sel4_async_block_io_fat/
block_io_wrapper.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7use core::convert::Infallible;
8use core::marker::PhantomData;
9
10use futures::future;
11
12use sel4_async_block_io::{
13    BlockIO, Operation,
14    access::{Access, Witness},
15    constant_block_sizes,
16};
17
18pub use embedded_fat as fat;
19
20pub struct BlockIOWrapper<T, A> {
21    inner: T,
22    _phantom: PhantomData<A>,
23}
24
25impl<T, A> BlockIOWrapper<T, A> {
26    pub fn new(inner: T) -> Self {
27        Self {
28            inner,
29            _phantom: PhantomData,
30        }
31    }
32}
33
34impl<T: BlockIO<A, BlockSize = constant_block_sizes::BlockSize512>, A: Access> fat::BlockDevice
35    for BlockIOWrapper<T, A>
36{
37    type Error = Infallible;
38
39    async fn read(
40        &self,
41        blocks: &mut [fat::Block],
42        start_block_idx: fat::BlockIdx,
43        _reason: &str,
44    ) -> Result<(), Self::Error> {
45        future::join_all(blocks.iter_mut().enumerate().map(|(i, block)| async move {
46            let block_idx = u64::from(start_block_idx.0)
47                .checked_add(i.try_into().unwrap())
48                .unwrap();
49            self.inner
50                .read_or_write_blocks(
51                    block_idx,
52                    Operation::Read {
53                        buf: &mut block.contents,
54                        witness: A::ReadWitness::TRY_WITNESS.unwrap(),
55                    },
56                )
57                .await
58        }))
59        .await;
60        Ok(())
61    }
62
63    async fn write(
64        &self,
65        blocks: &[fat::Block],
66        start_block_idx: fat::BlockIdx,
67    ) -> Result<(), Self::Error> {
68        future::join_all(blocks.iter().enumerate().map(|(i, block)| async move {
69            let block_idx = u64::from(start_block_idx.0)
70                .checked_add(i.try_into().unwrap())
71                .unwrap();
72            self.inner
73                .read_or_write_blocks(
74                    block_idx,
75                    Operation::Write {
76                        buf: &block.contents,
77                        witness: A::WriteWitness::TRY_WITNESS.unwrap(),
78                    },
79                )
80                .await
81        }))
82        .await;
83        Ok(())
84    }
85
86    async fn num_blocks(&self) -> Result<fat::BlockCount, Self::Error> {
87        Ok(fat::BlockCount(self.inner.num_blocks().try_into().unwrap()))
88    }
89}