tokio-rs / bytes

Utilities for working with bytes
MIT License
1.87k stars 278 forks source link

`Buf::get_int()` implementation for `Bytes` returns positive number instead of negative when `nbytes` < 8. #730

Closed patrickhx closed 2 weeks ago

patrickhx commented 3 weeks ago

Steps to reproduce:

Run the following program, using bytes version 1.7.1

use bytes::{BytesMut, Buf, BufMut};

fn main() {
    const SOME_NEG_NUMBER: i64 = -42;
    let mut buffer = BytesMut::with_capacity(8);

    buffer.put_int(SOME_NEG_NUMBER, 1);
    println!("buffer = {:?}", &buffer);
    assert_eq!(buffer.freeze().get_int(1), SOME_NEG_NUMBER);
}

Expected outcome: Assertion passes and program terminates successfully, due to the symmetry of the put_int and get_int calls.

Actual outcome: Assertion fails:

buffer = b"\xd6"
thread 'main' panicked at src/main.rs:9:5:
assertion `left == right` failed
  left: 214
 right: -42
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Additional information:

  1. Only happens with negative numbers; positive numbers are always OK.
  2. Only happens when nbytes parameter is < 8.
  3. Other combos like put_i8()/get_i8() or put_i16()/get_i16() work as intended.
paolobarbolini commented 3 weeks ago

It looks like this has been caused by 234d814122d6445bdfb15f635290bfc4dd36c2eb / #280, as demonstrated by the revert:

