Skip to content

Commit f6e00a5

Browse files
committed
Revise API for fixed integer coding
1 parent 60d869e commit f6e00a5

2 files changed

Lines changed: 54 additions & 30 deletions

File tree

src/fixed.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
11
use std::convert::TryInto;
22
use std::mem::size_of;
33

4-
/// `FixedInt` provides encoding/decoding to and from fixed int representations.
4+
/// `FixedInt` provides encoding/decoding to and from fixed int representations. Note that current
5+
/// Rust versions already provide this functionality via the `to_le_bytes()` and `to_be_bytes()`
6+
/// methods.
57
///
68
/// The emitted bytestring contains the bytes of the integer in machine endianness.
79
pub trait FixedInt: Sized + Copy {
810
type Bytes: AsRef<[u8]>;
11+
const ENCODED_SIZE: usize = size_of::<Self>();
912

10-
/// Encode a value into the given slice. `dst` must be exactly `REQUIRED_SPACE` bytes.
11-
fn encode_fixed(self, dst: &mut [u8]);
12-
/// Decode a value from the given slice. `src` must be exactly `REQUIRED_SPACE` bytes.
13-
fn decode_fixed(src: &[u8]) -> Self;
13+
/// Encode a value into the given slice using machine endianness. Returns `None` if `dst`
14+
/// doesn't provide enough space to encode this integer.
15+
fn encode_fixed(self, dst: &mut [u8]) -> Option<()>;
1416
/// Returns the representation of [`FixedInt`] as [`Bytes`], the little-endian representation
1517
/// of self in the stack.
1618
fn encode_fixed_light(self) -> Self::Bytes;
1719

20+
/// Decode a value from the given slice assuming little-endian.
21+
fn decode_le_fixed(src: &[u8]) -> Option<Self>;
22+
/// Decode a value from the given slice assuming big-endian.
23+
fn decode_be_fixed(src: &[u8]) -> Option<Self>;
24+
1825
/// Helper: Encode the value and return a Vec.
1926
fn encode_fixed_vec(self) -> Vec<u8> {
2027
self.encode_fixed_light().as_ref().to_vec()
2128
}
2229

23-
/// Helper: Decode the value from the Vec.
24-
fn decode_fixed_vec(v: &Vec<u8>) -> Self {
25-
Self::decode_fixed(&v[..])
26-
}
27-
2830
/// integer-encoding-rs always emits and receives little-endian integers (converting implicitly
2931
/// on big-endian machines). If you receive a big-endian integer, and would like it to be
3032
/// treated correctly, use this helper method to convert between endiannesses.
@@ -36,23 +38,33 @@ macro_rules! impl_fixedint {
3638
impl FixedInt for $t {
3739
type Bytes = [u8; size_of::<$t>()];
3840

39-
fn encode_fixed_light(self) -> Self::Bytes {
40-
self.to_le_bytes()
41+
fn encode_fixed(self, dst: &mut [u8]) -> Option<()> {
42+
if dst.len() == size_of::<Self>() {
43+
dst.clone_from_slice(&self.to_le_bytes());
44+
Some(())
45+
} else {
46+
None
47+
}
4148
}
4249

43-
fn encode_fixed(self, dst: &mut [u8]) {
44-
assert_eq!(dst.len(), size_of::<Self>());
45-
dst.clone_from_slice(&self.to_le_bytes());
50+
fn encode_fixed_light(self) -> Self::Bytes {
51+
self.to_le_bytes()
4652
}
4753

48-
#[cfg(target_endian = "little")]
49-
fn decode_fixed(src: &[u8]) -> Self {
50-
Self::from_le_bytes(src.try_into().unwrap())
54+
fn decode_le_fixed(src: &[u8]) -> Option<Self> {
55+
if src.len() == size_of::<Self>() {
56+
Some(Self::from_le_bytes(src.try_into().unwrap()))
57+
} else {
58+
None
59+
}
5160
}
5261

53-
#[cfg(target_endian = "big")]
54-
fn decode_fixed(src: &[u8]) -> $t {
55-
Self::from_be_bytes(src.try_into().unwrap())
62+
fn decode_be_fixed(src: &[u8]) -> Option<Self> {
63+
if src.len() == size_of::<Self>() {
64+
Some(Self::from_be_bytes(src.try_into().unwrap()))
65+
} else {
66+
None
67+
}
5668
}
5769

5870
fn switch_endianness(self) -> Self {

src/reader.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,35 +115,47 @@ impl<R: Read> VarIntReader for R {
115115
}
116116

117117
/// A trait for reading FixedInts from any other `Reader`.
118+
///
119+
/// On EOF, an io::Error with io::ErrorKind::UnexpectedEof is returned.
118120
pub trait FixedIntReader {
119-
/// Read a fixed integer from a reader. How many bytes are read depends on `FI`.
120-
///
121-
/// On EOF, an io::Error with io::ErrorKind::UnexpectedEof is returned.
122-
fn read_fixedint<FI: FixedInt>(&mut self) -> Result<FI>;
121+
fn read_le_fixedint<FI: FixedInt>(&mut self) -> Result<FI>;
122+
fn read_be_fixedint<FI: FixedInt>(&mut self) -> Result<FI>;
123123
}
124124

125125
/// Like FixedIntReader, but returns a future.
126126
#[cfg(any(feature = "tokio_async", feature = "futures_async"))]
127127
#[async_trait::async_trait]
128128
pub trait FixedIntAsyncReader {
129-
async fn read_fixedint_async<FI: FixedInt>(&mut self) -> Result<FI>;
129+
async fn read_le_fixedint_async<FI: FixedInt>(&mut self) -> Result<FI>;
130+
async fn read_be_fixedint_async<FI: FixedInt>(&mut self) -> Result<FI>;
130131
}
131132

132133
#[cfg(any(feature = "tokio_async", feature = "futures_async"))]
133134
#[async_trait::async_trait]
134135
impl<AR: AsyncRead + Unpin + Send> FixedIntAsyncReader for AR {
135-
async fn read_fixedint_async<FI: FixedInt>(&mut self) -> Result<FI> {
136+
async fn read_le_fixedint_async<FI: FixedInt>(&mut self) -> Result<FI> {
137+
let mut buf = [0 as u8; 8];
138+
self.read_exact(&mut buf[0..std::mem::size_of::<FI>()])
139+
.await?;
140+
Ok(FI::decode_le_fixed(&buf[0..std::mem::size_of::<FI>()]).unwrap())
141+
}
142+
async fn read_be_fixedint_async<FI: FixedInt>(&mut self) -> Result<FI> {
136143
let mut buf = [0 as u8; 8];
137144
self.read_exact(&mut buf[0..std::mem::size_of::<FI>()])
138145
.await?;
139-
Ok(FI::decode_fixed(&buf[0..std::mem::size_of::<FI>()]))
146+
Ok(FI::decode_be_fixed(&buf[0..std::mem::size_of::<FI>()]).unwrap())
140147
}
141148
}
142149

143150
impl<R: Read> FixedIntReader for R {
144-
fn read_fixedint<FI: FixedInt>(&mut self) -> Result<FI> {
151+
fn read_le_fixedint<FI: FixedInt>(&mut self) -> Result<FI> {
152+
let mut buf = [0 as u8; 8];
153+
self.read_exact(&mut buf[0..std::mem::size_of::<FI>()])?;
154+
Ok(FI::decode_le_fixed(&buf[0..std::mem::size_of::<FI>()]).unwrap())
155+
}
156+
fn read_be_fixedint<FI: FixedInt>(&mut self) -> Result<FI> {
145157
let mut buf = [0 as u8; 8];
146158
self.read_exact(&mut buf[0..std::mem::size_of::<FI>()])?;
147-
Ok(FI::decode_fixed(&buf[0..std::mem::size_of::<FI>()]))
159+
Ok(FI::decode_be_fixed(&buf[0..std::mem::size_of::<FI>()]).unwrap())
148160
}
149161
}

0 commit comments

Comments
 (0)