use std::io::{Cursor, Write}; use androscalpel_serializer::{ReadSeek, Result, Serializable}; #[derive(Debug, Clone, PartialEq, Eq)] pub enum ExtraField { Zip64(Zip64ExtraField), Generic(GenericExtraField), } impl ExtraField { fn to_generic(&self) -> Result { match self { Self::Zip64(field) => field.to_generic_field(), Self::Generic(field) => Ok(field.clone()), } } } impl Serializable for ExtraField { fn serialize(&self, output: &mut dyn Write) -> Result<()> { self.to_generic()?.serialize(output) } fn deserialize(input: &mut dyn ReadSeek) -> Result { Ok(Self::Generic(GenericExtraField::deserialize(input)?)) /* match field.id { Zip64ExtraField::ID => Ok(Self::Zip64(Zip64ExtraField::from_generic(&field)?)), _ => Ok(Self::Generic(field)), } */ } fn size(&self) -> usize { self.to_generic().unwrap().size() } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Zip64ExtraField { pub original_size: Option, pub compressed_size: Option, pub offset_header: Option, pub disk_number: Option, } impl Zip64ExtraField { pub const ID: u16 = 0x0001; fn to_generic_field(&self) -> Result { let mut data = Cursor::new(Vec::::new()); if let Some(original_size) = self.original_size { original_size.serialize(&mut data)?; } if let Some(compressed_size) = self.compressed_size { compressed_size.serialize(&mut data)?; } if let Some(offset_header) = self.offset_header { offset_header.serialize(&mut data)?; } if let Some(disk_number) = self.disk_number { disk_number.serialize(&mut data)?; } Ok(GenericExtraField { id: Self::ID, data: data.into_inner(), }) } pub fn from_generic( field: &GenericExtraField, original_size: bool, compressed_size: bool, offset_header: bool, disk_number: bool, ) -> Result { assert_eq!(field.id, Self::ID); let mut data = Cursor::new(&field.data); let original_size = if original_size { Some(u64::deserialize(&mut data)?) } else { None }; let compressed_size = if compressed_size { Some(u64::deserialize(&mut data)?) } else { None }; let offset_header = if offset_header { Some(u64::deserialize(&mut data)?) } else { None }; let disk_number = if disk_number { Some(u32::deserialize(&mut data)?) } else { None }; Ok(Self { original_size, compressed_size, offset_header, disk_number, }) } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct GenericExtraField { pub id: u16, pub data: Vec, } impl Serializable for GenericExtraField { fn serialize(&self, output: &mut dyn Write) -> Result<()> { self.id.serialize(output)?; (self.data.len() as u16).serialize(output)?; for c in &self.data { c.serialize(output)?; } Ok(()) } fn deserialize(input: &mut dyn ReadSeek) -> Result { let id = u16::deserialize(input)?; let data_size = u16::deserialize(input)?; let mut data = vec![]; for _ in 0..data_size { data.push(u8::deserialize(input)?); } Ok(Self { id, data }) } fn size(&self) -> usize { 4 + self.data.len() } }