105 lines
3.1 KiB
Rust
105 lines
3.1 KiB
Rust
use crate::{
|
|
Fat32FileSystem, ReadSeek, ReadWriteSeek,
|
|
entry::{DirEntry, DirectoryIterator},
|
|
error::Error,
|
|
file::{File, RawFile},
|
|
path::Path,
|
|
};
|
|
use io::{self, IoBase, Read, Seek, Write};
|
|
|
|
pub struct Dir<'a, T> {
|
|
raw: RawFile<'a, T>,
|
|
fs: &'a Fat32FileSystem<T>,
|
|
}
|
|
|
|
impl<'a, T: IoBase> IoBase for Dir<'a, T> {
|
|
type Error = Error<T::Error>;
|
|
}
|
|
impl<'a, T: ReadSeek> Seek for Dir<'a, T> {
|
|
fn seek(&mut self, pos: io::SeekFrom) -> Result<u64, Self::Error> {
|
|
self.raw.seek(pos)
|
|
}
|
|
}
|
|
impl<'a, T: ReadSeek> Read for Dir<'a, T> {
|
|
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
|
|
self.raw.read(buf)
|
|
}
|
|
}
|
|
impl<'a, T: ReadWriteSeek> Write for Dir<'a, T> {
|
|
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
|
|
self.raw.write(buf)
|
|
}
|
|
|
|
fn flush(&mut self) -> Result<(), Self::Error> {
|
|
self.raw.flush()
|
|
}
|
|
}
|
|
|
|
impl<'a, T> Dir<'a, T> {
|
|
pub fn new(raw: RawFile<'a, T>, fs: &'a Fat32FileSystem<T>) -> Self {
|
|
Self { raw, fs }
|
|
}
|
|
pub fn iter(&self) -> DirectoryIterator<'a, T> {
|
|
DirectoryIterator::new(RawFile::new(self.fs, self.raw.first_cluster(), None))
|
|
}
|
|
}
|
|
impl<'a, T: ReadSeek> Dir<'a, T> {
|
|
pub fn open_entry<P: AsRef<Path>>(&self, path: P) -> Result<DirEntry<'a, T>, Error<T::Error>> {
|
|
if path.as_ref().is_absolute() {
|
|
return self.fs.open_entry(path);
|
|
}
|
|
let (start, entryname) = path.as_ref().split_path();
|
|
for file in self.iter() {
|
|
let f = file?;
|
|
if f.name_is(start) {
|
|
if let Some(entry_name) = entryname {
|
|
if f.is_dir() {
|
|
return f.to_dir().open_entry(entry_name);
|
|
} else {
|
|
return Err(Error::NotFound);
|
|
}
|
|
} else {
|
|
return Ok(f);
|
|
}
|
|
}
|
|
}
|
|
Err(Error::NotFound)
|
|
}
|
|
pub fn open_file<P: AsRef<Path>>(&self, path: P) -> Result<File<'a, T>, Error<T::Error>> {
|
|
if path.as_ref().is_absolute() {
|
|
return self.fs.open_file(path);
|
|
}
|
|
let (start, dirname) = path.as_ref().split_path();
|
|
let entry = self.open_entry(start)?;
|
|
match dirname {
|
|
Some(name) => {
|
|
if !entry.is_dir() {
|
|
return Err(Error::NotFound);
|
|
}
|
|
entry.to_dir().open_file(name)
|
|
}
|
|
None => {
|
|
if !entry.is_file() {
|
|
return Err(Error::NotFound);
|
|
}
|
|
Ok(entry.to_file())
|
|
}
|
|
}
|
|
}
|
|
pub fn open_dir<P: AsRef<Path>>(&self, path: P) -> Result<Self, Error<T::Error>> {
|
|
let path = path.as_ref();
|
|
if path.is_absolute() {
|
|
return self.fs.open_dir(path);
|
|
}
|
|
let (start, dirname) = path.split_path();
|
|
let entry = self.open_entry(start)?;
|
|
if !entry.is_dir() {
|
|
return Err(Error::NotFound);
|
|
}
|
|
match dirname {
|
|
Some(name) => entry.to_dir().open_dir(name),
|
|
None => Ok(entry.to_dir()),
|
|
}
|
|
}
|
|
}
|