Skip to content

Commit de801df

Browse files
committed
Add try_from_iter for ArrayRegisterData and VecRegisterData
1 parent 53fb533 commit de801df

File tree

1 file changed

+134
-48
lines changed

1 file changed

+134
-48
lines changed

core/src/register_data.rs

Lines changed: 134 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -80,71 +80,102 @@ impl<const SIZE: usize, RB: funty::Integral> ArrayRegisterData<SIZE, RB> {
8080
}
8181
}
8282

83-
impl<const SIZE: usize, RB: funty::Integral> RegisterData<RB> for ArrayRegisterData<SIZE, RB> {
84-
fn register(&self, register: gimli::Register) -> Option<RB> {
85-
let local_register_index = register.0.checked_sub(self.starting_register_number)?;
86-
self.registers.get(local_register_index as usize).copied()
87-
}
88-
fn register_ref(&self, register: gimli::Register) -> Option<&RB> {
89-
let local_register_index = register.0.checked_sub(self.starting_register_number)?;
90-
self.registers.get(local_register_index as usize)
91-
}
92-
fn register_mut(&mut self, register: gimli::Register) -> Option<&mut RB> {
93-
let local_register_index = register.0.checked_sub(self.starting_register_number)?;
94-
self.registers.get_mut(local_register_index as usize)
95-
}
96-
}
97-
98-
impl<const SIZE: usize, RB> FromIterator<u8> for ArrayRegisterData<SIZE, RB>
83+
impl<const SIZE: usize, RB> ArrayRegisterData<SIZE, RB>
9984
where
10085
RB: funty::Integral,
10186
RB::Bytes: for<'a> TryFrom<&'a [u8]>,
10287
{
103-
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
104-
// Get the iterator. We assume that it is in the same format as the bytes function outputs
88+
/// Try to build a [ArrayRegisterData] from an [IntoIterator<Item = u8>]
89+
pub fn try_from_iter<I: IntoIterator<Item = u8>>(
90+
iter: I,
91+
) -> Result<Self, RegisterDataFromIterError> {
92+
use RegisterDataFromIterError::*;
93+
// Get the iterator.
10594
let mut iter = iter.into_iter();
10695

107-
assert_eq!(
108-
iter.next().unwrap(),
109-
REGISTER_DATA_IDENTIFIER,
110-
"The given iterator is not for register data"
111-
);
96+
match iter.next() {
97+
Some(REGISTER_DATA_IDENTIFIER) => {}
98+
Some(id) => return Err(InvalidIdentifier(id)),
99+
None => return Err(NotEnoughItems),
100+
}
112101

113102
// First the starting number is encoded
114-
let starting_register_number =
115-
u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
103+
let starting_register_number = u16::from_le_bytes([
104+
iter.next().ok_or(NotEnoughItems)?,
105+
iter.next().ok_or(NotEnoughItems)?,
106+
]);
116107

117108
// Second is how many registers there are
118-
let register_count = u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
109+
let register_count = u16::from_le_bytes([
110+
iter.next().ok_or(NotEnoughItems)?,
111+
iter.next().ok_or(NotEnoughItems)?,
112+
]);
119113

120114
// Create the buffer we're storing the registers in
121115
let mut registers = ArrayVec::new();
122116

123117
// We process everything byte-by-byte generically so every register has an unknown length
124118
// So we need to store the bytes temporarily until we have enough to fully read the bytes as a register
125119
let register_size = core::mem::size_of::<RB>();
120+
121+
// Check that all register bytes will fit in `registers`
122+
let num_register_bytes = register_count as usize * register_size;
123+
if num_register_bytes > SIZE {
124+
return Err(LengthTooBig(register_count, register_size));
125+
}
126+
126127
let mut register_bytes_buffer = ArrayVec::<u8, 16>::new();
127128

128-
for byte in (0..register_count as usize * register_size).map(|_| iter.next().unwrap()) {
129-
register_bytes_buffer.push(byte);
129+
for byte in
130+
(0..num_register_bytes).map(|_| iter.next().ok_or(NotEnoughItems))
131+
{
132+
let byte = byte?;
133+
register_bytes_buffer.try_push(byte).map_err(|_| Corrupt)?;
130134

131135
if register_bytes_buffer.len() == register_size {
132136
registers.push(RB::from_le_bytes(
133137
register_bytes_buffer
134138
.as_slice()
135139
.try_into()
136-
.unwrap_or_else(|_| panic!()),
140+
.map_err(|_| Corrupt)?,
137141
));
138142
register_bytes_buffer = ArrayVec::new();
139143
}
140144
}
141145

142-
assert!(register_bytes_buffer.is_empty());
146+
if !register_bytes_buffer.is_empty() {
147+
return Err(Corrupt);
148+
}
143149

144-
Self {
150+
Ok(Self {
145151
starting_register_number,
146152
registers,
147-
}
153+
})
154+
}
155+
}
156+
157+
impl<const SIZE: usize, RB: funty::Integral> RegisterData<RB> for ArrayRegisterData<SIZE, RB> {
158+
fn register(&self, register: gimli::Register) -> Option<RB> {
159+
let local_register_index = register.0.checked_sub(self.starting_register_number)?;
160+
self.registers.get(local_register_index as usize).copied()
161+
}
162+
fn register_ref(&self, register: gimli::Register) -> Option<&RB> {
163+
let local_register_index = register.0.checked_sub(self.starting_register_number)?;
164+
self.registers.get(local_register_index as usize)
165+
}
166+
fn register_mut(&mut self, register: gimli::Register) -> Option<&mut RB> {
167+
let local_register_index = register.0.checked_sub(self.starting_register_number)?;
168+
self.registers.get_mut(local_register_index as usize)
169+
}
170+
}
171+
172+
impl<const SIZE: usize, RB> FromIterator<u8> for ArrayRegisterData<SIZE, RB>
173+
where
174+
RB: funty::Integral,
175+
RB::Bytes: for<'a> TryFrom<&'a [u8]>,
176+
{
177+
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
178+
Self::try_from_iter(iter).unwrap()
148179
}
149180
}
150181

