hadris_block/
volume_async.rs1use crate::detect::{BlockFormat, FatVariant};
2use crate::{Error, Result};
3use hadris_fat::r#async::fat_table::FatType;
4use hadris_fat::r#async::fs::FatVolume;
5use hadris_io::SeekFrom;
6use hadris_io::r#async::{Borrowed, Read, Seek};
7
8#[non_exhaustive]
10pub enum OpenVolume<'a, S>
11where
12 S: Seek,
13{
14 Fat(FatVolume<Borrowed<'a, S>>),
16}
17
18impl<'a, S> OpenVolume<'a, S>
19where
20 S: Read + Seek<Error = <S as Read>::Error>,
21{
22 pub async fn open(source: &'a mut S, logical_block_size: u32) -> Result<Self> {
26 match crate::detect::r#async::detect(source, logical_block_size).await? {
27 Some(BlockFormat::Fat(format)) => Self::open_detected(source, format).await,
28 Some(BlockFormat::PartitionTable(kind)) => Err(Error::PartitionedDisk(kind)),
29 None => Err(Error::UnknownFormat),
30 }
31 }
32
33 pub async fn open_detected(source: &'a mut S, detected: FatVariant) -> Result<Self> {
35 if detected == FatVariant::ExFat {
36 return Err(Error::UnsupportedFormat(BlockFormat::Fat(detected)));
37 }
38 source
39 .seek(SeekFrom::Start(0))
40 .await
41 .map_err(hadris_io::Error::erase)?;
42 let fat = FatVolume::open(Borrowed::new(source)).await?;
43 let opened = fat_variant(fat.fat_type());
44 if opened != detected {
45 return Err(Error::DetectedFormatMismatch { detected, opened });
46 }
47 Ok(Self::Fat(fat))
48 }
49
50 pub fn format(&self) -> FatVariant {
52 match self {
53 Self::Fat(fat) => fat_variant(fat.fat_type()),
54 }
55 }
56
57 pub fn as_fat(&self) -> Option<&FatVolume<Borrowed<'a, S>>> {
59 match self {
60 Self::Fat(fat) => Some(fat),
61 }
62 }
63
64 pub fn as_fat_mut(&mut self) -> Option<&mut FatVolume<Borrowed<'a, S>>> {
66 match self {
67 Self::Fat(fat) => Some(fat),
68 }
69 }
70
71 #[allow(clippy::result_large_err)]
72 pub fn into_fat(self) -> core::result::Result<FatVolume<Borrowed<'a, S>>, Self> {
74 match self {
75 Self::Fat(fat) => Ok(fat),
76 }
77 }
78
79 pub fn into_inner(self) -> &'a mut S {
81 match self {
82 Self::Fat(fat) => fat.into_inner().0,
83 }
84 }
85}
86
87fn fat_variant(format: FatType) -> FatVariant {
88 match format {
89 FatType::Fat12 => FatVariant::Fat12,
90 FatType::Fat16 => FatVariant::Fat16,
91 FatType::Fat32 => FatVariant::Fat32,
92 }
93}