haggis-rs/src/filetype.rs

103 lines
3.1 KiB
Rust
Raw Normal View History

2023-07-04 00:51:47 -04:00
use {
crate::{Error, File, Special},
std::io::{Read, Write},
};
/// An enum representing the type of file of an archive member
2023-07-04 00:51:47 -04:00
#[derive(Debug)]
pub enum FileType {
/// A normal file and it's contained data
2023-07-04 00:51:47 -04:00
Normal(File),
/// A hard link to another file in this archive
2023-07-04 00:51:47 -04:00
HardLink(String),
/// A soft link to another file
2023-07-04 00:51:47 -04:00
SoftLink(String),
/// A directory inode
2023-07-04 00:51:47 -04:00
Directory,
/// A character (buffered) device
2023-07-04 00:51:47 -04:00
Character(Special),
/// A block device
2023-07-04 00:51:47 -04:00
Block(Special),
/// A Unix named pipe (fifo)
2023-07-04 00:51:47 -04:00
Fifo,
/// End of archive
Eof,
2023-07-04 00:51:47 -04:00
}
impl FileType {
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
let mut buf = [0; 1];
reader.read_exact(&mut buf)?;
match buf[0] {
0 => {
let file = File::read(reader)?;
Ok(Self::Normal(file))
}
1 => {
let mut len = [0; 8];
reader.read_exact(&mut len)?;
let len = u64::from_le_bytes(len);
let mut buf = Vec::with_capacity(len.try_into()?);
let mut handle = reader.take(len);
handle.read_exact(&mut buf)?;
let s = String::from_utf8(buf)?;
Ok(Self::HardLink(s))
}
2 => {
let mut len = [0; 8];
reader.read_exact(&mut len)?;
let len = u64::from_le_bytes(len);
let mut buf = Vec::with_capacity(len.try_into()?);
let mut handle = reader.take(len);
handle.read_exact(&mut buf)?;
let s = String::from_utf8(buf)?;
Ok(Self::SoftLink(s))
}
3 => Ok(Self::Directory),
4 => {
let sp = Special::read(reader)?;
Ok(Self::Character(sp))
}
5 => {
let sp = Special::read(reader)?;
Ok(Self::Block(sp))
}
6 => Ok(Self::Fifo),
_ => Err(Error::UnknownFileType),
}
}
pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
match self {
Self::Normal(f) => {
writer.write_all(&[0])?;
f.write(writer)?;
}
Self::HardLink(s) => {
writer.write_all(&[1])?;
let len = s.len() as u64;
writer.write_all(&len.to_le_bytes())?;
writer.write_all(s.as_bytes())?;
}
Self::SoftLink(s) => {
writer.write_all(&[2])?;
let len = s.len() as u64;
writer.write_all(&len.to_le_bytes())?;
writer.write_all(s.as_bytes())?;
}
Self::Directory => writer.write_all(&[3])?,
Self::Character(s) => {
writer.write_all(&[4])?;
s.write(writer)?;
}
Self::Block(s) => {
writer.write_all(&[5])?;
s.write(writer)?;
}
Self::Fifo => writer.write_all(&[6])?,
Self::Eof => {}
2023-07-04 00:51:47 -04:00
}
Ok(())
}
}