1mod pcfsig;
15mod pfs;
16mod raw;
17
18pub use pcfsig::{PcfSigKeyDecoder, PcfSigSignatureDecoder};
19pub use pfs::{PfsNodeDecoder, PfsSessionDecoder};
20pub use raw::RawDecoder;
21
22#[derive(Debug, Clone, PartialEq)]
24pub enum FieldValue {
25 None,
27 U64(u64),
28 Bytes(Vec<u8>),
29 Text(String),
30 Uid([u8; 16]),
31 Enum {
33 raw: u64,
34 name: String,
35 },
36 Flags {
38 raw: u64,
39 set: Vec<String>,
40 },
41}
42
43#[derive(Debug, Clone, PartialEq)]
45pub struct FieldNode {
46 pub name: String,
47 pub value: FieldValue,
48 pub range: Option<(u64, u64)>,
50 pub note: Option<String>,
52 pub children: Vec<FieldNode>,
53}
54
55impl FieldNode {
56 pub fn group(name: impl Into<String>) -> Self {
58 Self {
59 name: name.into(),
60 value: FieldValue::None,
61 range: None,
62 note: None,
63 children: Vec::new(),
64 }
65 }
66
67 pub fn leaf(name: impl Into<String>, value: FieldValue, range: (u64, u64)) -> Self {
69 Self {
70 name: name.into(),
71 value,
72 range: Some(range),
73 note: None,
74 children: Vec::new(),
75 }
76 }
77
78 pub fn with_note(mut self, note: impl Into<String>) -> Self {
80 self.note = Some(note.into());
81 self
82 }
83
84 pub fn child(mut self, c: FieldNode) -> Self {
86 self.children.push(c);
87 self
88 }
89
90 pub fn push(&mut self, c: FieldNode) {
92 self.children.push(c);
93 }
94}
95
96#[derive(Debug, Clone, Copy)]
98pub struct PartitionMeta<'a> {
99 pub partition_type: u32,
100 pub uid: &'a [u8; 16],
101 pub label: &'a str,
102}
103
104#[derive(Debug, Clone)]
106pub struct Decoded {
107 pub format_name: String,
109 pub fields: Vec<FieldNode>,
110 pub warnings: Vec<String>,
112}
113
114pub trait PartitionDecoder {
116 fn name(&self) -> &'static str;
118
119 fn matches(&self, meta: &PartitionMeta, data: &[u8]) -> bool;
122
123 fn decode(&self, meta: &PartitionMeta, data: &[u8]) -> Decoded;
126}
127
128pub struct DecoderRegistry {
131 decoders: Vec<Box<dyn PartitionDecoder>>,
132}
133
134impl DecoderRegistry {
135 pub fn with_builtins() -> Self {
138 Self {
139 decoders: vec![
140 Box::new(PfsNodeDecoder),
141 Box::new(PfsSessionDecoder),
142 Box::new(PcfSigKeyDecoder),
143 Box::new(PcfSigSignatureDecoder),
144 Box::new(RawDecoder),
145 ],
146 }
147 }
148
149 pub fn register(&mut self, d: Box<dyn PartitionDecoder>) {
151 let insert_at = self.decoders.len().saturating_sub(1);
152 self.decoders.insert(insert_at, d);
153 }
154
155 pub fn names(&self) -> Vec<&'static str> {
157 self.decoders.iter().map(|d| d.name()).collect()
158 }
159
160 pub fn decode(&self, meta: &PartitionMeta, data: &[u8]) -> Decoded {
162 for d in &self.decoders {
163 if d.matches(meta, data) {
164 return d.decode(meta, data);
165 }
166 }
167 RawDecoder.decode(meta, data)
169 }
170
171 pub fn decode_with(&self, name: &str, meta: &PartitionMeta, data: &[u8]) -> Option<Decoded> {
173 self.decoders
174 .iter()
175 .find(|d| d.name() == name)
176 .map(|d| d.decode(meta, data))
177 }
178}
179
180impl Default for DecoderRegistry {
181 fn default() -> Self {
182 Self::with_builtins()
183 }
184}
185
186pub(crate) fn le_u16(data: &[u8], off: usize) -> Option<u16> {
188 Some(u16::from_le_bytes(data.get(off..off + 2)?.try_into().ok()?))
189}
190
191pub(crate) fn le_u32(data: &[u8], off: usize) -> Option<u32> {
193 Some(u32::from_le_bytes(data.get(off..off + 4)?.try_into().ok()?))
194}
195
196pub(crate) fn le_u64(data: &[u8], off: usize) -> Option<u64> {
198 Some(u64::from_le_bytes(data.get(off..off + 8)?.try_into().ok()?))
199}
200
201pub(crate) fn uid_at(data: &[u8], off: usize) -> Option<[u8; 16]> {
203 data.get(off..off + 16)?.try_into().ok()
204}