See the revert ```patch From 4a9b9a4ea0538dff7d9ae57070c98f6ad4afd708 Mon Sep 17 00:00:00 2001 From: Paolo Barbolini Date: Mon, 19 Aug 2024 06:08:47 +0200 Subject: [PATCH] Revert "Remove byteorder dependency (#280)" This reverts commit 234d814122d6445bdfb15f635290bfc4dd36c2eb. --- Cargo.toml | 1 + src/buf/buf_impl.rs | 126 ++++++++++++++++++-------------------------- src/buf/buf_mut.rs | 119 +++++++++++++++++++++++++---------------- 3 files changed, 127 insertions(+), 119 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e072539..a49d681 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ std = [] [dependencies] serde = { version = "1.0.60", optional = true, default-features = false, features = ["alloc"] } +byteorder = "1.3" [dev-dependencies] serde_test = "1.0" diff --git a/src/buf/buf_impl.rs b/src/buf/buf_impl.rs index c44d4fb..5817f41 100644 --- a/src/buf/buf_impl.rs +++ b/src/buf/buf_impl.rs @@ -1,68 +1,46 @@ #[cfg(feature = "std")] use crate::buf::{reader, Reader}; use crate::buf::{take, Chain, Take}; +use crate::panic_advance; #[cfg(feature = "std")] use crate::{min_u64_usize, saturating_sub_usize_u64}; -use crate::{panic_advance, panic_does_not_fit}; #[cfg(feature = "std")] use std::io::IoSlice; use alloc::boxed::Box; -macro_rules! buf_get_impl { - ($this:ident, $typ:tt::$conv:tt) => {{ - const SIZE: usize = core::mem::size_of::<$typ>(); - - if $this.remaining() < SIZE { - panic_advance(SIZE, $this.remaining()); - } +use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian}; +macro_rules! buf_get_impl { + ($this:ident, $size:expr, $conv:path) => {{ // try to convert directly from the bytes - // this Option trick is to avoid keeping a borrow on self - // when advance() is called (mut borrow) and to call bytes() only once - let ret = $this - .chunk() - .get(..SIZE) - .map(|src| unsafe { $typ::$conv(*(src as *const _ as *const [_; SIZE])) }); - + let ret = { + // this Option trick is to avoid keeping a borrow on self + // when advance() is called (mut borrow) and to call bytes() only once + if let Some(src) = $this.chunk().get(..($size)) { + Some($conv(src)) + } else { + None + } + }; if let Some(ret) = ret { // if the direct conversion was possible, advance and return - $this.advance(SIZE); + $this.advance($size); return ret; } else { // if not we copy the bytes in a temp buffer then convert - let mut buf = [0; SIZE]; + let mut buf = [0; ($size)]; $this.copy_to_slice(&mut buf); // (do the advance) - return $typ::$conv(buf); + return $conv(&buf); } }}; - (le => $this:ident, $typ:tt, $len_to_read:expr) => {{ - const SIZE: usize = core::mem::size_of::<$typ>(); - + ($this:ident, $buf_size:expr, $conv:path, $len_to_read:expr) => {{ // The same trick as above does not improve the best case speed. // It seems to be linked to the way the method is optimised by the compiler - let mut buf = [0; SIZE]; - - let subslice = match buf.get_mut(..$len_to_read) { - Some(subslice) => subslice, - None => panic_does_not_fit(SIZE, $len_to_read), - }; - - $this.copy_to_slice(subslice); - return $typ::from_le_bytes(buf); - }}; - (be => $this:ident, $typ:tt, $len_to_read:expr) => {{ - const SIZE: usize = core::mem::size_of::<$typ>(); - - let slice_at = match SIZE.checked_sub($len_to_read) { - Some(slice_at) => slice_at, - None => panic_does_not_fit(SIZE, $len_to_read), - }; - - let mut buf = [0; SIZE]; - $this.copy_to_slice(&mut buf[slice_at..]); - return $typ::from_be_bytes(buf); + let mut buf = [0; ($buf_size)]; + $this.copy_to_slice(&mut buf[..($len_to_read)]); + return $conv(&buf[..($len_to_read)], $len_to_read); }}; } @@ -350,7 +328,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u16(&mut self) -> u16 { - buf_get_impl!(self, u16::from_be_bytes); + buf_get_impl!(self, 2, BigEndian::read_u16); } /// Gets an unsigned 16 bit integer from `self` in little-endian byte order. @@ -370,7 +348,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u16_le(&mut self) -> u16 { - buf_get_impl!(self, u16::from_le_bytes); + buf_get_impl!(self, 2, LittleEndian::read_u16); } /// Gets an unsigned 16 bit integer from `self` in native-endian byte order. @@ -393,7 +371,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u16_ne(&mut self) -> u16 { - buf_get_impl!(self, u16::from_ne_bytes); + buf_get_impl!(self, 2, NativeEndian::read_u16); } /// Gets a signed 16 bit integer from `self` in big-endian byte order. @@ -413,7 +391,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i16(&mut self) -> i16 { - buf_get_impl!(self, i16::from_be_bytes); + buf_get_impl!(self, 2, BigEndian::read_i16); } /// Gets a signed 16 bit integer from `self` in little-endian byte order. @@ -433,7 +411,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i16_le(&mut self) -> i16 { - buf_get_impl!(self, i16::from_le_bytes); + buf_get_impl!(self, 2, LittleEndian::read_i16); } /// Gets a signed 16 bit integer from `self` in native-endian byte order. @@ -456,7 +434,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i16_ne(&mut self) -> i16 { - buf_get_impl!(self, i16::from_ne_bytes); + buf_get_impl!(self, 2, NativeEndian::read_i16); } /// Gets an unsigned 32 bit integer from `self` in the big-endian byte order. @@ -476,7 +454,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u32(&mut self) -> u32 { - buf_get_impl!(self, u32::from_be_bytes); + buf_get_impl!(self, 4, BigEndian::read_u32); } /// Gets an unsigned 32 bit integer from `self` in the little-endian byte order. @@ -496,7 +474,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u32_le(&mut self) -> u32 { - buf_get_impl!(self, u32::from_le_bytes); + buf_get_impl!(self, 4, LittleEndian::read_u32); } /// Gets an unsigned 32 bit integer from `self` in native-endian byte order. @@ -519,7 +497,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u32_ne(&mut self) -> u32 { - buf_get_impl!(self, u32::from_ne_bytes); + buf_get_impl!(self, 4, NativeEndian::read_u32); } /// Gets a signed 32 bit integer from `self` in big-endian byte order. @@ -539,7 +517,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i32(&mut self) -> i32 { - buf_get_impl!(self, i32::from_be_bytes); + buf_get_impl!(self, 4, BigEndian::read_i32); } /// Gets a signed 32 bit integer from `self` in little-endian byte order. @@ -559,7 +537,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i32_le(&mut self) -> i32 { - buf_get_impl!(self, i32::from_le_bytes); + buf_get_impl!(self, 4, LittleEndian::read_i32); } /// Gets a signed 32 bit integer from `self` in native-endian byte order. @@ -582,7 +560,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i32_ne(&mut self) -> i32 { - buf_get_impl!(self, i32::from_ne_bytes); + buf_get_impl!(self, 4, NativeEndian::read_i32); } /// Gets an unsigned 64 bit integer from `self` in big-endian byte order. @@ -602,7 +580,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u64(&mut self) -> u64 { - buf_get_impl!(self, u64::from_be_bytes); + buf_get_impl!(self, 8, BigEndian::read_u64); } /// Gets an unsigned 64 bit integer from `self` in little-endian byte order. @@ -622,7 +600,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u64_le(&mut self) -> u64 { - buf_get_impl!(self, u64::from_le_bytes); + buf_get_impl!(self, 8, LittleEndian::read_u64); } /// Gets an unsigned 64 bit integer from `self` in native-endian byte order. @@ -645,7 +623,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u64_ne(&mut self) -> u64 { - buf_get_impl!(self, u64::from_ne_bytes); + buf_get_impl!(self, 8, NativeEndian::read_u64); } /// Gets a signed 64 bit integer from `self` in big-endian byte order. @@ -665,7 +643,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i64(&mut self) -> i64 { - buf_get_impl!(self, i64::from_be_bytes); + buf_get_impl!(self, 8, BigEndian::read_i64); } /// Gets a signed 64 bit integer from `self` in little-endian byte order. @@ -685,7 +663,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i64_le(&mut self) -> i64 { - buf_get_impl!(self, i64::from_le_bytes); + buf_get_impl!(self, 8, LittleEndian::read_i64); } /// Gets a signed 64 bit integer from `self` in native-endian byte order. @@ -708,7 +686,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i64_ne(&mut self) -> i64 { - buf_get_impl!(self, i64::from_ne_bytes); + buf_get_impl!(self, 8, NativeEndian::read_i64); } /// Gets an unsigned 128 bit integer from `self` in big-endian byte order. @@ -728,7 +706,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u128(&mut self) -> u128 { - buf_get_impl!(self, u128::from_be_bytes); + buf_get_impl!(self, 16, BigEndian::read_u128); } /// Gets an unsigned 128 bit integer from `self` in little-endian byte order. @@ -748,7 +726,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u128_le(&mut self) -> u128 { - buf_get_impl!(self, u128::from_le_bytes); + buf_get_impl!(self, 16, LittleEndian::read_u128); } /// Gets an unsigned 128 bit integer from `self` in native-endian byte order. @@ -771,7 +749,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_u128_ne(&mut self) -> u128 { - buf_get_impl!(self, u128::from_ne_bytes); + buf_get_impl!(self, 16, NativeEndian::read_u128); } /// Gets a signed 128 bit integer from `self` in big-endian byte order. @@ -791,7 +769,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i128(&mut self) -> i128 { - buf_get_impl!(self, i128::from_be_bytes); + buf_get_impl!(self, 16, BigEndian::read_i128); } /// Gets a signed 128 bit integer from `self` in little-endian byte order. @@ -811,7 +789,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i128_le(&mut self) -> i128 { - buf_get_impl!(self, i128::from_le_bytes); + buf_get_impl!(self, 16, LittleEndian::read_i128); } /// Gets a signed 128 bit integer from `self` in native-endian byte order. @@ -834,7 +812,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_i128_ne(&mut self) -> i128 { - buf_get_impl!(self, i128::from_ne_bytes); + buf_get_impl!(self, 16, NativeEndian::read_i128); } /// Gets an unsigned n-byte integer from `self` in big-endian byte order. @@ -854,7 +832,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_uint(&mut self, nbytes: usize) -> u64 { - buf_get_impl!(be => self, u64, nbytes); + buf_get_impl!(self, 8, BigEndian::read_uint, nbytes); } /// Gets an unsigned n-byte integer from `self` in little-endian byte order. @@ -874,7 +852,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_uint_le(&mut self, nbytes: usize) -> u64 { - buf_get_impl!(le => self, u64, nbytes); + buf_get_impl!(self, 8, LittleEndian::read_uint, nbytes); } /// Gets an unsigned n-byte integer from `self` in native-endian byte order. @@ -923,7 +901,7 @@ pub trait Buf { /// This function panics if there is not enough remaining data in `self`, or /// if `nbytes` is greater than 8. fn get_int(&mut self, nbytes: usize) -> i64 { - buf_get_impl!(be => self, i64, nbytes); + buf_get_impl!(self, 8, BigEndian::read_int, nbytes); } /// Gets a signed n-byte integer from `self` in little-endian byte order. @@ -944,7 +922,7 @@ pub trait Buf { /// This function panics if there is not enough remaining data in `self`, or /// if `nbytes` is greater than 8. fn get_int_le(&mut self, nbytes: usize) -> i64 { - buf_get_impl!(le => self, i64, nbytes); + buf_get_impl!(self, 8, LittleEndian::read_int, nbytes); } /// Gets a signed n-byte integer from `self` in native-endian byte order. @@ -993,7 +971,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_f32(&mut self) -> f32 { - f32::from_bits(self.get_u32()) + buf_get_impl!(self, 4, BigEndian::read_f32); } /// Gets an IEEE754 single-precision (4 bytes) floating point number from @@ -1038,7 +1016,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_f32_ne(&mut self) -> f32 { - f32::from_bits(self.get_u32_ne()) + buf_get_impl!(self, 4, LittleEndian::read_f32); } /// Gets an IEEE754 double-precision (8 bytes) floating point number from @@ -1059,7 +1037,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_f64(&mut self) -> f64 { - f64::from_bits(self.get_u64()) + buf_get_impl!(self, 8, BigEndian::read_f64); } /// Gets an IEEE754 double-precision (8 bytes) floating point number from @@ -1080,7 +1058,7 @@ pub trait Buf { /// /// This function panics if there is not enough remaining data in `self`. fn get_f64_le(&mut self) -> f64 { - f64::from_bits(self.get_u64_le()) + buf_get_impl!(self, 8, LittleEndian::read_f64); } /// Gets an IEEE754 double-precision (8 bytes) floating point number from diff --git a/src/buf/buf_mut.rs b/src/buf/buf_mut.rs index e13278d..73baa1e 100644 --- a/src/buf/buf_mut.rs +++ b/src/buf/buf_mut.rs @@ -3,9 +3,10 @@ use crate::buf::{limit, Chain, Limit, UninitSlice}; use crate::buf::{writer, Writer}; use crate::{panic_advance, panic_does_not_fit}; -use core::{mem, ptr, usize}; +use core::{ptr, usize}; use alloc::{boxed::Box, vec::Vec}; +use byteorder::{BigEndian, ByteOrder, LittleEndian}; /// A trait for values that provide sequential write access to bytes. /// @@ -367,7 +368,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u16(&mut self, n: u16) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 2]; + BigEndian::write_u16(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 16 bit integer to `self` in little-endian byte order. @@ -390,7 +393,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u16_le(&mut self, n: u16) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 2]; + LittleEndian::write_u16(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 16 bit integer to `self` in native-endian byte order. @@ -440,7 +445,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i16(&mut self, n: i16) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 2]; + BigEndian::write_i16(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 16 bit integer to `self` in little-endian byte order. @@ -463,7 +470,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i16_le(&mut self, n: i16) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 2]; + LittleEndian::write_i16(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 16 bit integer to `self` in native-endian byte order. @@ -513,7 +522,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u32(&mut self, n: u32) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 4]; + BigEndian::write_u32(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 32 bit integer to `self` in little-endian byte order. @@ -536,7 +547,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u32_le(&mut self, n: u32) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 4]; + LittleEndian::write_u32(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 32 bit integer to `self` in native-endian byte order. @@ -586,7 +599,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i32(&mut self, n: i32) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 4]; + BigEndian::write_i32(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 32 bit integer to `self` in little-endian byte order. @@ -609,7 +624,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i32_le(&mut self, n: i32) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 4]; + LittleEndian::write_i32(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 32 bit integer to `self` in native-endian byte order. @@ -659,7 +676,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u64(&mut self, n: u64) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 8]; + BigEndian::write_u64(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 64 bit integer to `self` in little-endian byte order. @@ -682,7 +701,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u64_le(&mut self, n: u64) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 8]; + LittleEndian::write_u64(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 64 bit integer to `self` in native-endian byte order. @@ -732,7 +753,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i64(&mut self, n: i64) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 8]; + BigEndian::write_i64(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 64 bit integer to `self` in little-endian byte order. @@ -755,7 +778,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i64_le(&mut self, n: i64) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 8]; + LittleEndian::write_i64(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 64 bit integer to `self` in native-endian byte order. @@ -805,7 +830,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u128(&mut self, n: u128) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 16]; + BigEndian::write_u128(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 128 bit integer to `self` in little-endian byte order. @@ -828,7 +855,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_u128_le(&mut self, n: u128) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 16]; + LittleEndian::write_u128(&mut buf, n); + self.put_slice(&buf) } /// Writes an unsigned 128 bit integer to `self` in native-endian byte order. @@ -878,7 +907,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i128(&mut self, n: i128) { - self.put_slice(&n.to_be_bytes()) + let mut buf = [0; 16]; + BigEndian::write_i128(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 128 bit integer to `self` in little-endian byte order. @@ -901,7 +932,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_i128_le(&mut self, n: i128) { - self.put_slice(&n.to_le_bytes()) + let mut buf = [0; 16]; + LittleEndian::write_i128(&mut buf, n); + self.put_slice(&buf) } /// Writes a signed 128 bit integer to `self` in native-endian byte order. @@ -951,12 +984,9 @@ pub unsafe trait BufMut { /// `self` or if `nbytes` is greater than 8. #[inline] fn put_uint(&mut self, n: u64, nbytes: usize) { - let start = match mem::size_of_val(&n).checked_sub(nbytes) { - Some(start) => start, - None => panic_does_not_fit(nbytes, mem::size_of_val(&n)), - }; - - self.put_slice(&n.to_be_bytes()[start..]); + let mut buf = [0; 8]; + BigEndian::write_uint(&mut buf, n, nbytes); + self.put_slice(&buf[0..nbytes]) } /// Writes an unsigned n-byte integer to `self` in the little-endian byte order. @@ -979,13 +1009,9 @@ pub unsafe trait BufMut { /// `self` or if `nbytes` is greater than 8. #[inline] fn put_uint_le(&mut self, n: u64, nbytes: usize) { - let slice = n.to_le_bytes(); - let slice = match slice.get(..nbytes) { - Some(slice) => slice, - None => panic_does_not_fit(nbytes, slice.len()), - }; - - self.put_slice(slice); + let mut buf = [0; 8]; + LittleEndian::write_uint(&mut buf, n, nbytes); + self.put_slice(&buf[0..nbytes]) } /// Writes an unsigned n-byte integer to `self` in the native-endian byte order. @@ -1039,12 +1065,9 @@ pub unsafe trait BufMut { /// `self` or if `nbytes` is greater than 8. #[inline] fn put_int(&mut self, n: i64, nbytes: usize) { - let start = match mem::size_of_val(&n).checked_sub(nbytes) { - Some(start) => start, - None => panic_does_not_fit(nbytes, mem::size_of_val(&n)), - }; - - self.put_slice(&n.to_be_bytes()[start..]); + let mut buf = [0; 8]; + BigEndian::write_int(&mut buf, n, nbytes); + self.put_slice(&buf[0..nbytes]) } /// Writes low `nbytes` of a signed integer to `self` in little-endian byte order. @@ -1100,11 +1123,9 @@ pub unsafe trait BufMut { /// `self` or if `nbytes` is greater than 8. #[inline] fn put_int_ne(&mut self, n: i64, nbytes: usize) { - if cfg!(target_endian = "big") { - self.put_int(n, nbytes) - } else { - self.put_int_le(n, nbytes) - } + let mut buf = [0; 8]; + LittleEndian::write_int(&mut buf, n, nbytes); + self.put_slice(&buf[0..nbytes]) } /// Writes an IEEE754 single-precision (4 bytes) floating point number to @@ -1128,7 +1149,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_f32(&mut self, n: f32) { - self.put_u32(n.to_bits()); + let mut buf = [0; 4]; + BigEndian::write_f32(&mut buf, n); + self.put_slice(&buf) } /// Writes an IEEE754 single-precision (4 bytes) floating point number to @@ -1152,7 +1175,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_f32_le(&mut self, n: f32) { - self.put_u32_le(n.to_bits()); + let mut buf = [0; 4]; + LittleEndian::write_f32(&mut buf, n); + self.put_slice(&buf) } /// Writes an IEEE754 single-precision (4 bytes) floating point number to @@ -1204,7 +1229,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_f64(&mut self, n: f64) { - self.put_u64(n.to_bits()); + let mut buf = [0; 8]; + BigEndian::write_f64(&mut buf, n); + self.put_slice(&buf) } /// Writes an IEEE754 double-precision (8 bytes) floating point number to @@ -1228,7 +1255,9 @@ pub unsafe trait BufMut { /// `self`. #[inline] fn put_f64_le(&mut self, n: f64) { - self.put_u64_le(n.to_bits()); + let mut buf = [0; 8]; + LittleEndian::write_f64(&mut buf, n); + self.put_slice(&buf) } /// Writes an IEEE754 double-precision (8 bytes) floating point number to -- 2.46.0 ```
Darksonn commented 3 weeks ago

Thank you, we should fix this. Anyone willing to submit a PR?

paolobarbolini commented 3 weeks ago

I'm looking into it

paolobarbolini commented 3 weeks ago

Should be fixed in #732