apple_flat_package/
component_package.rs1use {
8 crate::{package_info::PackageInfo, PkgResult},
9 cpio_archive::ChainedCpioReader,
10 std::io::{Cursor, Read},
11};
12
13const GZIP_HEADER: [u8; 3] = [0x1f, 0x8b, 0x08];
14
15fn decode_archive(data: Vec<u8>) -> PkgResult<Box<dyn Read>> {
20 if data.len() > 3 && data[0..3] == GZIP_HEADER {
21 Ok(Box::new(flate2::read::GzDecoder::new(Cursor::new(data))) as Box<dyn Read>)
22 } else {
23 Ok(Box::new(Cursor::new(data)) as Box<dyn Read>)
24 }
25}
26
27pub type CpioReader = Box<ChainedCpioReader<Box<dyn Read>>>;
29
30fn cpio_reader(data: &[u8]) -> PkgResult<CpioReader> {
31 let decoder = decode_archive(data.to_vec())?;
32 Ok(cpio_archive::reader(decoder)?)
33}
34
35pub struct ComponentPackageReader {
37 bom: Option<Vec<u8>>,
38 package_info: Option<PackageInfo>,
39 payload: Option<Vec<u8>>,
40 scripts: Option<Vec<u8>>,
41}
42
43impl ComponentPackageReader {
44 pub fn from_file_data(
46 bom: Option<Vec<u8>>,
47 package_info: Option<Vec<u8>>,
48 payload: Option<Vec<u8>>,
49 scripts: Option<Vec<u8>>,
50 ) -> PkgResult<Self> {
51 let package_info = if let Some(data) = package_info {
52 Some(PackageInfo::from_reader(Cursor::new(data))?)
53 } else {
54 None
55 };
56
57 Ok(Self {
58 bom,
59 package_info,
60 payload,
61 scripts,
62 })
63 }
64
65 pub fn bom(&self) -> Option<&[u8]> {
67 self.bom.as_ref().map(|x| x.as_ref())
68 }
69
70 pub fn package_info(&self) -> Option<&PackageInfo> {
72 self.package_info.as_ref()
73 }
74
75 pub fn payload_reader(&self) -> PkgResult<Option<CpioReader>> {
77 if let Some(payload) = &self.payload {
78 Ok(Some(cpio_reader(payload)?))
79 } else {
80 Ok(None)
81 }
82 }
83
84 pub fn scripts_reader(&self) -> PkgResult<Option<CpioReader>> {
86 if let Some(data) = &self.scripts {
87 Ok(Some(cpio_reader(data)?))
88 } else {
89 Ok(None)
90 }
91 }
92}