1#![no_implicit_prelude]
21
22extern crate core;
23
24use core::clone::Clone;
25use core::cmp::{self, PartialEq};
26use core::convert::AsRef;
27use core::default::Default;
28use core::iter::Iterator;
29use core::ops::Deref;
30use core::option::Option::{None, Some};
31use core::result::Result::{self, Err, Ok};
32use core::str::from_utf8_unchecked;
33use core::unreachable;
34
35use crate::fs::{DeviceError, FatVersion};
36
37pub struct LongName(pub(super) [u8; LongName::SIZE]);
38pub struct ShortName(pub(super) [u8; ShortName::SIZE]);
39pub struct VolumeName(pub(super) [u8; VolumeName::SIZE]);
40
41impl LongName {
42 pub const SIZE: usize = 0xFFusize;
43
44 #[inline(always)]
45 pub const fn empty() -> LongName {
46 LongName([0u8; LongName::SIZE])
47 }
48
49 #[inline]
50 pub fn from_slice_truncate(v: &[u8]) -> LongName {
51 let mut n = LongName([0x20u8; LongName::SIZE]);
52 n.fill_inner(v);
53 n
54 }
55 #[inline]
56 pub fn from_str_truncate(v: impl AsRef<str>) -> LongName {
57 LongName::from_slice_truncate(v.as_ref().as_bytes())
58 }
59 #[inline]
60 pub fn from_slice(v: &[u8]) -> Result<LongName, DeviceError> {
61 if v.len() > LongName::SIZE {
62 Err(DeviceError::NameTooLong)
63 } else {
64 Ok(LongName::from_slice_truncate(v))
65 }
66 }
67 #[inline]
68 pub fn from_str(v: impl AsRef<str>) -> Result<LongName, DeviceError> {
69 if v.as_ref().len() > LongName::SIZE {
70 Err(DeviceError::NameTooLong)
71 } else {
72 Ok(LongName::from_str_truncate(v))
73 }
74 }
75
76 #[inline(always)]
77 pub fn len(&self) -> usize {
78 self.0.iter().position(|v| *v == 0).unwrap_or(LongName::SIZE)
79 }
80 #[inline(always)]
81 pub fn as_str(&self) -> &str {
82 unsafe { from_utf8_unchecked(&self.0[0..self.0.iter().position(|v| *v == 0).unwrap_or(LongName::SIZE)]) }
83 }
84 pub fn lfn_size(&self) -> u8 {
85 let mut r = self.len();
86 if r <= 13 {
87 return 1;
88 }
89 r += 1; let c = r / 0xC;
91 if (c * 0xC) == r {
92 return c as u8;
93 }
94 if r > 0xC {
95 r += 1; }
97 (r / 0xC) as u8 + 1
98 }
99 #[inline(always)]
100 pub fn is_self(&self) -> bool {
101 self.0[0] == b'.' && self.0[1] == 0
102 }
103 #[inline(always)]
104 pub fn is_empty(&self) -> bool {
105 self.0[0] == 0
106 }
107 #[inline(always)]
108 pub fn as_bytes(&self) -> &[u8] {
109 &self.0[0..self.0.iter().position(|v| *v == 0).unwrap_or(LongName::SIZE)]
110 }
111 #[inline(always)]
112 pub fn is_parent(&self) -> bool {
113 self.0[0] == b'.' && self.0[1] == b'.' && self.0[2] == 0
114 }
115 #[inline]
116 pub fn fill(&mut self, v: &[u8]) -> Result<(), DeviceError> {
117 if v.len() > LongName::SIZE {
118 return Err(DeviceError::NameTooLong);
119 }
120 self.fill_inner(v);
121 Ok(())
122 }
123 #[inline]
124 pub fn fill_str(&mut self, v: impl AsRef<str>) -> Result<(), DeviceError> {
125 self.fill(v.as_ref().as_bytes())
126 }
127
128 #[inline(always)]
129 pub(super) fn reset(&mut self) {
130 self.0.fill(0)
131 }
132 pub(super) fn fill_lfn(&mut self, b: &[u8]) -> u8 {
133 if b.len() < 0x20 {
134 return 0u8;
135 }
136 let v = ((b[0] & 0x1F) as usize - 1) * 0xD;
137 for i in 0..0xD {
138 if i + v >= LongName::SIZE {
139 break;
140 }
141 let c = b[LongName::pos_to_lfn(i)];
142 if c == 0 {
143 break;
144 }
145 self.0[v + i] = c;
146 }
147 b[0xD]
148 }
149
150 #[inline(always)]
151 pub(super) fn pos_to_lfn(v: usize) -> usize {
152 match v {
153 0 => 1,
154 1 => 3,
155 2 => 5,
156 3 => 7,
157 4 => 9,
158 5 => 14,
159 6 => 16,
160 7 => 18,
161 8 => 20,
162 9 => 22,
163 10 => 24,
164 11 => 28,
165 12 => 30,
166 _ => unreachable!(),
167 }
168 }
169
170 #[inline]
171 fn fill_inner(&mut self, v: &[u8]) {
172 if v.len() < LongName::SIZE {
173 self.0[0..v.len()].copy_from_slice(v)
174 } else {
175 self.0.copy_from_slice(&v[0..LongName::SIZE]);
176 }
177 }
178}
179impl ShortName {
180 pub const SIZE: usize = 0xBusize;
181 pub const SIZE_EXT: usize = 0x3usize;
182 pub const SIZE_NAME: usize = 0x8usize;
183
184 pub const SELF: ShortName = ShortName([0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20]);
185 pub const PARENT: ShortName = ShortName([0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20]);
186
187 #[inline]
188 pub fn empty() -> ShortName {
189 ShortName([0x20u8; ShortName::SIZE])
190 }
191 #[inline]
192 pub fn from_slice(v: &[u8]) -> ShortName {
193 let mut n = ShortName([0x20u8; ShortName::SIZE]);
194 n.fill(v);
195 n
196 }
197 #[inline]
198 pub fn from_str(v: impl AsRef<str>) -> ShortName {
199 ShortName::from_slice(v.as_ref().as_bytes())
200 }
201
202 #[inline]
203 pub fn name(&self) -> &str {
204 unsafe {
205 from_utf8_unchecked(
206 &self.0[0..self.0[0..ShortName::SIZE_NAME]
207 .iter()
208 .position(|v| *v == 0x20)
209 .unwrap_or(ShortName::SIZE_NAME)],
210 )
211 }
212 }
213 #[inline]
214 pub fn as_str(&self) -> &str {
215 let i = self.extension_len();
216 if i == 0 {
217 self.name()
218 } else {
219 unsafe { from_utf8_unchecked(&self.0[0..ShortName::SIZE_NAME + i]) }
220 }
221 }
222 #[inline]
223 pub fn checksum(&self) -> u8 {
224 let mut s = 0u8;
225 for i in self.0.iter() {
226 s = ((s & 1) << 7).wrapping_add((s >> 1) + *i);
227 }
228 s
229 }
230 #[inline(always)]
231 pub fn is_self(&self) -> bool {
232 self.0.eq(&ShortName::SELF.0)
233 }
234 #[inline(always)]
235 pub fn is_parent(&self) -> bool {
236 self.0.eq(&ShortName::PARENT.0)
237 }
238 #[inline(always)]
239 pub fn as_bytes(&self) -> &[u8] {
240 &self.0
241 }
242 #[inline(always)]
243 pub fn extension(&self) -> &str {
244 unsafe { from_utf8_unchecked(&self.0[ShortName::SIZE_NAME..ShortName::SIZE_NAME + self.extension_len()]) }
245 }
246 #[inline(always)]
247 pub fn fill(&mut self, v: &[u8]) {
248 ShortName::to_sfn(v, self);
249 }
250 #[inline]
251 pub fn fill_str(&mut self, v: impl AsRef<str>) {
252 self.fill(v.as_ref().as_bytes());
253 }
254
255 #[inline(always)]
256 pub(super) fn fill_inner(&mut self, v: &[u8]) {
257 self.0.copy_from_slice(&v[0..ShortName::SIZE])
258 }
259
260 #[inline(always)]
261 fn transform_char(v: u8) -> u8 {
262 match v {
263 0x00..=0x1F | 0x20 | 0x22 | 0x2A | 0x2B | 0x2C | 0x2F | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F | 0x5B | 0x5C | 0x5D | 0x7C => b'+',
264 v if v >= b'a' && v <= b'z' => v - 0x20,
265 v => v,
266 }
267 }
268 fn to_sfn(b: &[u8], sfn: &mut ShortName) {
269 match b.len() {
271 0 => return,
272 1 if b[0] == b'.' => {
273 sfn.0.copy_from_slice(&ShortName::SELF.0);
274 return;
275 },
276 2 if b[0] == b'.' && b[1] == b'.' => {
277 sfn.0.copy_from_slice(&ShortName::PARENT.0);
278 return;
279 },
280 _ => (),
281 }
282 let n = match b.iter().rposition(|v| *v == b'.') {
285 Some(i) => {
286 match b.len().saturating_sub(i + 1) {
288 0 => (),
289 1 => sfn.0[ShortName::SIZE_NAME] = b[i + 1],
290 2 => {
291 sfn.0[ShortName::SIZE_NAME] = b[i + 1];
292 sfn.0[ShortName::SIZE_NAME + 1] = b[i + 2];
293 },
294 _ => sfn.0[ShortName::SIZE_NAME..ShortName::SIZE].copy_from_slice(&b[i + 1..i + 4]),
295 }
296 i
297 },
298 None => b.len(),
299 };
300 if n < ShortName::SIZE_NAME {
301 sfn.0[0..n].copy_from_slice(&b[0..n]);
302 sfn.0[n..ShortName::SIZE_NAME].fill(0x20)
303 } else if n == ShortName::SIZE_NAME {
304 sfn.0[0..ShortName::SIZE_NAME].copy_from_slice(&b[0..ShortName::SIZE_NAME])
305 } else {
306 sfn.0[0..ShortName::SIZE_NAME - 2].copy_from_slice(&b[0..ShortName::SIZE_NAME - 2]);
307 sfn.0[ShortName::SIZE_NAME - 2] = b'~';
312 sfn.0[ShortName::SIZE_NAME - 1] = b'1';
313 }
314 for i in 0..cmp::min(n, ShortName::SIZE_NAME) {
318 if sfn.0[i] == 0x20 {
319 sfn.0[i] = b'_'
320 }
321 }
322 for i in sfn.0[0..ShortName::SIZE_NAME].iter_mut() {
324 *i = ShortName::transform_char(*i)
325 }
326 }
327
328 #[inline(always)]
329 fn extension_len(&self) -> usize {
330 match (
331 self.0[ShortName::SIZE_NAME],
332 self.0[ShortName::SIZE_NAME + 1],
333 self.0[ShortName::SIZE_NAME + 2],
334 ) {
335 (0x20, 0x20, 0x20) => 0,
336 (_, 0x20, 0x20) => 1,
337 (_, _, 0x20) => 2,
338 (..) => 3,
339 }
340 }
341}
342impl VolumeName {
343 pub const SIZE: usize = 0xBusize;
344
345 #[inline]
346 pub fn empty() -> VolumeName {
347 VolumeName([0x20u8; VolumeName::SIZE])
348 }
349
350 #[inline]
351 pub(super) fn from_slice(f: &FatVersion, v: &[u8]) -> VolumeName {
352 let i = match f {
353 FatVersion::Fat16(_) => 0x2B,
354 FatVersion::Fat32(_) => 0x47,
355 };
356 let mut n = VolumeName([0x20u8; VolumeName::SIZE]);
357 if (v.len().saturating_sub(i)) < VolumeName::SIZE {
358 n.0[0..(v.len().saturating_sub(i))].copy_from_slice(v)
359 } else {
360 n.0.copy_from_slice(&v[i..VolumeName::SIZE + i]);
361 }
362 n
363 }
364
365 #[inline(always)]
366 pub fn as_str(&self) -> &str {
367 unsafe { from_utf8_unchecked(&self.0[0..self.0.iter().position(|v| *v == 0x20).unwrap_or(VolumeName::SIZE)]) }
368 }
369 #[inline(always)]
370 pub fn as_bytes(&self) -> &[u8] {
371 &self.0
372 }
373}
374
375impl PartialEq for ShortName {
376 #[inline(always)]
377 fn eq(&self, other: &ShortName) -> bool {
378 self.0.eq(&other.0)
379 }
380}
381impl PartialEq<str> for ShortName {
382 #[inline(always)]
383 fn eq(&self, other: &str) -> bool {
384 self.eq(other.as_bytes())
385 }
386}
387impl PartialEq<[u8]> for ShortName {
388 #[inline]
389 fn eq(&self, other: &[u8]) -> bool {
390 let mut v = ShortName::empty();
391 v.fill(other);
392 v.0.eq(&self.0)
393 }
394}
395
396impl PartialEq for LongName {
397 #[inline(always)]
398 fn eq(&self, other: &LongName) -> bool {
399 self.0.eq(&other.0)
400 }
401}
402impl PartialEq<str> for LongName {
403 #[inline(always)]
404 fn eq(&self, other: &str) -> bool {
405 self.eq(other.as_bytes())
406 }
407}
408impl PartialEq<[u8]> for LongName {
409 #[inline(always)]
410 fn eq(&self, other: &[u8]) -> bool {
411 self.as_bytes().eq(other)
412 }
413}
414
415impl Deref for LongName {
416 type Target = [u8];
417
418 #[inline(always)]
419 fn deref(&self) -> &[u8] {
420 self.as_bytes()
421 }
422}
423impl AsRef<str> for LongName {
424 #[inline(always)]
425 fn as_ref(&self) -> &str {
426 self.as_str()
427 }
428}
429
430impl Clone for ShortName {
431 #[inline(always)]
432 fn clone(&self) -> ShortName {
433 ShortName(self.0.clone())
434 }
435}
436impl Deref for ShortName {
437 type Target = [u8];
438
439 #[inline(always)]
440 fn deref(&self) -> &[u8] {
441 &self.0
442 }
443}
444impl AsRef<str> for ShortName {
445 #[inline(always)]
446 fn as_ref(&self) -> &str {
447 self.as_str()
448 }
449}
450
451impl Clone for VolumeName {
452 #[inline(always)]
453 fn clone(&self) -> VolumeName {
454 VolumeName(self.0.clone())
455 }
456}
457impl Deref for VolumeName {
458 type Target = [u8];
459
460 #[inline(always)]
461 fn deref(&self) -> &[u8] {
462 self.as_bytes()
463 }
464}
465impl Default for VolumeName {
466 #[inline(always)]
467 fn default() -> VolumeName {
468 VolumeName::empty()
469 }
470}
471impl AsRef<str> for VolumeName {
472 #[inline(always)]
473 fn as_ref(&self) -> &str {
474 self.as_str()
475 }
476}
477
478#[cfg(feature = "debug")]
479mod display {
480 extern crate core;
481
482 use core::fmt::{Debug, Display, Formatter, Result, Write};
483 use core::iter::Iterator;
484 use core::result::Result::Ok;
485
486 use crate::fs::{LongName, ShortName, VolumeName};
487
488 impl Debug for LongName {
489 #[inline(always)]
490 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
491 f.write_str(self.as_str())
492 }
493 }
494 impl Display for LongName {
495 #[inline(always)]
496 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
497 f.write_str(self.as_str())
498 }
499 }
500
501 impl Debug for ShortName {
502 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
503 for (i, v) in self.0.iter().enumerate() {
504 if i == 8 {
505 f.write_char('.')?;
506 }
507 if *v == 0x20 {
508 f.write_char('.')?;
509 } else {
510 f.write_char(*v as _)?;
511 }
512 }
513 Ok(())
514 }
515 }
516 impl Display for ShortName {
517 #[inline]
518 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
519 f.write_str(self.name())?;
520 f.write_char('.')?;
521 f.write_str(self.extension())
522 }
523 }
524
525 impl Debug for VolumeName {
526 #[inline(always)]
527 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
528 f.write_str(self.as_str())
529 }
530 }
531 impl Display for VolumeName {
532 #[inline(always)]
533 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
534 f.write_str(self.as_str())
535 }
536 }
537}