affs_read/
types.rs

1//! Core types for AFFS.
2
3/// Block device trait for reading blocks from storage.
4///
5/// Implement this trait for your storage medium (file, memory, hardware, etc.).
6pub trait BlockDevice {
7    /// Read a single 512-byte block.
8    ///
9    /// # Arguments
10    /// * `block` - Block number to read
11    /// * `buf` - Buffer to read into (must be exactly 512 bytes)
12    ///
13    /// # Returns
14    /// `Ok(())` on success, `Err(())` on failure.
15    #[allow(clippy::result_unit_err)]
16    fn read_block(&self, block: u32, buf: &mut [u8; 512]) -> Result<(), ()>;
17}
18
19/// Filesystem type.
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum FsType {
22    /// Original File System.
23    Ofs,
24    /// Fast File System.
25    Ffs,
26}
27
28impl FsType {
29    /// Returns the data payload size per block.
30    #[inline]
31    pub const fn data_block_size(self) -> usize {
32        match self {
33            Self::Ofs => crate::OFS_DATA_SIZE,
34            Self::Ffs => crate::FFS_DATA_SIZE,
35        }
36    }
37}
38
39/// Entry type in the filesystem.
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum EntryType {
42    /// Root directory.
43    Root,
44    /// Directory.
45    Dir,
46    /// File.
47    File,
48    /// Hard link to file.
49    HardLinkFile,
50    /// Hard link to directory.
51    HardLinkDir,
52    /// Soft link.
53    SoftLink,
54}
55
56impl EntryType {
57    /// Create from secondary type value.
58    pub const fn from_sec_type(sec_type: i32) -> Option<Self> {
59        match sec_type {
60            crate::ST_ROOT => Some(Self::Root),
61            crate::ST_DIR => Some(Self::Dir),
62            crate::ST_FILE => Some(Self::File),
63            crate::ST_LFILE => Some(Self::HardLinkFile),
64            crate::ST_LDIR => Some(Self::HardLinkDir),
65            crate::ST_LSOFT => Some(Self::SoftLink),
66            _ => None,
67        }
68    }
69
70    /// Returns true if this is a directory type.
71    #[inline]
72    pub const fn is_dir(self) -> bool {
73        matches!(self, Self::Root | Self::Dir | Self::HardLinkDir)
74    }
75
76    /// Returns true if this is a file type.
77    #[inline]
78    pub const fn is_file(self) -> bool {
79        matches!(self, Self::File | Self::HardLinkFile)
80    }
81}
82
83/// Filesystem flags.
84#[derive(Debug, Clone, Copy, Default)]
85pub struct FsFlags {
86    /// International mode enabled.
87    pub intl: bool,
88    /// Directory cache enabled.
89    pub dircache: bool,
90}
91
92impl FsFlags {
93    /// Create flags from DOS type byte.
94    #[inline]
95    pub const fn from_dos_type(dos_type: u8) -> Self {
96        Self {
97            intl: (dos_type & crate::DOSFS_INTL) != 0,
98            dircache: (dos_type & crate::DOSFS_DIRCACHE) != 0,
99        }
100    }
101}
102
103/// Access permissions.
104#[derive(Debug, Clone, Copy, Default)]
105pub struct Access(pub u32);
106
107impl Access {
108    /// Create from raw access value.
109    #[inline]
110    pub const fn new(raw: u32) -> Self {
111        Self(raw)
112    }
113
114    /// Check if delete is protected (inverted in AFFS).
115    #[inline]
116    pub const fn is_delete_protected(self) -> bool {
117        (self.0 & crate::ACC_DELETE) != 0
118    }
119
120    /// Check if execute is protected.
121    #[inline]
122    pub const fn is_execute_protected(self) -> bool {
123        (self.0 & crate::ACC_EXECUTE) != 0
124    }
125
126    /// Check if write is protected.
127    #[inline]
128    pub const fn is_write_protected(self) -> bool {
129        (self.0 & crate::ACC_WRITE) != 0
130    }
131
132    /// Check if read is protected.
133    #[inline]
134    pub const fn is_read_protected(self) -> bool {
135        (self.0 & crate::ACC_READ) != 0
136    }
137
138    /// Check if archived flag is set.
139    #[inline]
140    pub const fn is_archived(self) -> bool {
141        (self.0 & crate::ACC_ARCHIVE) != 0
142    }
143
144    /// Check if pure (re-entrant) flag is set.
145    #[inline]
146    pub const fn is_pure(self) -> bool {
147        (self.0 & crate::ACC_PURE) != 0
148    }
149
150    /// Check if script flag is set.
151    #[inline]
152    pub const fn is_script(self) -> bool {
153        (self.0 & crate::ACC_SCRIPT) != 0
154    }
155
156    /// Check if hold flag is set.
157    #[inline]
158    pub const fn is_hold(self) -> bool {
159        (self.0 & crate::ACC_HOLD) != 0
160    }
161}