Skip to content

Commit

Permalink
For #24: respect endianness
Browse files Browse the repository at this point in the history
  • Loading branch information
dermesser committed May 21, 2022
1 parent ff6877a commit f80445a
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ maintained with the occasional fix for edge cases and depends on Tokio v0.2.

`FixedInt` casts integers to bytes by either copying the underlying memory or
performing a transmutation. The encoded values use machine endianness
(little-endian on x86).
(little-endian on x86, big-endian where applicable).

## VarInt

Expand Down
29 changes: 27 additions & 2 deletions src/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,37 @@ macro_rules! impl_fixedint {

fn encode_fixed(self, dst: &mut [u8]) {
assert_eq!(dst.len(), Self::REQUIRED_SPACE);
let encoded = unsafe { &*(&self as *const $t as *const [u8; $sz]) };

#[allow(unused_mut)]
let mut encoded = unsafe { &*(&self as *const $t as *const [u8; $sz]) };

#[cfg(target_endian = "big")]
{
let mut encoded_rev = [0 as u8; Self::REQUIRED_SPACE];
encoded_rev.copy_from_slice(encoded);
encoded_rev.reverse();
dst.clone_from_slice(&encoded_rev);
return;
}

dst.clone_from_slice(encoded);
}

fn decode_fixed(src: &[u8]) -> $t {
assert_eq!(src.len(), Self::REQUIRED_SPACE);
return unsafe { (src.as_ptr() as *const $t).read_unaligned() };
#[cfg(target_endian = "little")]
let src_fin = src;

#[cfg(target_endian = "big")]
let mut src_fin = [0 as u8; Self::REQUIRED_SPACE];

#[cfg(target_endian = "big")]
{
src_fin.copy_from_slice(src);
src_fin.reverse();
}

return unsafe { (src_fin.as_ptr() as *const $t).read_unaligned() };
}
}
};
Expand Down
15 changes: 15 additions & 0 deletions src/fixed_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,33 @@ mod tests {
#[test]
fn test_u32_enc() {
let result = (32 as u32).encode_fixed_vec();
#[cfg(target_endian = "big")]
assert_eq!(result, vec![0, 0, 0, 32]);
#[cfg(target_endian = "little")]
assert_eq!(result, vec![32, 0, 0, 0]);
}
#[test]
fn test_u16_enc() {
let result = (256 as u16).encode_fixed_vec();
#[cfg(target_endian = "big")]
assert_eq!(result, vec![1, 0]);
#[cfg(target_endian = "little")]
assert_eq!(result, vec![0, 1]);
}
#[test]
fn test_i16_enc() {
let result = (-32768 as i16).encode_fixed_vec();
#[cfg(target_endian = "big")]
assert_eq!(result, vec![128, 0]);
#[cfg(target_endian = "little")]
assert_eq!(result, vec![0, 128]);
}
#[test]
fn test_i32_enc() {
let result = (-32767 as i32).encode_fixed_vec();
#[cfg(target_endian = "big")]
assert_eq!(result, vec![255, 255, 128, 1]);
#[cfg(target_endian = "little")]
assert_eq!(result, vec![1, 128, 255, 255]);
}

Expand All @@ -45,6 +57,9 @@ mod tests {
fn test_i32_enc_light() {
let int = -32767 as i32;
let result = int.encode_fixed_light();
#[cfg(target_endian = "big")]
assert_eq!(result, &[255, 255, 128, 1]);
#[cfg(target_endian = "little")]
assert_eq!(result, &[1, 128, 255, 255]);
}
#[test]
Expand Down
7 changes: 5 additions & 2 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::fixed::FixedInt;
use crate::varint::{VarInt, VarIntMaxSize, MSB};

#[cfg(feature = "tokio_async")]
use tokio::io::{AsyncReadExt, AsyncRead};
use tokio::io::{AsyncRead, AsyncReadExt};

#[cfg(feature = "futures_async")]
use futures_util::{io::AsyncRead, io::AsyncReadExt};
Expand Down Expand Up @@ -40,7 +40,10 @@ pub struct VarIntProcessor {

impl VarIntProcessor {
fn new<VI: VarIntMaxSize>() -> VarIntProcessor {
VarIntProcessor { maxsize: VI::varint_max_size(), ..VarIntProcessor::default() }
VarIntProcessor {
maxsize: VI::varint_max_size(),
..VarIntProcessor::default()
}
}
fn push(&mut self, b: u8) -> Result<()> {
if self.i >= self.maxsize {
Expand Down
2 changes: 1 addition & 1 deletion src/varint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub(crate) trait VarIntMaxSize {

impl<VI: VarInt> VarIntMaxSize for VI {
fn varint_max_size() -> usize {
(size_of::<VI>()*8+7)/7
(size_of::<VI>() * 8 + 7) / 7
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/varint_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ mod tests {
#[test]
fn test_regression_22() {
let mut encoded: Vec<u8> = (0x112233 as u64).encode_var_vec();
assert_eq!(encoded.as_slice().read_varint::<i8>().unwrap_err().kind(), std::io::ErrorKind::InvalidData);
assert_eq!(
encoded.as_slice().read_varint::<i8>().unwrap_err().kind(),
std::io::ErrorKind::InvalidData
);
}
}

0 comments on commit f80445a

Please sign in to comment.