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