Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
7921064ae2 moved short name str into separate buffer 2025-07-29 20:34:35 +02:00

View file

@ -64,24 +64,30 @@ pub struct DirEntry {
file_size: u32,
// buffer for holding short name str representation
// initial dot if hidden (1)
// stem (8)
// dot (1)
// extension (3)
short_name: [u8; 13],
long_name: Option<String>,
}
impl Display for DirEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut name = self.name_string().unwrap_or_else(|| "<unknown>".to_owned());
let name = self.name_str().unwrap_or("<unknown>");
if self.attr.contains(Attr::Directory) {
name.push('/');
}
// add slash to end of dir_names
let dir_slash = if self.is_dir() { "/" } else { " " };
write!(
f,
"{} {}",
"{} {}{}",
self.attr,
// self.create_time().format("%a %b %d %H:%M:%S%.3f %Y"),
// self.write_time().format("%a %b %d %H:%M:%S%.3f %Y"),
name,
dir_slash,
)?;
Ok(())
@ -92,7 +98,7 @@ impl DirEntry {
pub fn load(bytes: &[u8]) -> anyhow::Result<DirEntry> {
assert_eq!(bytes.len(), 32);
let name = bytes[..11].try_into().unwrap();
let name: [u8; 11] = bytes[..11].try_into().unwrap();
let attr = Attr::from_bits_truncate(bytes[11]);
let create_time_tenths = bytes[13];
@ -130,6 +136,32 @@ impl DirEntry {
)
}
let mut short_name = [0; 13];
let mut short_name_iter = short_name.iter_mut();
if attr.contains(Attr::Hidden) {
// if hidden: lead with '.'
*short_name_iter.next().unwrap() = b'.';
}
if name[0] != 0 && name[0] != 0xe5 {
// dir_entry is not free
for c in name[..8].iter().filter(|&x| x != &0x20) {
*short_name_iter.next().unwrap() = *c;
}
if &name[8..] != &[0x20, 0x20, 0x20] {
// if extension is not empty: add dot and extension
*short_name_iter.next().unwrap() = b'.';
for c in name[8..].iter().filter(|&x| x != &0x20) {
*short_name_iter.next().unwrap() = *c;
}
}
}
Ok(DirEntry {
name,
attr,
@ -141,6 +173,7 @@ impl DirEntry {
write_time,
write_date,
file_size,
short_name,
long_name: None,
})
}
@ -216,29 +249,19 @@ impl DirEntry {
std::str::from_utf8(self.extension()).ok()
}
pub fn name_string(&self) -> Option<String> {
if let Some(long_filename) = self.long_name() {
return Some(long_filename.to_owned());
fn short_name(&self) -> &[u8] {
&self.short_name
}
let name = std::str::from_utf8(&self.name[..8]).ok()?.trim_ascii_end();
let ext = std::str::from_utf8(&self.name[8..]).ok()?.trim_ascii_end();
fn short_name_str(&self) -> Option<&str> {
let mut short_name = self.short_name();
let mut s = String::new();
if self.attr.contains(Attr::Hidden) {
s.push('.');
// remove trailing zeros
while short_name.last() == Some(&0) {
short_name = &short_name[..short_name.len() - 1];
}
s += name;
if !ext.is_empty() {
s.push('.');
s += ext;
}
Some(s)
std::str::from_utf8(short_name).ok()
}
pub fn long_name(&self) -> Option<&str> {
@ -249,6 +272,33 @@ impl DirEntry {
self.long_name = Some(long_name);
}
pub fn name_str(&self) -> Option<&str> {
if let Some(long_filename) = self.long_name() {
return Some(long_filename);
}
self.short_name_str()
// let name = std::str::from_utf8(&self.name[..8]).ok()?.trim_ascii_end();
// let ext = std::str::from_utf8(&self.name[8..]).ok()?.trim_ascii_end();
// let mut s = String::new();
// if self.attr.contains(Attr::Hidden) {
// s.push('.');
// }
// s += name;
// if !ext.is_empty() {
// s.push('.');
// s += ext;
// }
// Some(s)
}
pub fn attr(&self) -> Attr {
self.attr
}
@ -540,7 +590,7 @@ impl<R: Read> DirIter<R> {
.map_err(|e| {
anyhow::anyhow!(
"failed to get long filename for {}: {}",
dir_entry.name_string().as_deref().unwrap_or("<invalid>"),
dir_entry.name_str().as_deref().unwrap_or("<invalid>"),
e
)
})? {