Skip to main content

pcf_debug/
lib.rs

1//! `pcf-debug` — a read-only inspector and visualiser for Partitioned Container
2//! Format (PCF) files.
3//!
4//! The crate is organised as a pipeline:
5//!
6//! 1. [`model::walk`] reads the file's physical structure defensively.
7//! 2. [`model::build`] turns that into a [`model::LayoutMap`] with gaps and
8//!    overlaps materialised.
9//! 3. [`plugin`] decoders turn each partition's bytes into a field tree.
10//! 4. [`render`] turns the shared [`render::Report`] into text, hexdumps, or
11//!    HTML.
12//!
13//! The orchestration helper [`build_report`] runs steps 1–3; the binary in
14//! `main.rs` adds argument parsing and chooses a renderer.
15
16pub mod cli;
17pub mod model;
18pub mod plugin;
19pub mod render;
20
21use plugin::{DecoderRegistry, PartitionMeta};
22use render::Report;
23
24/// Read a partition's used bytes from the file image, or an empty slice when the
25/// region is out of bounds or empty.
26fn partition_bytes(data: &[u8], entry: &pcf::PartitionEntry, in_bounds: bool) -> Vec<u8> {
27    if in_bounds && entry.used_bytes > 0 {
28        let start = entry.start_offset as usize;
29        let end = (entry.start_offset + entry.used_bytes) as usize;
30        data[start..end].to_vec()
31    } else {
32        Vec::new()
33    }
34}
35
36/// Build the full report (physical layout + decoded partitions) from raw bytes.
37pub fn build_report(data: &[u8], verify: bool, registry: &DecoderRegistry) -> Report {
38    let walk = model::walk(data, verify);
39    let layout = model::build(&walk);
40
41    let mut decoded = Vec::new();
42    for b in &layout.blocks {
43        for ev in &b.entries {
44            let e = &ev.entry;
45            let bytes = partition_bytes(data, e, ev.data_in_bounds);
46            let label = e.label_string().unwrap_or_default();
47            let meta = PartitionMeta {
48                partition_type: e.partition_type,
49                uid: &e.uid,
50                label: &label,
51            };
52            decoded.push((e.uid, registry.decode(&meta, &bytes)));
53        }
54    }
55    Report { layout, decoded }
56}