hadris_fat/format/
options.rs1use super::super::fat_table::FatType;
6
7#[derive(Debug, Clone)]
9pub struct FatFormatOptions {
10 pub volume_size: u64,
12 pub volume_label: VolumeLabel,
14 pub oem_name: OemName,
16 pub sector_size: SectorSize,
18 pub sectors_per_cluster: Option<u8>,
20 pub fat_type: FatTypeSelection,
22 pub fat_copies: u8,
24 pub root_entry_count: u16,
26 pub hidden_sectors: u32,
28 pub media_type: MediaType,
30 pub volume_id: Option<u32>,
32}
33
34impl Default for FatFormatOptions {
35 fn default() -> Self {
36 Self {
37 volume_size: 0,
38 volume_label: VolumeLabel::default(),
39 oem_name: OemName::default(),
40 sector_size: SectorSize::default(),
41 sectors_per_cluster: None,
42 fat_type: FatTypeSelection::Auto,
43 fat_copies: 2,
44 root_entry_count: 512,
45 hidden_sectors: 0,
46 media_type: MediaType::FixedDisk,
47 volume_id: None,
48 }
49 }
50}
51
52impl FatFormatOptions {
53 pub fn new(volume_size: u64) -> Self {
55 Self {
56 volume_size,
57 ..Default::default()
58 }
59 }
60
61 pub fn volume_label(mut self, label: &str) -> Self {
63 self.volume_label = VolumeLabel::new(label);
64 self
65 }
66
67 pub fn sector_size(mut self, size: SectorSize) -> Self {
69 self.sector_size = size;
70 self
71 }
72
73 pub fn fat_type(mut self, fat_type: FatTypeSelection) -> Self {
75 self.fat_type = fat_type;
76 self
77 }
78
79 pub fn sectors_per_cluster(mut self, spc: u8) -> Self {
81 self.sectors_per_cluster = Some(spc);
82 self
83 }
84
85 pub fn fat_copies(mut self, copies: u8) -> Self {
87 self.fat_copies = copies.clamp(1, 2);
88 self
89 }
90
91 pub fn media_type(mut self, media_type: MediaType) -> Self {
93 self.media_type = media_type;
94 self
95 }
96
97 pub fn hidden_sectors(mut self, hidden: u32) -> Self {
99 self.hidden_sectors = hidden;
100 self
101 }
102
103 pub fn volume_id(mut self, id: u32) -> Self {
105 self.volume_id = Some(id);
106 self
107 }
108
109}
110
111#[derive(Debug, Clone)]
113pub struct VolumeLabel([u8; 11]);
114
115impl VolumeLabel {
116 pub fn new(s: &str) -> Self {
121 let mut bytes = [b' '; 11];
122 for (i, c) in s.chars().take(11).enumerate() {
123 let c = c.to_ascii_uppercase();
124 if c.is_ascii() && Self::is_valid_char(c as u8) {
125 bytes[i] = c as u8;
126 } else {
127 bytes[i] = b'_';
128 }
129 }
130 Self(bytes)
131 }
132
133 pub fn no_name() -> Self {
135 Self(*b"NO NAME ")
136 }
137
138 fn is_valid_char(c: u8) -> bool {
140 matches!(c, b'A'..=b'Z' | b'0'..=b'9' | b' ' | b'!' | b'#' | b'$' | b'%' | b'&' | b'\'' | b'(' | b')' | b'-' | b'@' | b'^' | b'_' | b'`' | b'{' | b'}' | b'~')
141 }
142
143 pub fn as_bytes(&self) -> &[u8; 11] {
145 &self.0
146 }
147}
148
149impl Default for VolumeLabel {
150 fn default() -> Self {
151 Self::no_name()
152 }
153}
154
155#[derive(Debug, Clone)]
157pub struct OemName([u8; 8]);
158
159impl OemName {
160 pub fn new(s: &str) -> Self {
162 let mut bytes = [b' '; 8];
163 for (i, c) in s.chars().take(8).enumerate() {
164 if c.is_ascii() {
165 bytes[i] = c as u8;
166 }
167 }
168 Self(bytes)
169 }
170
171 pub fn as_bytes(&self) -> &[u8; 8] {
173 &self.0
174 }
175}
176
177impl Default for OemName {
178 fn default() -> Self {
179 Self(*b"HADRISFT")
180 }
181}
182
183#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
185pub enum SectorSize {
186 #[default]
188 S512 = 512,
189 S1024 = 1024,
191 S2048 = 2048,
193 S4096 = 4096,
195}
196
197impl SectorSize {
198 pub fn bytes(self) -> usize {
200 self as usize
201 }
202}
203
204impl TryFrom<usize> for SectorSize {
205 type Error = ();
206
207 fn try_from(value: usize) -> Result<Self, Self::Error> {
208 match value {
209 512 => Ok(Self::S512),
210 1024 => Ok(Self::S1024),
211 2048 => Ok(Self::S2048),
212 4096 => Ok(Self::S4096),
213 _ => Err(()),
214 }
215 }
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
220pub enum FatTypeSelection {
221 #[default]
223 Auto,
224 Fat12,
226 Fat16,
228 Fat32,
230}
231
232impl FatTypeSelection {
233 pub fn as_fat_type(self) -> Option<FatType> {
235 match self {
236 Self::Auto => None,
237 Self::Fat12 => Some(FatType::Fat12),
238 Self::Fat16 => Some(FatType::Fat16),
239 Self::Fat32 => Some(FatType::Fat32),
240 }
241 }
242}
243
244impl From<FatType> for FatTypeSelection {
245 fn from(fat_type: FatType) -> Self {
246 match fat_type {
247 FatType::Fat12 => Self::Fat12,
248 FatType::Fat16 => Self::Fat16,
249 FatType::Fat32 => Self::Fat32,
250 }
251 }
252}
253
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
256pub enum MediaType {
257 #[default]
259 FixedDisk,
260 Removable,
262 Custom(u8),
264}
265
266impl MediaType {
267 pub fn value(self) -> u8 {
269 match self {
270 Self::FixedDisk => 0xF8,
271 Self::Removable => 0xF0,
272 Self::Custom(v) => v,
273 }
274 }
275}