use { crate::{Error, File, Special}, std::io::{Read, Write}, }; /// An enum representing the type of file of an archive member #[derive(Debug)] pub enum FileType { /// A normal file and it's contained data Normal(File), /// A hard link to another file in this archive HardLink(String), /// A soft link to another file SoftLink(String), /// A directory inode Directory, /// A character (buffered) device Character(Special), /// A block device Block(Special), /// A Unix named pipe (fifo) Fifo, /// End of archive Eof, } impl FileType { pub fn read(reader: &mut T) -> Result { 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(&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 => {} } Ok(()) } }