squashfs_async/
fragments.rs1use serde::Deserialize;
3use tokio::io::{AsyncReadExt, AsyncSeekExt};
4
5use super::data;
6use super::deser;
7use super::error::FragmentsError;
8use super::metadata;
9use super::superblock::SuperBlock;
10
11#[derive(Debug, Default, Copy, Clone, Deserialize)]
13pub struct FragmentLocation {
14 pub index: u32,
15 pub offset: u32,
16}
17impl FragmentLocation {
18 pub fn valid(&self) -> bool {
19 self.index != 0xFFFFFFFF
20 }
21}
22
23#[derive(Debug, Deserialize)]
25pub struct Entry {
26 pub start: u64,
27 pub size: data::BlockSize,
28 _unused: u32,
29}
30#[derive(Default, Debug)]
32pub struct FragmentsTable {
33 pub entries: Vec<Entry>,
34}
35impl std::fmt::Display for FragmentsTable {
36 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
37 write!(f, "Fragment table with {} entries", self.entries.len())
38 }
39}
40
41impl FragmentsTable {
42 pub fn entry(&self, location: FragmentLocation) -> Result<&Entry, FragmentsError> {
44 if !location.valid() {
45 return Err(FragmentsError::InvalidLocation);
46 }
47
48 self.entries
49 .get(location.index as usize)
50 .ok_or(FragmentsError::InvalidLocation)
51 }
52 pub async fn from_reader(
54 superblock: &SuperBlock,
55 mut r: impl crate::AsyncSeekBufRead,
56 ) -> Result<Self, FragmentsError> {
57 r.seek(std::io::SeekFrom::Start(superblock.fragment_table_start))
58 .await
59 .map_err(FragmentsError::ReadFailure)?;
60 let n = (superblock.fragment_entry_count as f64 / 512.0).ceil() as usize;
61 let mut locations = Vec::<u64>::with_capacity(n);
62 for _ in 0..n {
63 locations.push(
64 r.read_u64_le()
65 .await
66 .map_err(|_| FragmentsError::InvalidLocation)?,
67 )
68 }
69 let mut entries = Vec::<Entry>::with_capacity(superblock.fragment_entry_count as usize);
70 for l in locations {
71 r.seek(std::io::SeekFrom::Start(l))
72 .await
73 .map_err(FragmentsError::ReadFailure)?;
74 let block =
75 metadata::MetadataBlock::from_reader(&mut r, superblock.compression).await?;
76 entries.extend(
77 block
78 .data
79 .chunks(16)
80 .map(deser::bincode_deser)
81 .collect::<Result<Vec<Entry>, _>>()
82 .map_err(|_| FragmentsError::InvalidEntry)?,
83 );
84 }
85 Ok(Self { entries })
86 }
87}