embedded_fat/fat/
lfn.rs
1use core::str;
2
3use crate::ShortFileName;
4
5const LFN_BUFFER_SIZE: usize = 255 * 4;
6
7#[allow(missing_docs)]
8#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
9pub struct LfnEntry {
10 pub is_start: bool,
11 pub sequence: u8,
12 pub checksum: u8,
13 pub buffer: [char; 13],
14}
15
16pub(crate) struct LfnVisitor {
17 buffer: [u8; LFN_BUFFER_SIZE],
18 state: Option<LfnVisitorState>,
19}
20
21struct LfnVisitorState {
22 buffer_used: usize,
23 last_sequence: u8,
24 checksum: u8,
25}
26
27impl Default for LfnVisitor {
28 fn default() -> Self {
29 Self {
30 buffer: [0; LFN_BUFFER_SIZE],
31 state: Default::default(),
32 }
33 }
34}
35
36impl LfnVisitor {
37 pub(crate) fn visit(&mut self, entry: &LfnEntry) {
38 if entry.is_start {
39 if entry.sequence > 20 {
40 self.state = None;
41 } else {
42 let mut state = LfnVisitorState {
43 buffer_used: 0,
44 last_sequence: entry.sequence,
45 checksum: entry.checksum,
46 };
47 state.extend_buffer(&mut self.buffer, &entry.buffer);
48 self.state = Some(state);
49 }
50 } else if let Some(state) = self.state.as_mut() {
51 if state.checksum != entry.checksum || state.last_sequence != entry.sequence + 1 {
52 self.state = None;
53 } else {
54 state.last_sequence -= 1;
55 state.extend_buffer(&mut self.buffer, &entry.buffer);
56 }
57 } else {
58 self.state = None;
59 }
60 }
61
62 pub(crate) fn take(&mut self, short_name: &ShortFileName) -> Option<&str> {
63 self.state.take().as_ref().and_then(|state| {
64 if state.last_sequence != 1 || state.checksum != short_name.lfn_checksum() {
65 None
66 } else {
67 let active_buffer = &mut self.buffer[..state.buffer_used];
68 active_buffer.reverse();
69 str::from_utf8(active_buffer)
70 .ok()
71 .map(|s| s.split('\0').next().unwrap())
72 }
73 })
74 }
75}
76
77impl LfnVisitorState {
78 fn extend_buffer(&mut self, buffer: &mut [u8], extension: &[char]) {
79 let remaining_buffer = &mut buffer[self.buffer_used..];
80 let mut used = 0;
81 for c in extension {
82 let s = c.encode_utf8(&mut remaining_buffer[used..]);
83 used += s.len();
84 }
85 remaining_buffer[..used].reverse();
86 self.buffer_used += used;
87 }
88}