1use core::fmt;
2pub use strat9_abi::data::DirentHeader;
3
4#[derive(Debug, Clone, Copy)]
5pub struct Dirent {
7 pub ino: u64,
8 pub type_: u8,
9 pub name_len: u16,
10 pub name: [u8; 256],
11}
12
13impl Dirent {
14 pub fn new(ino: u64, type_: u8, name: &[u8]) -> Self {
16 let mut d = Self {
17 ino,
18 type_,
19 name_len: 0,
20 name: [0; 256],
21 };
22 let len = core::cmp::min(name.len(), 255);
23 d.name[..len].copy_from_slice(&name[..len]);
24 d.name_len = len as u16;
25 d
26 }
27
28 pub fn name(&self) -> &[u8] {
30 &self.name[..self.name_len as usize]
31 }
32}
33
34impl fmt::Display for Dirent {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(
38 f,
39 "{}",
40 core::str::from_utf8(self.name()).unwrap_or("<invalid>")
41 )
42 }
43}
44
45pub struct DirentIter<'a> {
47 buf: &'a [u8],
48 offset: usize,
49}
50
51impl<'a> DirentIter<'a> {
52 pub fn new(buf: &'a [u8], valid_len: usize) -> Self {
54 let valid_len = core::cmp::min(valid_len, buf.len());
55 Self {
56 buf: &buf[..valid_len],
57 offset: 0,
58 }
59 }
60}
61
62impl<'a> Iterator for DirentIter<'a> {
63 type Item = Dirent;
64
65 fn next(&mut self) -> Option<Dirent> {
67 if self.offset + DirentHeader::SIZE > self.buf.len() {
68 return None;
69 }
70 let hdr = &self.buf[self.offset..self.offset + DirentHeader::SIZE];
71 let ino = u64::from_le_bytes(hdr[0..8].try_into().ok()?);
72 let file_type = hdr[8];
73 let name_len = u16::from_le_bytes(hdr[9..11].try_into().ok()?);
74 let _padding = hdr[11];
75 let name_start = self.offset + DirentHeader::SIZE;
76 let name_end = name_start + name_len as usize;
77 if name_end + 1 > self.buf.len() {
78 return None;
79 }
80 let mut d = Dirent::new(ino, file_type, &self.buf[name_start..name_end]);
81 d.name_len = core::cmp::min(name_len, 255);
82 self.offset = name_end + 1; Some(d)
84 }
85}