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