@@ -223,50 +254,76 @@ impl<RB: funty::Integral> RegisterData<RB> for VecRegisterData<RB> {
223254
}
224255

225256
#[cfg(feature = "std")]
226-
impl<RB> FromIterator<u8> for VecRegisterData<RB>
257+
impl<RB> VecRegisterData<RB>
227258
where
228259
RB: funty::Integral,
229260
RB::Bytes: for<'a> TryFrom<&'a [u8]>,
230261
{
231-
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
262+
/// Try to build a [VecRegisterData] from an [IntoIterator<Item = u8>]
263+
pub fn try_from_iter<I: IntoIterator<Item = u8>>(
264+
iter: I,
265+
) -> Result<Self, RegisterDataFromIterError> {
266+
use RegisterDataFromIterError::*;
267+
232268
let mut iter = iter.into_iter();
233269

234-
assert_eq!(
235-
iter.next().unwrap(),
236-
REGISTER_DATA_IDENTIFIER,
237-
"The given iterator is not for register data"
238-
);
270+
match iter.next() {
271+
Some(REGISTER_DATA_IDENTIFIER) => {}
272+
Some(id) => return Err(InvalidIdentifier(id)),
273+
None => return Err(NotEnoughItems),
274+
}
239275

240-
let starting_register_number =
241-
u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
276+
let starting_register_number = u16::from_le_bytes([
277+
iter.next().ok_or(NotEnoughItems)?,
278+
iter.next().ok_or(NotEnoughItems)?,
279+
]);
242280

243-
let register_count = u16::from_le_bytes([iter.next().unwrap(), iter.next().unwrap()]);
281+
let register_count = u16::from_le_bytes([
282+
iter.next().ok_or(NotEnoughItems)?,
283+
iter.next().ok_or(NotEnoughItems)?,
284+
]);
244285

245286
let mut registers = Vec::new();
246287
let register_size = core::mem::size_of::<RB>();
247288

248289
let mut register_bytes_buffer = ArrayVec::<u8, 16>::new();
249290

250-
for byte in (0..register_count as usize * register_size).map(|_| iter.next().unwrap()) {
251-
register_bytes_buffer.push(byte);
291+
for byte in
292+
(0..register_count as usize * register_size).map(|_| iter.next().ok_or(NotEnoughItems))
293+
{
294+
let byte = byte?;
295+
register_bytes_buffer.try_push(byte).map_err(|_| Corrupt)?;
252296

253297
if register_bytes_buffer.len() == register_size {
254298
registers.push(RB::from_le_bytes(
255299
register_bytes_buffer
256300
.as_slice()
257301
.try_into()
258-
.unwrap_or_else(|_| panic!()),
302+
.map_err(|_| Corrupt)?,
259303
));
260304
register_bytes_buffer.clear();
261305
}
262306
}
263307

264-
assert!(register_bytes_buffer.is_empty());
308+
if !register_bytes_buffer.is_empty() {
309+
return Err(Corrupt);
310+
}
265311

266-
Self {
312+
Ok(Self {
267313
starting_register_number,
268314
registers,
269-
}
315+
})
316+
}
317+
}
318+
319+
#[cfg(feature = "std")]
320+
impl<RB> FromIterator<u8> for VecRegisterData<RB>
321+
where
322+
RB: funty::Integral,
323+
RB::Bytes: for<'a> TryFrom<&'a [u8]>,
324+
{
325+
fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
326+
Self::try_from_iter(iter).unwrap()
270327
}
271328
}
272329

@@ -324,6 +381,35 @@ impl<'a, RB: funty::Integral> Iterator for RegisterDataBytesIterator<'a, RB> {
324381

325382
impl<'a, RB: funty::Integral> ExactSizeIterator for RegisterDataBytesIterator<'a, RB> {}
326383

384+
#[derive(Debug)]
385+
/// Specifies what went wrong building a [RegisterData] from an iterator
386+
pub enum RegisterDataFromIterError {
387+
/// The given iterator is not for a register set.
388+
/// First item from iterator yielded invalid identifier. Expected [REGISTER_DATA_IDENTIFIER]
389+
InvalidIdentifier(u8),
390+
/// Iterator specified length too big for declared register set
391+
LengthTooBig(u16, usize),
392+
/// Iterator did not yield enough items to build register set
393+
NotEnoughItems,
394+
/// Iterator data is corrupt in some other way
395+
Corrupt,
396+
}
397+
398+
impl core::fmt::Display for RegisterDataFromIterError {
399+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
400+
use RegisterDataFromIterError::*;
401+
match self {
402+
InvalidIdentifier(id) => write!(f, "Iterator is not for a register set. Started with {id}, expected {REGISTER_DATA_IDENTIFIER}"),
403+
LengthTooBig(count, size) => write!(f, "Iterator specified length too big for register set: {len}", len = *count as usize * size),
404+
NotEnoughItems => write!(f, "Iterator did not yield enough items to build register set"),
405+
Corrupt => write!(f, "Iterator data is corrupt")
406+
}
407+
}
408+
}
409+
410+
#[cfg(feature = "std")]
411+
impl std::error::Error for RegisterDataFromIterError {}
412+
327413
#[cfg(test)]
328414
mod tests {
329415
use super::*;

0 commit comments

Comments
 (0)