Skip to content

Commit 46da424

Browse files
committed
remove unchecked implementation
1 parent d51b103 commit 46da424

4 files changed

Lines changed: 43 additions & 44 deletions

File tree

sv2/binary-sv2/src/datatypes/copy_data_types.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
//
1313
// ### `Sv2DataType`
1414
// The `Sv2DataType` trait is implemented for these data types, providing methods for encoding and
15-
// decoding operations such as `from_bytes_unchecked`, `from_vec_`, `from_reader_` (if `std` is
16-
// available), and `to_slice_unchecked`. The methods use little-endian byte order for consistency
15+
// decoding operations such as `from_bytes_`, `from_reader_` (if `std` is available), and
16+
// `to_slice`. The methods use little-endian byte order for consistency
1717
// across platforms.
1818
//
1919
// ## Special Types
@@ -27,7 +27,11 @@
2727
// The `impl_sv2_for_unsigned` macro streamlines the implementation of the `Sv2DataType` trait for
2828
// unsigned integer types, ensuring little-endian byte ordering for serialization and handling both
2929
// in-memory buffers and `std::io::Read`/`Write` interfaces when `std` is available.
30-
use crate::{codec::Fixed, datatypes::Sv2DataType, Error};
30+
use crate::{
31+
codec::{Fixed, SizeHint},
32+
datatypes::Sv2DataType,
33+
Error,
34+
};
3135
use core::convert::{TryFrom, TryInto};
3236

3337
#[cfg(not(feature = "no_std"))]
@@ -40,8 +44,9 @@ impl Fixed for bool {
4044
}
4145

