use super::*;
use crate::app::format::WriteError;
use crate::app::Timestamp;
#[derive(Debug, PartialEq, Eq)]
pub(crate) struct Group70Var7<'a> {
pub(crate) file_type: FileType,
pub(crate) file_size: u32,
pub(crate) time_of_creation: Timestamp,
pub(crate) permissions: Permissions,
pub(crate) request_id: u16,
pub(crate) file_name: &'a str,
}
impl<'a> Group70Var7<'a> {
const FILE_NAME_OFFSET: u16 = 20;
pub(crate) fn format(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "\nfile name: {}", self.file_name)?;
write!(f, "\nfile type: {:?}", self.file_type)?;
write!(f, "\nfile size: {}", self.file_size)?;
write!(
f,
"\ntime of creation: {}",
self.time_of_creation.raw_value()
)?;
write!(f, "\npermissions: {}", self.permissions)?;
write!(f, "\nrequest id: {}", self.request_id)?;
Ok(())
}
pub(crate) fn write(&self, cursor: &mut scursor::WriteCursor) -> Result<(), WriteError> {
cursor.write_u16_le(Self::FILE_NAME_OFFSET)?;
cursor.write_u16_le(byte_length(self.file_name)?)?;
cursor.write_u16_le(self.file_type.to_u16())?;
cursor.write_u32_le(self.file_size)?;
self.time_of_creation.write(cursor)?;
self.permissions.write(cursor)?;
cursor.write_u16_le(self.request_id)?;
cursor.write_bytes(self.file_name.as_bytes())?;
Ok(())
}
pub(crate) fn read(cursor: &mut scursor::ReadCursor<'a>) -> Result<Self, ReadError> {
let file_name_offset = cursor.read_u16_le()?;
if file_name_offset != Self::FILE_NAME_OFFSET {
return Err(ReadError::BadOffset {
expected: Self::FILE_NAME_OFFSET,
actual: file_name_offset,
});
}
let file_name_length = cursor.read_u16_le()?;
let file_type = FileType::new(cursor.read_u16_le()?);
let file_size = cursor.read_u32_le()?;
let time_of_creation = Timestamp::read(cursor)?;
let permissions = Permissions::read(cursor)?;
let request_id = cursor.read_u16_le()?;
let file_name_bytes = cursor.read_bytes(file_name_length as usize)?;
let file_name = std::str::from_utf8(file_name_bytes)?;
Ok(Self {
file_type,
file_size,
time_of_creation,
permissions,
request_id,
file_name,
})
}
}
#[cfg(test)]
mod test {
use super::*;
const OBJECT: Group70Var7 = Group70Var7 {
file_type: FileType::File,
file_size: 0xAABBCCDD,
time_of_creation: Timestamp::new(0xAABBCCDDEEFF),
permissions: Permissions {
world: PermissionSet::all(),
group: PermissionSet::all(),
owner: PermissionSet::all(),
},
request_id: 0xEEFF,
file_name: "foo.dat",
};
const DATA: &[u8] = &[
20, 0, 7, 0, 0x01, 0x00, 0xDD, 0xCC, 0xBB, 0xAA, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0b11111111, 0b00000001, 0xFF, 0xEE, b'f', b'o', b'o', b'.', b'd', b'a', b't',
];
#[test]
fn writes_valid_object() {
let mut buffer = [0; 64];
let mut cursor = scursor::WriteCursor::new(&mut buffer);
OBJECT.write(&mut cursor).unwrap();
assert_eq!(cursor.written(), DATA)
}
#[test]
fn parses_valid_object() {
let mut cursor = scursor::ReadCursor::new(DATA);
let obj = Group70Var7::read(&mut cursor).unwrap();
assert_eq!(obj, OBJECT);
assert!(cursor.is_empty());
}
}