1use core::iter::FusedIterator;
5use core::mem;
6use core::ops::{Deref, Range};
7
8use zerocopy::byteorder::LittleEndian;
9use zerocopy::{
10 FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, SplitByteSliceMut,
11 Unaligned, U32,
12};
13
14use crate::error::{NtHiveError, Result};
15use crate::helpers::byte_subrange;
16use crate::hive::Hive;
17use crate::index_root::IndexRootItemRange;
18use crate::key_node::{KeyNode, KeyNodeMut};
19use crate::subkeys_list::SubkeysList;
20
21#[allow(dead_code)]
24#[derive(FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned)]
25#[repr(packed)]
26struct FastLeafItem {
27 key_node_offset: U32<LittleEndian>,
28 name_hint: [u8; 4],
29}
30
31#[allow(dead_code)]
34#[derive(FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned)]
35#[repr(packed)]
36struct HashLeafItem {
37 key_node_offset: U32<LittleEndian>,
38 name_hash: [u8; 4],
39}
40
41#[derive(FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned)]
44#[repr(packed)]
45struct IndexLeafItem {
46 key_node_offset: U32<LittleEndian>,
47}
48
49#[derive(Clone, Copy)]
61pub(crate) enum LeafType {
62 Fast,
63 Hash,
64 Index,
65}
66
67impl LeafType {
68 pub(crate) fn from_signature(signature: &[u8]) -> Option<Self> {
69 match signature {
70 b"lf" => Some(Self::Fast),
71 b"lh" => Some(Self::Hash),
72 b"li" => Some(Self::Index),
73 _ => None,
74 }
75 }
76
77 fn item_size(&self) -> usize {
78 match self {
79 Self::Fast => mem::size_of::<FastLeafItem>(),
80 Self::Hash => mem::size_of::<HashLeafItem>(),
81 Self::Index => mem::size_of::<IndexLeafItem>(),
82 }
83 }
84}
85
86pub(crate) struct LeafItemRange(Range<usize>);
88
89impl LeafItemRange {
90 pub fn key_node_offset<B>(&self, hive: &Hive<B>) -> u32
91 where
92 B: SplitByteSlice,
93 {
94 let (index_leaf_item, _) =
98 Ref::<&[u8], IndexLeafItem>::from_prefix(&hive.data[self.0.clone()]).unwrap();
99 index_leaf_item.key_node_offset.get()
100 }
101}
102
103impl Deref for LeafItemRange {
104 type Target = Range<usize>;
105
106 fn deref(&self) -> &Self::Target {
107 &self.0
108 }
109}
110
111#[derive(Clone)]
117pub(crate) struct LeafItemRanges {
118 items_range: Range<usize>,
119 leaf_type: LeafType,
120}
121
122impl LeafItemRanges {
123 pub fn new(
124 count: u16,
125 count_field_offset: usize,
126 data_range: Range<usize>,
127 leaf_type: LeafType,
128 ) -> Result<Self> {
129 let byte_count = count as usize * leaf_type.item_size();
130
131 let items_range = byte_subrange(&data_range, byte_count).ok_or_else(|| {
132 NtHiveError::InvalidSizeField {
133 offset: count_field_offset,
134 expected: byte_count,
135 actual: data_range.len(),
136 }
137 })?;
138
139 Ok(Self {
140 items_range,
141 leaf_type,
142 })
143 }
144
145 pub fn from_index_root_item_range<B>(
146 hive: &Hive<B>,
147 index_root_item_range: IndexRootItemRange,
148 ) -> Result<Self>
149 where
150 B: SplitByteSlice,
151 {
152 let subkeys_list_offset = index_root_item_range.subkeys_list_offset(hive);
153 let cell_range = hive.cell_range_from_data_offset(subkeys_list_offset)?;
154 let subkeys_list = SubkeysList::new_without_index_root(hive, cell_range)?;
155
156 let header = subkeys_list.header();
157 let count = header.count.get();
158 let count_field_offset = hive.offset_of_field(&header.count);
159
160 if count == 0 {
164 return Err(NtHiveError::InvalidSizeField {
165 offset: count_field_offset,
166 expected: 1,
167 actual: 0,
168 });
169 }
170
171 let leaf_type = LeafType::from_signature(&header.signature).unwrap();
172 LeafItemRanges::new(
173 count,
174 count_field_offset,
175 subkeys_list.data_range,
176 leaf_type,
177 )
178 }
179}
180
181impl Iterator for LeafItemRanges {
182 type Item = LeafItemRange;
183
184 fn next(&mut self) -> Option<Self::Item> {
185 let item_size = self.leaf_type.item_size();
186 let item_range = byte_subrange(&self.items_range, item_size)?;
187 self.items_range.start += item_size;
188
189 Some(LeafItemRange(item_range))
190 }
191
192 fn count(self) -> usize {
193 let (size, _) = self.size_hint();
194 size
195 }
196
197 fn last(mut self) -> Option<Self::Item> {
198 let (size, _) = self.size_hint();
199 if size == 0 {
200 return None;
201 }
202
203 self.nth(size - 1)
204 }
205
206 fn nth(&mut self, n: usize) -> Option<Self::Item> {
207 let bytes_to_skip = n.checked_mul(self.leaf_type.item_size())?;
209 self.items_range.start = self.items_range.start.checked_add(bytes_to_skip)?;
210 self.next()
211 }
212
213 fn size_hint(&self) -> (usize, Option<usize>) {
214 let size = self.items_range.len() / self.leaf_type.item_size();
215 (size, Some(size))
216 }
217}
218
219impl<B: SplitByteSlice> From<LeafKeyNodes<'_, B>> for LeafItemRanges {
220 fn from(leaf_key_nodes: LeafKeyNodes<'_, B>) -> LeafItemRanges {
221 leaf_key_nodes.leaf_item_ranges
222 }
223}
224
225impl ExactSizeIterator for LeafItemRanges {}
226impl FusedIterator for LeafItemRanges {}
227
228#[derive(Clone)]
237pub struct LeafKeyNodes<'h, B: SplitByteSlice> {
238 hive: &'h Hive<B>,
239 leaf_item_ranges: LeafItemRanges,
240}
241
242impl<'h, B> LeafKeyNodes<'h, B>
243where
244 B: SplitByteSlice,
245{
246 pub(crate) fn new(
247 hive: &'h Hive<B>,
248 count: u16,
249 count_field_offset: usize,
250 data_range: Range<usize>,
251 leaf_type: LeafType,
252 ) -> Result<Self> {
253 let leaf_item_ranges =
254 LeafItemRanges::new(count, count_field_offset, data_range, leaf_type)?;
255
256 Ok(Self {
257 hive,
258 leaf_item_ranges,
259 })
260 }
261}
262
263impl<'h, B> Iterator for LeafKeyNodes<'h, B>
264where
265 B: SplitByteSlice,
266{
267 type Item = Result<KeyNode<'h, B>>;
268
269 fn next(&mut self) -> Option<Self::Item> {
270 let leaf_item_range = self.leaf_item_ranges.next()?;
271 let key_node = iter_try!(KeyNode::from_leaf_item_range(self.hive, leaf_item_range));
272 Some(Ok(key_node))
273 }
274
275 fn count(self) -> usize {
276 self.leaf_item_ranges.count()
277 }
278
279 fn last(mut self) -> Option<Self::Item> {
280 let (size, _) = self.size_hint();
281 if size == 0 {
282 return None;
283 }
284
285 self.nth(size - 1)
286 }
287
288 fn nth(&mut self, n: usize) -> Option<Self::Item> {
289 let bytes_to_skip = n.checked_mul(self.leaf_item_ranges.leaf_type.item_size())?;
291 self.leaf_item_ranges.items_range.start = self
292 .leaf_item_ranges
293 .items_range
294 .start
295 .checked_add(bytes_to_skip)?;
296 self.next()
297 }
298
299 fn size_hint(&self) -> (usize, Option<usize>) {
300 self.leaf_item_ranges.size_hint()
301 }
302}
303
304impl<B> ExactSizeIterator for LeafKeyNodes<'_, B> where B: SplitByteSlice {}
305impl<B> FusedIterator for LeafKeyNodes<'_, B> where B: SplitByteSlice {}
306
307pub(crate) struct LeafKeyNodesMut<'h, B: SplitByteSliceMut> {
316 hive: &'h mut Hive<B>,
317 leaf_item_ranges: LeafItemRanges,
318}
319
320impl<'h, B> LeafKeyNodesMut<'h, B>
321where
322 B: SplitByteSliceMut,
323{
324 pub(crate) fn new(
325 hive: &'h mut Hive<B>,
326 count: u16,
327 count_field_offset: usize,
328 data_range: Range<usize>,
329 leaf_type: LeafType,
330 ) -> Result<Self> {
331 let leaf_item_ranges =
332 LeafItemRanges::new(count, count_field_offset, data_range, leaf_type)?;
333
334 Ok(Self {
335 hive,
336 leaf_item_ranges,
337 })
338 }
339
340 pub(crate) fn next<'a>(&'a mut self) -> Option<Result<KeyNodeMut<'a, B>>>
341 where
342 'h: 'a,
343 {
344 let leaf_item_range = self.leaf_item_ranges.next()?;
345 let key_node = iter_try!(KeyNodeMut::from_leaf_item_range(self.hive, leaf_item_range));
346 Some(Ok(key_node))
347 }
348}