4246
impl<'a> Sv2DataType<'a> for bool {
43-
fn from_bytes_unchecked(data: &'a mut [u8]) -> Self {
44-
match data
47+
fn from_bytes_(data: &'a mut [u8]) -> Result<Self, Error> {
48+
bool::size_hint(data, 0)?;
49+
let value = match data
4550
.first()
4651
.map(|x: &u8| x << 7)
4752
.map(|x: u8| x >> 7)
@@ -50,7 +55,8 @@ impl<'a> Sv2DataType<'a> for bool {
5055
0 => false,
5156
1 => true,
5257
_ => panic!(),
53-
}
58+
};
59+
Ok(value)
5460
}
5561

5662
#[cfg(not(feature = "no_std"))]
@@ -60,11 +66,15 @@ impl<'a> Sv2DataType<'a> for bool {
6066
Self::from_bytes_(&mut dst)
6167
}
6268

63-
fn to_slice_unchecked(&'a self, dst: &mut [u8]) {
69+
fn to_slice(&'a self, dst: &mut [u8]) -> Result<usize, Error> {
70+
if dst.len() < Self::SIZE {
71+
return Err(Error::WriteError(Self::SIZE, dst.len()));
72+
}
6473
match self {
6574
true => dst[0] = 1,
6675
false => dst[0] = 0,
6776
};
77+
Ok(Self::SIZE)
6878
}
6979

7080
#[cfg(not(feature = "no_std"))]
@@ -102,25 +112,29 @@ impl Fixed for u64 {
102112
macro_rules! impl_sv2_for_unsigned {
103113
($a:ty) => {
104114
impl<'a> Sv2DataType<'a> for $a {
105-
fn from_bytes_unchecked(data: &'a mut [u8]) -> Self {
106-
// unchecked function is fine to panic
115+
fn from_bytes_(data: &'a mut [u8]) -> Result<Self, Error> {
116+
Self::size_hint(data, 0)?;
107117
let a: &[u8; Self::SIZE] = data[0..Self::SIZE].try_into().expect(
108118
"Try to decode a copy data type from a buffer that do not have enough bytes",
109119
);
110-
Self::from_le_bytes(*a)
120+
Ok(Self::from_le_bytes(*a))
111121
}
112122

113123
#[cfg(not(feature = "no_std"))]
114124
fn from_reader_(reader: &mut impl Read) -> Result<Self, Error> {
115125
let mut dst = [0_u8; Self::SIZE];
116126
reader.read_exact(&mut dst)?;
117-
Ok(Self::from_bytes_unchecked(&mut dst))
127+
Ok(Self::from_le_bytes(dst))
118128
}
119129

120-
fn to_slice_unchecked(&'a self, dst: &mut [u8]) {
130+
fn to_slice(&'a self, dst: &mut [u8]) -> Result<usize, Error> {
131+
if dst.len() < Self::SIZE {
132+
return Err(Error::WriteError(Self::SIZE, dst.len()));
133+
}
121134
let dst = &mut dst[0..Self::SIZE];
122135
let src = self.to_le_bytes();
123136
dst.copy_from_slice(&src);
137+
Ok(Self::SIZE)
124138
}
125139

126140
#[cfg(not(feature = "no_std"))]

sv2/binary-sv2/src/datatypes/mod.rs

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
// - **Deserialize**: Convert byte slices or reader sources into Rust types.
1111
// - **Serialize**: Encode Rust types into byte slices or write them to I/O streams.
1212
//
13-
// Supports both **checked** and **unchecked** variants for serialization and deserialization.
14-
// Checked functions validate data lengths, while unchecked versions assume size correctness for
15-
// optimized performance.
13+
// Checked functions validate data lengths before decoding or encoding.
1614
//
1715
// ### Modules
1816
// - **`copy_data_types`**: Defines fixed-size types directly copied into or from byte slices, such
@@ -55,41 +53,19 @@ use std::io::{Error as E, Read, Write};
5553
/// - Deserialization: Converting byte slices or streams back into the in-memory representation of
5654
/// the data.
5755
///
58-
/// This trait includes functions for both checked and unchecked conversions, providing flexibility
59-
/// in situations where error handling can be safely ignored.
6056
pub trait Sv2DataType<'a>: Sized + SizeHint + GetSize + TryInto<FieldMarker> {
6157
/// Creates an instance of the type from a mutable byte slice, checking for size constraints.
6258
///
6359
/// This function verifies that the provided byte slice has the correct size according to the
6460
/// type's size hint.
65-
fn from_bytes_(data: &'a mut [u8]) -> Result<Self, Error> {
66-
let size = Self::size_hint(data, 0)?;
67-
if size > data.len() {
68-
return Err(Error::ReadError(data.len(), size));
69-
}
70-
let (head, _) = data.split_at_mut(size);
71-
Ok(Self::from_bytes_unchecked(head))
72-
}
73-
74-
/// Constructs an instance from a mutable byte slice without verifying size constraints.
75-
fn from_bytes_unchecked(data: &'a mut [u8]) -> Self;
61+
fn from_bytes_(data: &'a mut [u8]) -> Result<Self, Error>;
7662

7763
// Constructs an instance from a reader source, checking for size constraints.
7864
#[cfg(not(feature = "no_std"))]
7965
fn from_reader_(reader: &mut impl Read) -> Result<Self, Error>;
8066

8167
/// Serializes the instance to a mutable slice, checking the destination size.
82-
fn to_slice(&'a self, dst: &mut [u8]) -> Result<usize, Error> {
83-
if dst.len() >= self.get_size() {
84-
self.to_slice_unchecked(dst);
85-
Ok(self.get_size())
86-
} else {
87-
Err(Error::WriteError(self.get_size(), dst.len()))
88-
}
89-
}
90-
91-
/// Serializes the instance to a mutable slice without checking the destination size.
92-
fn to_slice_unchecked(&'a self, dst: &mut [u8]);
68+
fn to_slice(&'a self, dst: &mut [u8]) -> Result<usize, Error>;
9369

9470
// Serializes the instance to a writer destination, checking for I/O errors.
9571
#[cfg(not(feature = "no_std"))]

sv2/binary-sv2/src/datatypes/non_copy_data_types/inner.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,16 @@ impl<'a, const ISFIXED: bool, const SIZE: usize, const HEADERSIZE: usize, const
333333
where
334334
Self: TryInto<FieldMarker>,
335335
{
336-
fn from_bytes_unchecked(data: &'a mut [u8]) -> Self {
336+
fn from_bytes_(data: &'a mut [u8]) -> Result<Self, Error> {
337+
let size = Self::size_hint(data, 0)?;
338+
if size > data.len() {
339+
return Err(Error::ReadError(data.len(), size));
340+
}
341+
let (head, _) = data.split_at_mut(size);
337342
if ISFIXED {
338-
Self::Ref(data)
343+
Ok(Self::Ref(head))
339344
} else {
340-
Self::Ref(&mut data[HEADERSIZE..])
345+
Ok(Self::Ref(&mut head[HEADERSIZE..]))
341346
}
342347
}
343348

@@ -351,8 +356,11 @@ where
351356
Ok(Self::Owned(dst))
352357
}
353358

354-
fn to_slice_unchecked(&'a self, dst: &mut [u8]) {
359+
fn to_slice(&'a self, dst: &mut [u8]) -> Result<usize, Error> {
355360
let size = self.get_size();
361+
if dst.len() < size {
362+
return Err(Error::WriteError(size, dst.len()));
363+
}
356364
let header = self.get_header();
357365
dst[0..HEADERSIZE].copy_from_slice(&header[..HEADERSIZE]);
358366
match self {
@@ -365,6 +373,7 @@ where
365373
dst[HEADERSIZE..].copy_from_slice(data);
366374
}
367375
}
376+
Ok(size)
368377
}
369378

370379
#[cfg(not(feature = "no_std"))]

sv2/binary-sv2/src/datatypes/non_copy_data_types/seq_inner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ macro_rules! impl_codec_for_sequence {
306306
}
307307
let (head, t) = tail.split_at_mut(element_size);
308308
tail = t;
309-
inner.push(T::from_bytes_unchecked(head));
309+
inner.push(T::from_bytes_(head)?);
310310
}
311311
Ok(Self(inner, PhantomData))
312312
}

0 commit comments

Comments
 (0)