nt_hive/
key_values_list.rs1use core::iter::FusedIterator;
5use core::mem;
6use core::ops::{Deref, Range};
7
8use zerocopy::byteorder::LittleEndian;
9use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, Unaligned, U32};
10
11use crate::error::{NtHiveError, Result};
12use crate::helpers::byte_subrange;
13use crate::hive::Hive;
14use crate::key_value::KeyValue;
15
16#[allow(dead_code)]
18#[derive(FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned)]
19#[repr(packed)]
20struct KeyValuesListItem {
21 key_value_offset: U32<LittleEndian>,
22}
23
24struct KeyValuesListItemRange(Range<usize>);
26
27impl KeyValuesListItemRange {
28 fn key_value_offset<B>(&self, hive: &Hive<B>) -> u32
29 where
30 B: SplitByteSlice,
31 {
32 let item = Ref::<&[u8], KeyValuesListItem>::from_bytes(&hive.data[self.0.clone()]).unwrap();
33 item.key_value_offset.get()
34 }
35}
36
37impl Deref for KeyValuesListItemRange {
38 type Target = Range<usize>;
39
40 fn deref(&self) -> &Self::Target {
41 &self.0
42 }
43}
44
45#[derive(Clone)]
51struct KeyValuesListItemRanges {
52 items_range: Range<usize>,
53}
54
55impl KeyValuesListItemRanges {
56 pub(crate) fn new(
57 count: u32,
58 count_field_offset: usize,
59 cell_range: Range<usize>,
60 ) -> Result<Self> {
61 let byte_count = count as usize * mem::size_of::<KeyValuesListItem>();
62
63 let items_range = byte_subrange(&cell_range, byte_count).ok_or_else(|| {
64 NtHiveError::InvalidSizeField {
65 offset: count_field_offset,
66 expected: byte_count,
67 actual: cell_range.len(),
68 }
69 })?;
70
71 Ok(Self { items_range })
72 }
73}
74
75impl Iterator for KeyValuesListItemRanges {
76 type Item = KeyValuesListItemRange;
77
78 fn next(&mut self) -> Option<Self::Item> {
79 let item_range = byte_subrange(&self.items_range, mem::size_of::<KeyValuesListItem>())?;
80 self.items_range.start += mem::size_of::<KeyValuesListItem>();
81
82 Some(KeyValuesListItemRange(item_range))
83 }
84
85 fn count(self) -> usize {
86 let (size, _) = self.size_hint();
87 size
88 }
89
90 fn last(mut self) -> Option<Self::Item> {
91 let (size, _) = self.size_hint();
92 if size == 0 {
93 return None;
94 }
95
96 self.nth(size - 1)
97 }
98
99 fn nth(&mut self, n: usize) -> Option<Self::Item> {
100 let bytes_to_skip = n.checked_mul(mem::size_of::<KeyValuesListItem>())?;
102 self.items_range.start = self.items_range.start.checked_add(bytes_to_skip)?;
103 self.next()
104 }
105
106 fn size_hint(&self) -> (usize, Option<usize>) {
107 let size = self.items_range.len() / mem::size_of::<KeyValuesListItem>();
108 (size, Some(size))
109 }
110}
111
112impl ExactSizeIterator for KeyValuesListItemRanges {}
113impl FusedIterator for KeyValuesListItemRanges {}
114
115#[derive(Clone)]
121pub struct KeyValues<'h, B: SplitByteSlice> {
122 hive: &'h Hive<B>,
123 key_values_list_item_ranges: KeyValuesListItemRanges,
124}
125
126impl<'h, B> KeyValues<'h, B>
127where
128 B: SplitByteSlice,
129{
130 pub(crate) fn new(
131 hive: &'h Hive<B>,
132 count: u32,
133 count_field_offset: usize,
134 cell_range: Range<usize>,
135 ) -> Result<Self> {
136 let key_values_list_item_ranges =
137 KeyValuesListItemRanges::new(count, count_field_offset, cell_range)?;
138
139 Ok(Self {
140 hive,
141 key_values_list_item_ranges,
142 })
143 }
144}
145
146impl<'h, B> Iterator for KeyValues<'h, B>
147where
148 B: SplitByteSlice,
149{
150 type Item = Result<KeyValue<'h, B>>;
151
152 fn next(&mut self) -> Option<Self::Item> {
153 let key_values_list_item_range = self.key_values_list_item_ranges.next()?;
154 let key_value_offset = key_values_list_item_range.key_value_offset(self.hive);
155 let cell_range = iter_try!(self.hive.cell_range_from_data_offset(key_value_offset));
156 let key_value = iter_try!(KeyValue::new(self.hive, cell_range));
157 Some(Ok(key_value))
158 }
159
160 fn count(self) -> usize {
161 self.key_values_list_item_ranges.count()
162 }
163
164 fn last(mut self) -> Option<Self::Item> {
165 let (size, _) = self.size_hint();
166 if size == 0 {
167 return None;
168 }
169
170 self.nth(size - 1)
171 }
172
173 fn nth(&mut self, n: usize) -> Option<Self::Item> {
174 let bytes_to_skip = n.checked_mul(mem::size_of::<KeyValuesListItem>())?;
176 self.key_values_list_item_ranges.items_range.start = self
177 .key_values_list_item_ranges
178 .items_range
179 .start
180 .checked_add(bytes_to_skip)?;
181 self.next()
182 }
183
184 fn size_hint(&self) -> (usize, Option<usize>) {
185 self.key_values_list_item_ranges.size_hint()
186 }
187}
188
189impl<B> ExactSizeIterator for KeyValues<'_, B> where B: SplitByteSlice {}
190impl<B> FusedIterator for KeyValues<'_, B> where B: SplitByteSlice {}