From 632edbfe0c2c1b053fd4d4f26079a2c815215df0 Mon Sep 17 00:00:00 2001 From: nuskey8 Date: Fri, 24 Jul 2026 15:57:20 +0900 Subject: [PATCH 1/2] refacor: implement read/write operations using macros --- zerompk/src/lib.rs | 5 + zerompk/src/read.rs | 1163 +---------------------- zerompk/src/read_macro.rs | 651 +++++++++++++ zerompk/src/write.rs | 1781 +----------------------------------- zerompk/src/write_macro.rs | 345 +++++++ 5 files changed, 1087 insertions(+), 2858 deletions(-) create mode 100644 zerompk/src/read_macro.rs create mode 100644 zerompk/src/write_macro.rs diff --git a/zerompk/src/lib.rs b/zerompk/src/lib.rs index 1abd79b..81b974b 100644 --- a/zerompk/src/lib.rs +++ b/zerompk/src/lib.rs @@ -3,6 +3,11 @@ #[cfg(test)] extern crate self as zerompk; +#[macro_use] +mod read_macro; +#[macro_use] +mod write_macro; + #[cfg(feature = "std")] mod bufread; mod consts; diff --git a/zerompk/src/read.rs b/zerompk/src/read.rs index ae51002..9007a6f 100644 --- a/zerompk/src/read.rs +++ b/zerompk/src/read.rs @@ -294,487 +294,20 @@ impl<'de> Read<'de> for SliceReader<'de> { } } - #[inline(always)] - fn read_nil(&mut self) -> Result<()> { - let byte = self.peek_byte()?; - if byte == NIL_MARKER { - self.pos += 1; - Ok(()) - } else { + impl_read_methods! { + read_byte = |reader| reader.take_byte()?, + read_2 = |reader| *reader.take_array::<2>()?, + read_4 = |reader| *reader.take_array::<4>()?, + read_5 = |reader| *reader.take_array::<5>()?, + read_8 = |reader| *reader.take_array::<8>()?, + read_9 = |reader| *reader.take_array::<9>()?, + read_13 = |reader| *reader.take_array::<13>()?, + read_bytes = |reader, len| alloc::borrow::Cow::Borrowed(reader.take_slice(len)?), + invalid = |reader, marker| { cold_path(); - Err(Error::InvalidMarker(byte)) - } - } - - #[inline(always)] - fn read_boolean(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - FALSE_MARKER => Ok(false), - TRUE_MARKER => Ok(true), - _ => { - cold_path(); - self.pos -= 1; - invalid_marker(byte) - } - } - } - - #[inline(always)] - fn read_u8(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte), - // uint 8 - UINT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_u16(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as u16), - // uint 8 - UINT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as u16) - } - // uint 16 - UINT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(u16::from_be_bytes(*bytes)) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_u32(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as u32), - // uint 8 - UINT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as u32) - } - // uint 16 - UINT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(u16::from_be_bytes(*bytes) as u32) - } - // uint 32 - UINT32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(u32::from_be_bytes(*bytes)) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_u64(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as u64), - // uint 8 - UINT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as u64) - } - // uint 16 - UINT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(u16::from_be_bytes(*bytes) as u64) - } - // uint 32 - UINT32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(u32::from_be_bytes(*bytes) as u64) - } - // uint 64 - UINT64_MARKER => { - let bytes = self.take_array::<8>()?; - Ok(u64::from_be_bytes(*bytes)) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_i8(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i8), - // Negative FixInt - NEG_FIXINT_START..=NEG_FIXINT_END => Ok(byte as i8), - // int 8 - INT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as i8) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_i16(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i16), - // Negative FixInt - NEG_FIXINT_START..=NEG_FIXINT_END => Ok((byte as i8) as i16), - // int 8 - INT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as i8 as i16) - } - // int 16 - INT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(i16::from_be_bytes(*bytes)) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_i32(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i32), - // Negative FixInt - NEG_FIXINT_START..=NEG_FIXINT_END => Ok((byte as i8) as i32), - // int 8 - INT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as i8 as i32) - } - // int 16 - INT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(i16::from_be_bytes(*bytes) as i32) - } - // int 32 - INT32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(i32::from_be_bytes(*bytes)) - } - _ => { - cold_path(); - self.pos -= 1; - invalid_marker(byte) - } - } - } - - #[inline(always)] - fn read_i64(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // Positive FixInt - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i64), - // Negative FixInt - NEG_FIXINT_START..=NEG_FIXINT_END => Ok((byte as i8) as i64), - // int 8 - INT8_MARKER => { - let byte = self.take_byte()?; - Ok(byte as i8 as i64) - } - // int 16 - INT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(i16::from_be_bytes(*bytes) as i64) - } - // int 32 - INT32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(i32::from_be_bytes(*bytes) as i64) - } - // int 64 - INT64_MARKER => { - let bytes = self.take_array::<8>()?; - Ok(i64::from_be_bytes(*bytes)) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_f32(&mut self) -> Result { - let byte = self.peek_byte()?; - match byte { - // float 32 - 0xca => { - self.pos += 1; - let bytes = self.take_array::<4>()?; - Ok(f32::from_bits(u32::from_be_bytes(*bytes))) - } - _ => { - cold_path(); - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_f64(&mut self) -> Result { - let byte = self.peek_byte()?; - match byte { - // float 64 - 0xcb => { - self.pos += 1; - let bytes = self.take_array::<8>()?; - Ok(f64::from_bits(u64::from_be_bytes(*bytes))) - } - _ => { - cold_path(); - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_string(&mut self) -> Result> { - let byte = self.take_byte()?; - let len = match byte { - // fixstr - FIXSTR_START..=FIXSTR_END => (byte - FIXSTR_START) as usize, - // str 8 - STR8_MARKER => { - let byte = self.take_byte()?; - byte as usize - } - // str 16 - STR16_MARKER => { - let bytes = self.take_array::<2>()?; - u16::from_be_bytes(*bytes) as usize - } - // str 32 - STR32_MARKER => { - let bytes = self.take_array::<4>()?; - u32::from_be_bytes(*bytes) as usize - } - _ => { - cold_path(); - self.pos -= 1; - return Err(Error::InvalidMarker(byte)); - } - }; - let bytes = self.take_slice(len)?; - match core::str::from_utf8(bytes) { - Ok(s) => Ok(alloc::borrow::Cow::Borrowed(s)), - Err(err) => Err(Error::InvalidUtf8(err)), - } - } - - #[inline(always)] - fn read_string_bytes(&mut self) -> Result> { - let byte = self.take_byte()?; - let len = match byte { - // fixstr - FIXSTR_START..=FIXSTR_END => (byte - FIXSTR_START) as usize, - // str 8 - STR8_MARKER => { - let byte = self.take_byte()?; - byte as usize - } - // str 16 - STR16_MARKER => { - let bytes = self.take_array::<2>()?; - u16::from_be_bytes(*bytes) as usize - } - // str 32 - STR32_MARKER => { - let bytes = self.take_array::<4>()?; - u32::from_be_bytes(*bytes) as usize - } - _ => { - cold_path(); - self.pos -= 1; - return Err(Error::InvalidMarker(byte)); - } - }; - let bytes = self.take_slice(len)?; - Ok(alloc::borrow::Cow::Borrowed(bytes)) - } - - #[inline(always)] - fn read_binary(&mut self) -> Result> { - let byte = self.take_byte()?; - let len = match byte { - // bin 8 - BIN8_MARKER => { - let byte = self.take_byte()?; - byte as usize - } - // bin 16 - BIN16_MARKER => { - let bytes = self.take_array::<2>()?; - u16::from_be_bytes(*bytes) as usize - } - // bin 32 - BIN32_MARKER => { - let bytes = self.take_array::<4>()?; - u32::from_be_bytes(*bytes) as usize - } - _ => { - cold_path(); - self.pos -= 1; - return Err(Error::InvalidMarker(byte)); - } - }; - let bytes = self.take_slice(len)?; - Ok(alloc::borrow::Cow::Borrowed(bytes)) - } - - #[inline(always)] - fn read_timestamp(&mut self) -> Result<(i64, u32)> { - let byte = self.take_byte()?; - match byte { - // fixext 4 with type -1 - TIMESTAMP32_MARKER => { - let ext_info = self.take_array::<5>()?; - let [ext, tail @ ..] = *ext_info; - if ext as i8 != TIMESTAMP_EXT_TYPE { - return Err(Error::InvalidMarker(ext)); - } - - let seconds = u32::from_be_bytes(tail) as i64; - Ok((seconds, 0)) - } - // fixext 8 with type -1 - TIMESTAMP64_MARKER => { - let ext_info = self.take_array::<9>()?; - let [ext, tail @ ..] = *ext_info; - if ext as i8 != TIMESTAMP_EXT_TYPE { - return Err(Error::InvalidMarker(ext)); - } - - let data64 = u64::from_be_bytes(tail); - let nanoseconds = (data64 >> 34) as u32; - let seconds = (data64 & 0x0000_0003_ffff_ffff) as i64; - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - Ok((seconds, nanoseconds)) - } - // ext8(12) with type -1 - TIMESTAMP96_MARKER => { - let len = self.take_byte()? as usize; - if len != 12 { - return Err(Error::InvalidMarker(len as u8)); - } - - let ext_info = self.take_array::<13>()?; - let [ext, tail @ ..] = *ext_info; - if ext as i8 != TIMESTAMP_EXT_TYPE { - return Err(Error::InvalidMarker(ext)); - } - - // Instead of using pointers, use `try_into().unwrap()`. - // This is faster because it is properly optimized by the compiler. - let nanoseconds = u32::from_be_bytes(tail[0..4].try_into().unwrap()); - let seconds = i64::from_be_bytes(tail[4..12].try_into().unwrap()); - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - Ok((seconds, nanoseconds)) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_array_len(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // fixarray - FIXARRAY_START..=FIXARRAY_END => Ok((byte - FIXARRAY_START) as usize), - // array 16 - ARRAY16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(u16::from_be_bytes(*bytes) as usize) - } - // array 32 - ARRAY32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(u32::from_be_bytes(*bytes) as usize) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - - #[inline(always)] - fn read_map_len(&mut self) -> Result { - let byte = self.take_byte()?; - match byte { - // fixmap - FIXMAP_START..=FIXMAP_END => Ok((byte - FIXMAP_START) as usize), - // map 16 - MAP16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(u16::from_be_bytes(*bytes) as usize) - } - // map 32 - MAP32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(u32::from_be_bytes(*bytes) as usize) - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } + reader.pos -= 1; + invalid_marker(marker) + }, } #[inline(always)] @@ -795,51 +328,6 @@ impl<'de> Read<'de> for SliceReader<'de> { } } - #[inline(always)] - fn read_ext_len(&mut self) -> Result<(i8, usize)> { - let byte = self.take_byte()?; - let len = match byte { - // fixext 1 - FIXEXT1_MARKER => 1, - // fixext 2 - FIXEXT2_MARKER => 2, - // fixext 4 - FIXEXT4_MARKER => 4, - // fixext 8 - FIXEXT8_MARKER => 8, - // fixext 16 - FIXEXT16_MARKER => 16, - // ext 8 - EXT8_MARKER => { - let byte = self.take_byte()?; - byte as usize - } - // ext 16 - EXT16_MARKER => { - let bytes = self.take_array::<2>()?; - u16::from_be_bytes(*bytes) as usize - } - // ext 32 - EXT32_MARKER => { - let bytes = self.take_array::<4>()?; - u32::from_be_bytes(*bytes) as usize - } - _ => { - cold_path(); - self.pos -= 1; - return Err(Error::InvalidMarker(byte)); - } - }; - let ext_type = self.take_byte()? as i8; - Ok((ext_type, len)) - } - - #[inline(always)] - fn read_ext(&mut self) -> Result<(i8, alloc::borrow::Cow<'de, [u8]>)> { - let (type_id, len) = self.read_ext_len()?; - Ok((type_id, alloc::borrow::Cow::Borrowed(self.take_slice(len)?))) - } - #[inline(always)] fn read_array>(&mut self, out: &mut alloc::vec::Vec) -> Result<()> { out.clear(); @@ -876,86 +364,6 @@ impl<'de> Read<'de> for SliceReader<'de> { Ok(()) } - #[inline(always)] - fn read_option>(&mut self) -> Result> - where - Self: Sized, - { - let byte = self.peek_byte()?; - if byte == NIL_MARKER { - self.pos += 1; - Ok(None) - } else { - Ok(Some(T::read(self)?)) - } - } - - #[inline(always)] - fn read_tag(&mut self) -> Result> { - let byte = self.take_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(Tag::Int(byte as u64)), - UINT8_MARKER => { - let byte = self.take_byte()?; - Ok(Tag::Int(byte as u64)) - } - UINT16_MARKER => { - let bytes = self.take_array::<2>()?; - Ok(Tag::Int(u16::from_be_bytes(*bytes) as u64)) - } - UINT32_MARKER => { - let bytes = self.take_array::<4>()?; - Ok(Tag::Int(u32::from_be_bytes(*bytes) as u64)) - } - UINT64_MARKER => { - let bytes = self.take_array::<8>()?; - Ok(Tag::Int(u64::from_be_bytes(*bytes))) - } - FIXSTR_START..=FIXSTR_END => { - let len = (byte - FIXSTR_START) as usize; - let bytes = self.take_slice(len)?; - match core::str::from_utf8(bytes) { - Ok(s) => Ok(Tag::String(alloc::borrow::Cow::Borrowed(s))), - Err(err) => Err(Error::InvalidUtf8(err)), - } - } - STR8_MARKER => { - let byte = self.take_byte()?; - let len = byte as usize; - let bytes = self.take_slice(len)?; - match core::str::from_utf8(bytes) { - Ok(s) => Ok(Tag::String(alloc::borrow::Cow::Borrowed(s))), - Err(err) => Err(Error::InvalidUtf8(err)), - } - } - STR16_MARKER => { - let bytes = self.take_array::<2>()?; - let len = u16::from_be_bytes(*bytes) as usize; - - let bytes = self.take_slice(len)?; - match core::str::from_utf8(bytes) { - Ok(s) => Ok(Tag::String(alloc::borrow::Cow::Borrowed(s))), - Err(err) => Err(Error::InvalidUtf8(err)), - } - } - STR32_MARKER => { - let bytes = self.take_array::<4>()?; - let len = u32::from_be_bytes(*bytes) as usize; - - let bytes = self.take_slice(len)?; - match core::str::from_utf8(bytes) { - Ok(s) => Ok(Tag::String(alloc::borrow::Cow::Borrowed(s))), - Err(err) => Err(Error::InvalidUtf8(err)), - } - } - _ => { - cold_path(); - self.pos -= 1; - Err(Error::InvalidMarker(byte)) - } - } - } - fn skip_value(&mut self) -> Result<()> { self.increment_depth()?; let byte = self.peek_byte()?; @@ -1195,515 +603,42 @@ impl<'de, R: std::io::Read> Read<'de> for IOReader { } } - #[inline(always)] - fn read_nil(&mut self) -> Result<()> { - let byte = self.read_byte()?; - if byte == NIL_MARKER { - Ok(()) - } else { - Err(Error::InvalidMarker(byte)) - } - } - - #[inline(always)] - fn read_boolean(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - FALSE_MARKER => Ok(false), - TRUE_MARKER => Ok(true), - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_u8(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte), - UINT8_MARKER => { - let value = self.read_byte()?; - Ok(value) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_u16(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as u16), - UINT8_MARKER => { - let value = self.read_byte()?; - Ok(value as u16) - } - UINT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(u16::from_be_bytes(buf)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_u32(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as u32), - UINT8_MARKER => { - let value = self.read_byte()?; - Ok(value as u32) - } - UINT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(u16::from_be_bytes(buf) as u32) - } - UINT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(u32::from_be_bytes(buf)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_u64(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as u64), - UINT8_MARKER => { - let value = self.read_byte()?; - Ok(value as u64) - } - UINT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(u16::from_be_bytes(buf) as u64) - } - UINT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(u32::from_be_bytes(buf) as u64) - } - UINT64_MARKER => { - let mut buf = [0u8; 8]; - self.read_exact(&mut buf)?; - Ok(u64::from_be_bytes(buf)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_i8(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i8), - NEG_FIXINT_START..=NEG_FIXINT_END => Ok(byte as i8), - INT8_MARKER => { - let value = self.read_byte()?; - Ok(value as i8) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_i16(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i16), - NEG_FIXINT_START..=NEG_FIXINT_END => Ok((byte as i8) as i16), - INT8_MARKER => { - let value = self.read_byte()?; - Ok((value as i8) as i16) - } - INT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(i16::from_be_bytes(buf)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_i32(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i32), - NEG_FIXINT_START..=NEG_FIXINT_END => Ok((byte as i8) as i32), - INT8_MARKER => { - let value = self.read_byte()?; - Ok((value as i8) as i32) - } - INT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(i16::from_be_bytes(buf) as i32) - } - INT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(i32::from_be_bytes(buf)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_i64(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(byte as i64), - NEG_FIXINT_START..=NEG_FIXINT_END => Ok((byte as i8) as i64), - INT8_MARKER => { - let value = self.read_byte()?; - Ok((value as i8) as i64) - } - INT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(i16::from_be_bytes(buf) as i64) - } - INT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(i32::from_be_bytes(buf) as i64) - } - INT64_MARKER => { - let mut buf = [0u8; 8]; - self.read_exact(&mut buf)?; - Ok(i64::from_be_bytes(buf)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_f32(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - FLOAT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(f32::from_bits(u32::from_be_bytes(buf))) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_f64(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - FLOAT64_MARKER => { - let mut buf = [0u8; 8]; - self.read_exact(&mut buf)?; - Ok(f64::from_bits(u64::from_be_bytes(buf))) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_string(&mut self) -> Result> { - let mut buf = [0u8; 1]; - let byte = self.read_byte()?; - let len = match byte { - FIXSTR_START..=FIXSTR_END => (byte - FIXSTR_START) as usize, - STR8_MARKER => { - self.read_exact(&mut buf)?; - buf[0] as usize - } - STR16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - u16::from_be_bytes(buf) as usize - } - STR32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - u32::from_be_bytes(buf) as usize - } - _ => return Err(Error::InvalidMarker(byte)), - }; - - let str_buf = self.read_exact_vec(len)?; - - match alloc::string::String::from_utf8(str_buf) { - Ok(s) => Ok(alloc::borrow::Cow::Owned(s)), - Err(err) => Err(Error::InvalidUtf8(err.utf8_error())), - } - } - - #[inline(always)] - fn read_string_bytes(&mut self) -> Result> { - let mut buf = [0u8; 1]; - let byte = self.read_byte()?; - let len = match byte { - FIXSTR_START..=FIXSTR_END => (byte - FIXSTR_START) as usize, - STR8_MARKER => { - self.read_exact(&mut buf)?; - buf[0] as usize - } - STR16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - u16::from_be_bytes(buf) as usize - } - STR32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - u32::from_be_bytes(buf) as usize - } - _ => return Err(Error::InvalidMarker(byte)), - }; - - let str_buf = self.read_exact_vec(len)?; - Ok(alloc::borrow::Cow::Owned(str_buf)) - } - - #[inline(always)] - fn read_binary(&mut self) -> Result> { - let mut buf = [0u8; 1]; - let byte = self.read_byte()?; - let len = match byte { - BIN8_MARKER => { - self.read_exact(&mut buf)?; - buf[0] as usize - } - BIN16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - u16::from_be_bytes(buf) as usize - } - BIN32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - u32::from_be_bytes(buf) as usize - } - _ => return Err(Error::InvalidMarker(byte)), - }; - - let data_buf = self.read_exact_vec(len)?; - Ok(alloc::borrow::Cow::Owned(data_buf)) - } - - #[inline(always)] - fn read_timestamp(&mut self) -> Result<(i64, u32)> { - let byte = self.read_byte()?; - match byte { - TIMESTAMP32_MARKER => { - let mut ext_info = [0u8; 5]; - self.read_exact(&mut ext_info)?; - - let [ext, tail @ ..] = ext_info; - if ext != TIMESTAMP_EXT_TYPE as u8 { - return Err(Error::InvalidMarker(ext)); - } - let seconds = u32::from_be_bytes(tail) as i64; - Ok((seconds, 0)) - } - TIMESTAMP64_MARKER => { - let mut ext_info = [0u8; 9]; - self.read_exact(&mut ext_info)?; - - let [ext, tail @ ..] = ext_info; - if ext != -1i8 as u8 { - return Err(Error::InvalidMarker(ext)); - } - - let data64 = u64::from_be_bytes(tail); - let nanoseconds = (data64 >> 34) as u32; - let seconds = (data64 & 0x0000_0003_ffff_ffff) as i64; - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - Ok((seconds, nanoseconds)) - } - TIMESTAMP96_MARKER => { - let len = self.read_byte()? as usize; - if len != 12 { - return Err(Error::InvalidMarker(len as u8)); - } - - let mut ext_info = [0u8; 13]; - self.read_exact(&mut ext_info)?; - let [ext, tail @ ..] = ext_info; - if ext != TIMESTAMP_EXT_TYPE as u8 { - return Err(Error::InvalidMarker(ext)); - } - - // Instead of using pointers, use `try_into().unwrap()`. - // This is faster because it is properly optimized by the compiler. - let nanoseconds = u32::from_be_bytes(tail[0..4].try_into().unwrap()); - let seconds = i64::from_be_bytes(tail[4..12].try_into().unwrap()); - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - - Ok((seconds, nanoseconds)) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_array_len(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - FIXARRAY_START..=FIXARRAY_END => Ok((byte - FIXARRAY_START) as usize), - ARRAY16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(u16::from_be_bytes(buf) as usize) - } - ARRAY32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(u32::from_be_bytes(buf) as usize) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_map_len(&mut self) -> Result { - let byte = self.read_byte()?; - match byte { - FIXMAP_START..=FIXMAP_END => Ok((byte - FIXMAP_START) as usize), - MAP16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(u16::from_be_bytes(buf) as usize) - } - MAP32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(u32::from_be_bytes(buf) as usize) - } - _ => Err(Error::InvalidMarker(byte)), - } - } - - #[inline(always)] - fn read_ext_len(&mut self) -> Result<(i8, usize)> { - let mut buf = [0u8; 1]; - let byte = self.read_byte()?; - let len = match byte { - FIXEXT1_MARKER => 1, - FIXEXT2_MARKER => 2, - FIXEXT4_MARKER => 4, - FIXEXT8_MARKER => 8, - FIXEXT16_MARKER => 16, - EXT8_MARKER => { - self.read_exact(&mut buf)?; - buf[0] as usize - } - EXT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - u16::from_be_bytes(buf) as usize - } - EXT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - u32::from_be_bytes(buf) as usize - } - _ => return Err(Error::InvalidMarker(byte)), - }; - self.read_exact(&mut buf)?; - let ext_type = buf[0] as i8; - Ok((ext_type, len)) - } - - #[inline(always)] - fn read_ext(&mut self) -> Result<(i8, alloc::borrow::Cow<'de, [u8]>)> { - let (type_id, len) = self.read_ext_len()?; - Ok(( - type_id, - alloc::borrow::Cow::Owned(self.read_exact_vec(len)?), - )) - } - - #[inline(always)] - fn read_option>(&mut self) -> Result> { - let byte = self.read_byte()?; - if byte == NIL_MARKER { - Ok(None) - } else { - self.unread_byte(byte); - Ok(Some(T::read(self)?)) - } - } - - fn read_tag(&mut self) -> Result> { - let mut buf = [0u8; 1]; - let byte = self.read_byte()?; - match byte { - POS_FIXINT_START..=POS_FIXINT_END => Ok(Tag::Int(byte as u64)), - UINT8_MARKER => { - let value = self.read_byte()?; - Ok(Tag::Int(value as u64)) - } - UINT16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - Ok(Tag::Int(u16::from_be_bytes(buf) as u64)) - } - UINT32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - Ok(Tag::Int(u32::from_be_bytes(buf) as u64)) - } - UINT64_MARKER => { - let mut buf = [0u8; 8]; - self.read_exact(&mut buf)?; - Ok(Tag::Int(u64::from_be_bytes(buf))) - } - FIXSTR_START..=FIXSTR_END => { - let len = (byte - FIXSTR_START) as usize; - let str_buf = self.read_exact_vec(len)?; - match alloc::string::String::from_utf8(str_buf) { - Ok(s) => Ok(Tag::String(s.into())), - Err(err) => Err(Error::InvalidUtf8(err.utf8_error())), - } - } - STR8_MARKER => { - self.read_exact(&mut buf)?; - let len = buf[0] as usize; - let str_buf = self.read_exact_vec(len)?; - match alloc::string::String::from_utf8(str_buf) { - Ok(s) => Ok(Tag::String(s.into())), - Err(err) => Err(Error::InvalidUtf8(err.utf8_error())), - } - } - STR16_MARKER => { - let mut buf = [0u8; 2]; - self.read_exact(&mut buf)?; - let len = u16::from_be_bytes(buf) as usize; - let str_buf = self.read_exact_vec(len)?; - match alloc::string::String::from_utf8(str_buf) { - Ok(s) => Ok(Tag::String(s.into())), - Err(err) => Err(Error::InvalidUtf8(err.utf8_error())), - } - } - STR32_MARKER => { - let mut buf = [0u8; 4]; - self.read_exact(&mut buf)?; - let len = u32::from_be_bytes(buf) as usize; - let str_buf = self.read_exact_vec(len)?; - match alloc::string::String::from_utf8(str_buf) { - Ok(s) => Ok(Tag::String(s.into())), - Err(err) => Err(Error::InvalidUtf8(err.utf8_error())), - } - } - _ => Err(Error::InvalidMarker(byte)), - } + impl_read_methods! { + read_byte = |reader| reader.read_byte()?, + read_2 = |reader| { + let mut bytes = [0; 2]; + reader.read_exact(&mut bytes)?; + bytes + }, + read_4 = |reader| { + let mut bytes = [0; 4]; + reader.read_exact(&mut bytes)?; + bytes + }, + read_5 = |reader| { + let mut bytes = [0; 5]; + reader.read_exact(&mut bytes)?; + bytes + }, + read_8 = |reader| { + let mut bytes = [0; 8]; + reader.read_exact(&mut bytes)?; + bytes + }, + read_9 = |reader| { + let mut bytes = [0; 9]; + reader.read_exact(&mut bytes)?; + bytes + }, + read_13 = |reader| { + let mut bytes = [0; 13]; + reader.read_exact(&mut bytes)?; + bytes + }, + read_bytes = |reader, len| { + alloc::borrow::Cow::Owned(reader.read_exact_vec(len)?) + }, + invalid = |_reader, marker| Err(Error::InvalidMarker(marker)), } fn skip_value(&mut self) -> Result<()> { diff --git a/zerompk/src/read_macro.rs b/zerompk/src/read_macro.rs new file mode 100644 index 0000000..aba3c31 --- /dev/null +++ b/zerompk/src/read_macro.rs @@ -0,0 +1,651 @@ +macro_rules! impl_read_methods { + ( + read_byte = |$byte_reader:ident| $read_byte:expr, + read_2 = |$reader_2:ident| $read_2:expr, + read_4 = |$reader_4:ident| $read_4:expr, + read_5 = |$reader_5:ident| $read_5:expr, + read_8 = |$reader_8:ident| $read_8:expr, + read_9 = |$reader_9:ident| $read_9:expr, + read_13 = |$reader_13:ident| $read_13:expr, + read_bytes = |$bytes_reader:ident, $bytes_len:ident| $read_bytes:expr, + invalid = |$reader:ident, $bad_marker:ident| $invalid:expr $(,)? + ) => { + #[inline(always)] + fn read_nil(&mut self) -> Result<()> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + if marker == NIL_MARKER { + Ok(()) + } else { + { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_boolean(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + FALSE_MARKER => Ok(false), + TRUE_MARKER => Ok(true), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_f32(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + if marker == FLOAT32_MARKER { + Ok(f32::from_bits(u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }))) + } else { + { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_f64(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + if marker == FLOAT64_MARKER { + Ok(f64::from_bits(u64::from_be_bytes({ + let $reader_8 = &mut *self; + $read_8 + }))) + } else { + { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_array_len(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + FIXARRAY_START..=FIXARRAY_END => Ok((marker - FIXARRAY_START) as usize), + ARRAY16_MARKER => Ok(u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize), + ARRAY32_MARKER => Ok(u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_map_len(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + FIXMAP_START..=FIXMAP_END => Ok((marker - FIXMAP_START) as usize), + MAP16_MARKER => Ok(u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize), + MAP32_MARKER => Ok(u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_ext_len(&mut self) -> Result<(i8, usize)> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + let len = match marker { + FIXEXT1_MARKER => 1, + FIXEXT2_MARKER => 2, + FIXEXT4_MARKER => 4, + FIXEXT8_MARKER => 8, + FIXEXT16_MARKER => 16, + EXT8_MARKER => { + ({ + let $byte_reader = &mut *self; + $read_byte + }) as usize + } + EXT16_MARKER => u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize, + EXT32_MARKER => u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize, + _ => { + return { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + }; + Ok(( + { + let $byte_reader = &mut *self; + $read_byte + } as i8, + len, + )) + } + + #[inline(always)] + fn read_ext(&mut self) -> Result<(i8, alloc::borrow::Cow<'de, [u8]>)> { + let (type_id, len) = self.read_ext_len()?; + let bytes = { + let $bytes_reader = &mut *self; + let $bytes_len = len; + $read_bytes + }; + Ok((type_id, bytes)) + } + + #[inline(always)] + fn read_string(&mut self) -> Result> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + let len = match marker { + FIXSTR_START..=FIXSTR_END => (marker - FIXSTR_START) as usize, + STR8_MARKER => { + let $byte_reader = &mut *self; + $read_byte as usize + } + STR16_MARKER => u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize, + STR32_MARKER => u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize, + _ => { + return { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + }; + let bytes = { + let $bytes_reader = &mut *self; + let $bytes_len = len; + $read_bytes + }; + match bytes { + alloc::borrow::Cow::Borrowed(bytes) => core::str::from_utf8(bytes) + .map(alloc::borrow::Cow::Borrowed) + .map_err(Error::InvalidUtf8), + alloc::borrow::Cow::Owned(bytes) => alloc::string::String::from_utf8(bytes) + .map(alloc::borrow::Cow::Owned) + .map_err(|error| Error::InvalidUtf8(error.utf8_error())), + } + } + + #[inline(always)] + fn read_string_bytes(&mut self) -> Result> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + let len = match marker { + FIXSTR_START..=FIXSTR_END => (marker - FIXSTR_START) as usize, + STR8_MARKER => { + let $byte_reader = &mut *self; + $read_byte as usize + } + STR16_MARKER => u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize, + STR32_MARKER => u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize, + _ => { + return { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + }; + let bytes = { + let $bytes_reader = &mut *self; + let $bytes_len = len; + $read_bytes + }; + Ok(bytes) + } + + #[inline(always)] + fn read_binary(&mut self) -> Result> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + let len = match marker { + BIN8_MARKER => { + let $byte_reader = &mut *self; + $read_byte as usize + } + BIN16_MARKER => u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize, + BIN32_MARKER => u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize, + _ => { + return { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + }; + let bytes = { + let $bytes_reader = &mut *self; + let $bytes_len = len; + $read_bytes + }; + Ok(bytes) + } + + #[inline(always)] + fn read_option>(&mut self) -> Result> { + if self.peek_marker()? == NIL_MARKER { + self.read_nil()?; + Ok(None) + } else { + T::read(self).map(Some) + } + } + + #[inline(always)] + fn read_timestamp(&mut self) -> Result<(i64, u32)> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + TIMESTAMP32_MARKER => { + let [ext, tail @ ..] = { + let $reader_5 = &mut *self; + $read_5 + }; + if ext as i8 != TIMESTAMP_EXT_TYPE { + return Err(Error::InvalidMarker(ext)); + } + Ok((u32::from_be_bytes(tail) as i64, 0)) + } + TIMESTAMP64_MARKER => { + let [ext, tail @ ..] = { + let $reader_9 = &mut *self; + $read_9 + }; + if ext as i8 != TIMESTAMP_EXT_TYPE { + return Err(Error::InvalidMarker(ext)); + } + let data = u64::from_be_bytes(tail); + let nanoseconds = (data >> 34) as u32; + if nanoseconds >= 1_000_000_000 { + return Err(Error::InvalidTimestamp); + } + Ok(((data & 0x0000_0003_ffff_ffff) as i64, nanoseconds)) + } + TIMESTAMP96_MARKER => { + let len = { + let $byte_reader = &mut *self; + $read_byte + }; + if len != 12 { + return Err(Error::InvalidMarker(len)); + } + let [ext, tail @ ..] = { + let $reader_13 = &mut *self; + $read_13 + }; + if ext as i8 != TIMESTAMP_EXT_TYPE { + return Err(Error::InvalidMarker(ext)); + } + let nanoseconds = u32::from_be_bytes(tail[..4].try_into().unwrap()); + if nanoseconds >= 1_000_000_000 { + return Err(Error::InvalidTimestamp); + } + let seconds = i64::from_be_bytes(tail[4..].try_into().unwrap()); + Ok((seconds, nanoseconds)) + } + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_tag(&mut self) -> Result> { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(Tag::Int(marker as u64)), + UINT8_MARKER => Ok(Tag::Int({ + let $byte_reader = &mut *self; + $read_byte + } as u64)), + UINT16_MARKER => Ok(Tag::Int(u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as u64)), + UINT32_MARKER => Ok(Tag::Int(u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as u64)), + UINT64_MARKER => Ok(Tag::Int(u64::from_be_bytes({ + let $reader_8 = &mut *self; + $read_8 + }))), + FIXSTR_START..=FIXSTR_END | STR8_MARKER | STR16_MARKER | STR32_MARKER => { + let len = match marker { + FIXSTR_START..=FIXSTR_END => (marker - FIXSTR_START) as usize, + STR8_MARKER => { + let $byte_reader = &mut *self; + $read_byte as usize + } + STR16_MARKER => u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as usize, + STR32_MARKER => u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as usize, + _ => unreachable!(), + }; + let bytes = { + let $bytes_reader = &mut *self; + let $bytes_len = len; + $read_bytes + }; + match bytes { + alloc::borrow::Cow::Borrowed(bytes) => core::str::from_utf8(bytes) + .map(|value| Tag::String(alloc::borrow::Cow::Borrowed(value))) + .map_err(Error::InvalidUtf8), + alloc::borrow::Cow::Owned(bytes) => alloc::string::String::from_utf8(bytes) + .map(|value| Tag::String(alloc::borrow::Cow::Owned(value))) + .map_err(|error| Error::InvalidUtf8(error.utf8_error())), + } + } + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_u8(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker), + UINT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + }), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_u16(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker as u16), + UINT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as u16), + UINT16_MARKER => Ok(u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + })), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_u32(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker as u32), + UINT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as u32), + UINT16_MARKER => Ok(u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as u32), + UINT32_MARKER => Ok(u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + })), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_u64(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker as u64), + UINT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as u64), + UINT16_MARKER => Ok(u16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as u64), + UINT32_MARKER => Ok(u32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as u64), + UINT64_MARKER => Ok(u64::from_be_bytes({ + let $reader_8 = &mut *self; + $read_8 + })), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_i8(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END | NEG_FIXINT_START..=NEG_FIXINT_END => { + Ok(marker as i8) + } + INT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as i8), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_i16(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker as i16), + NEG_FIXINT_START..=NEG_FIXINT_END => Ok(marker as i8 as i16), + INT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as i8 as i16), + INT16_MARKER => Ok(i16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + })), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_i32(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker as i32), + NEG_FIXINT_START..=NEG_FIXINT_END => Ok(marker as i8 as i32), + INT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as i8 as i32), + INT16_MARKER => Ok(i16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as i32), + INT32_MARKER => Ok(i32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + })), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + + #[inline(always)] + fn read_i64(&mut self) -> Result { + let marker = { + let $byte_reader = &mut *self; + $read_byte + }; + match marker { + POS_FIXINT_START..=POS_FIXINT_END => Ok(marker as i64), + NEG_FIXINT_START..=NEG_FIXINT_END => Ok(marker as i8 as i64), + INT8_MARKER => Ok({ + let $byte_reader = &mut *self; + $read_byte + } as i8 as i64), + INT16_MARKER => Ok(i16::from_be_bytes({ + let $reader_2 = &mut *self; + $read_2 + }) as i64), + INT32_MARKER => Ok(i32::from_be_bytes({ + let $reader_4 = &mut *self; + $read_4 + }) as i64), + INT64_MARKER => Ok(i64::from_be_bytes({ + let $reader_8 = &mut *self; + $read_8 + })), + _ => { + let $reader = &mut *self; + let $bad_marker = marker; + $invalid + } + } + } + }; +} diff --git a/zerompk/src/write.rs b/zerompk/src/write.rs index 394a4cf..5c70891 100644 --- a/zerompk/src/write.rs +++ b/zerompk/src/write.rs @@ -93,18 +93,6 @@ impl<'a> SliceWriter<'a> { SliceWriter { buffer, pos: 0 } } - #[inline(always)] - fn take_array(&mut self) -> Result<&mut [u8; N]> { - if N > self.buffer.len() - self.pos { - cold_path(); - return Err(Error::BufferTooSmall); - } - let array: &mut [u8; N] = - unsafe { &mut *(self.buffer.as_mut_ptr().add(self.pos) as *mut [u8; N]) }; - self.pos += N; - Ok(array) - } - #[inline(always)] fn take_slice(&mut self, len: usize) -> Result<&mut [u8]> { if len > self.buffer.len() - self.pos { @@ -124,549 +112,22 @@ impl<'a> SliceWriter<'a> { } impl<'a> Write for SliceWriter<'a> { - #[inline(always)] - fn write_nil(&mut self) -> Result<()> { - let buf = self.take_array::<1>()?; - buf[0] = NIL_MARKER; - Ok(()) - } - - #[inline(always)] - fn write_boolean(&mut self, b: bool) -> Result<()> { - let buf = self.take_array::<1>()?; - buf[0] = if b { TRUE_MARKER } else { FALSE_MARKER }; - Ok(()) - } - - #[inline(always)] - fn write_u8(&mut self, u: u8) -> Result<()> { - if u <= POS_FIXINT_END { - let buf = self.take_array::<1>()?; - buf[0] = u; + impl_write_methods! { + write = |writer, data| { + writer.take_slice(data.len())?.copy_from_slice(data); Ok(()) - } else { - let buf = self.take_array::<2>()?; - *buf = [UINT8_MARKER, u]; + }, + write_parts = |writer, header, payload| { + let output = writer.take_slice(header.len() + payload.len())?; + let (output_header, output_payload) = output.split_at_mut(header.len()); + output_header.copy_from_slice(header); + output_payload.copy_from_slice(payload); Ok(()) - } - } - - #[inline(always)] - fn write_u16(&mut self, u: u16) -> Result<()> { - match u { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = u as u8; - Ok(()) - } - 128..=255 => { - let buf = self.take_array::<2>()?; - *buf = [UINT8_MARKER, u as u8]; - Ok(()) - } - _ => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = UINT16_MARKER; - *tail = u.to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_u32(&mut self, u: u32) -> Result<()> { - match u { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = u as u8; - Ok(()) - } - 128..=255 => { - let buf = self.take_array::<2>()?; - *buf = [UINT8_MARKER, u as u8]; - Ok(()) - } - 256..=65535 => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = UINT16_MARKER; - *tail = (u as u16).to_be_bytes(); - Ok(()) - } - _ => { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = UINT32_MARKER; - *tail = u.to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_u64(&mut self, u: u64) -> Result<()> { - match u { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = u as u8; - Ok(()) - } - 128..=255 => { - let buf = self.take_array::<2>()?; - *buf = [UINT8_MARKER, u as u8]; - Ok(()) - } - 256..=65535 => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = UINT16_MARKER; - *tail = (u as u16).to_be_bytes(); - Ok(()) - } - 65536..=4294967295 => { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = UINT32_MARKER; - *tail = (u as u32).to_be_bytes(); - Ok(()) - } - _ => { - let buf = self.take_array::<9>()?; - let [head, tail @ ..] = buf; - *head = UINT64_MARKER; - *tail = u.to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_i8(&mut self, i: i8) -> Result<()> { - match i { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = i as u8; - Ok(()) - } - -32..=-1 => { - let buf = self.take_array::<1>()?; - buf[0] = 0xe0 | ((i + 32) as u8); - Ok(()) - } - _ => { - let buf = self.take_array::<2>()?; - *buf = [INT8_MARKER, i as u8]; - Ok(()) - } - } - } - - #[inline(always)] - fn write_i16(&mut self, i: i16) -> Result<()> { - match i { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = i as u8; - Ok(()) - } - -32..=-1 => { - let buf = self.take_array::<1>()?; - buf[0] = 0xe0 | ((i + 32) as u8); - Ok(()) - } - -128..=127 => { - let buf = self.take_array::<2>()?; - *buf = [INT8_MARKER, i as u8]; - Ok(()) - } - _ => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = INT16_MARKER; - *tail = i.to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_i32(&mut self, i: i32) -> Result<()> { - match i { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = i as u8; - Ok(()) - } - -32..=-1 => { - let buf = self.take_array::<1>()?; - buf[0] = 0xe0 | ((i + 32) as u8); - Ok(()) - } - -128..=127 => { - let buf = self.take_array::<2>()?; - *buf = [INT8_MARKER, i as u8]; - Ok(()) - } - -32768..=32767 => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = INT16_MARKER; - *tail = (i as i16).to_be_bytes(); - Ok(()) - } - _ => { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = INT32_MARKER; - *tail = i.to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_i64(&mut self, i: i64) -> Result<()> { - match i { - 0..=127 => { - let buf = self.take_array::<1>()?; - buf[0] = i as u8; - Ok(()) - } - -32..=-1 => { - let buf = self.take_array::<1>()?; - buf[0] = 0xe0 | ((i + 32) as u8); - Ok(()) - } - -128..=127 => { - let buf = self.take_array::<2>()?; - *buf = [INT8_MARKER, i as u8]; - Ok(()) - } - -32768..=32767 => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = INT16_MARKER; - *tail = (i as i16).to_be_bytes(); - Ok(()) - } - -2147483648..=2147483647 => { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = INT32_MARKER; - *tail = (i as i32).to_be_bytes(); - Ok(()) - } - _ => { - let buf = self.take_array::<9>()?; - let [head, tail @ ..] = buf; - *head = INT64_MARKER; - *tail = i.to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_f32(&mut self, f: f32) -> Result<()> { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = FLOAT32_MARKER; - *tail = f.to_be_bytes(); - Ok(()) - } - - #[inline(always)] - fn write_f64(&mut self, f: f64) -> Result<()> { - let buf = self.take_array::<9>()?; - let [head, tail @ ..] = buf; - *head = FLOAT64_MARKER; - *tail = f.to_be_bytes(); - Ok(()) - } - - #[inline(always)] - fn write_string(&mut self, s: &str) -> Result<()> { - let len = s.len(); - match len { - // FixStr - 0..=31 => { - let buf = self.take_slice(1 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = 0xa0 | (len as u8); - core::ptr::copy_nonoverlapping(s.as_bytes().as_ptr(), ptr.add(1), len); - } - Ok(()) - } - // Str8 - 32..=255 => { - let buf = self.take_slice(2 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = STR8_MARKER; - *ptr.add(1) = len as u8; - core::ptr::copy_nonoverlapping(s.as_bytes().as_ptr(), ptr.add(2), len); - } - Ok(()) - } - // Str16 - 256..=65535 => { - let buf = self.take_slice(3 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = STR16_MARKER; - core::ptr::copy_nonoverlapping( - (len as u16).to_be_bytes().as_ptr(), - ptr.add(1), - 2, - ); - core::ptr::copy_nonoverlapping(s.as_bytes().as_ptr(), ptr.add(3), len); - } - Ok(()) - } - // Str32 - _ => { - let buf = self.take_slice(5 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = STR32_MARKER; - core::ptr::copy_nonoverlapping( - (len as u32).to_be_bytes().as_ptr(), - ptr.add(1), - 4, - ); - core::ptr::copy_nonoverlapping(s.as_bytes().as_ptr(), ptr.add(5), len); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_binary(&mut self, data: &[u8]) -> Result<()> { - let len = data.len(); - match len { - // Bin8 - 0..=255 => { - let buf = self.take_slice(2 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = BIN8_MARKER; - *ptr.add(1) = len as u8; - core::ptr::copy_nonoverlapping(data.as_ptr(), ptr.add(2), len); - } - Ok(()) - } - // Bin16 - 256..=65535 => { - let buf = self.take_slice(3 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = BIN16_MARKER; - core::ptr::copy_nonoverlapping( - (len as u16).to_be_bytes().as_ptr(), - ptr.add(1), - 2, - ); - core::ptr::copy_nonoverlapping(data.as_ptr(), ptr.add(3), len); - } - Ok(()) - } - // Bin32 - _ => { - let buf = self.take_slice(5 + len)?; - unsafe { - let ptr = buf.as_mut_ptr(); - *ptr = BIN32_MARKER; - core::ptr::copy_nonoverlapping( - (len as u32).to_be_bytes().as_ptr(), - ptr.add(1), - 4, - ); - core::ptr::copy_nonoverlapping(data.as_ptr(), ptr.add(5), len); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_timestamp(&mut self, seconds: i64, nanoseconds: u32) -> Result<()> { - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - - // timestamp 32: sec in [0, 2^32-1], nsec == 0 - if nanoseconds == 0 && (0..=u32::MAX as i64).contains(&seconds) { - let buf = self.take_array::<6>()?; - let [head, type_marker, tail @ ..] = buf; - *head = TIMESTAMP32_MARKER; - *type_marker = 0xff; - *tail = (seconds as u32).to_be_bytes(); - return Ok(()); - } - - // timestamp 64: sec in [0, 2^34-1] - if (0..=(1i64 << 34) - 1).contains(&seconds) { - let data = ((nanoseconds as u64) << 34) | (seconds as u64); - let buf = self.take_array::<10>()?; - let [head, type_marker, tail @ ..] = buf; - *head = TIMESTAMP64_MARKER; - *type_marker = 0xff; - *tail = data.to_be_bytes(); - return Ok(()); - } - - // timestamp 96 - let buf = self.take_array::<15>()?; - let [head, len_marker, type_marker, tail @ ..] = buf; - *head = TIMESTAMP96_MARKER; - *len_marker = 12; - *type_marker = 0xff; - unsafe { - let tail_ptr = tail.as_mut_ptr(); - core::ptr::copy_nonoverlapping(nanoseconds.to_be_bytes().as_ptr(), tail_ptr, 4); - core::ptr::copy_nonoverlapping(seconds.to_be_bytes().as_ptr(), tail_ptr.add(4), 8); - } - Ok(()) - } - - #[inline(always)] - fn write_array_len(&mut self, len: usize) -> Result<()> { - match len { - 0..=15 => { - let buf = self.take_array::<1>()?; - buf[0] = FIXARRAY_START | (len as u8); - Ok(()) - } - 16..=65535 => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = ARRAY16_MARKER; - *tail = (len as u16).to_be_bytes(); - Ok(()) - } - _ => { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = ARRAY32_MARKER; - *tail = (len as u32).to_be_bytes(); - Ok(()) - } - } - } - - #[inline(always)] - fn write_map_len(&mut self, len: usize) -> Result<()> { - match len { - 0..=15 => { - let buf = self.take_array::<1>()?; - buf[0] = FIXMAP_START | (len as u8); - Ok(()) - } - 16..=65535 => { - let buf = self.take_array::<3>()?; - let [head, tail @ ..] = buf; - *head = MAP16_MARKER; - *tail = (len as u16).to_be_bytes(); - Ok(()) - } - _ => { - let buf = self.take_array::<5>()?; - let [head, tail @ ..] = buf; - *head = MAP32_MARKER; - *tail = (len as u32).to_be_bytes(); - Ok(()) - } - } - } - - fn write_ext(&mut self, type_id: i8, data: &[u8]) -> Result<()> { - let len = data.len(); - match len { - 1 => { - let buf = self.take_array::<3>()?; - let [head, type_marker, tail] = buf; - *head = FIXEXT1_MARKER; - *type_marker = type_id as u8; - *tail = data[0]; - Ok(()) - } - 2 => { - let buf = self.take_array::<4>()?; - let [head, type_marker, tail @ ..] = buf; - *head = FIXEXT2_MARKER; - *type_marker = type_id as u8; - *tail = data.try_into().unwrap(); - Ok(()) - } - 4 => { - let buf = self.take_array::<6>()?; - let [head, type_marker, tail @ ..] = buf; - *head = FIXEXT4_MARKER; - *type_marker = type_id as u8; - *tail = data.try_into().unwrap(); - Ok(()) - } - 8 => { - let buf = self.take_array::<10>()?; - let [head, type_marker, tail @ ..] = buf; - *head = FIXEXT8_MARKER; - *type_marker = type_id as u8; - *tail = data.try_into().unwrap(); - Ok(()) - } - 16 => { - let buf = self.take_array::<18>()?; - let [head, type_marker, tail @ ..] = buf; - *head = FIXEXT16_MARKER; - *type_marker = type_id as u8; - *tail = data.try_into().unwrap(); - Ok(()) - } - 0..=255 => { - let buf = self.take_slice(3 + len)?; - unsafe { - let (header, body) = buf.split_at_mut(3); - header.copy_from_slice(&[EXT8_MARKER, len as u8, type_id as u8]); - core::ptr::copy_nonoverlapping(data.as_ptr(), body.as_mut_ptr(), len); - } - Ok(()) - } - 256..=65535 => { - let buf = self.take_slice(4 + len)?; - unsafe { - let (header, body) = buf.split_at_mut(4); - let len_bytes = (len as u16).to_be_bytes(); - header.copy_from_slice(&[ - EXT16_MARKER, - len_bytes[0], - len_bytes[1], - type_id as u8, - ]); - core::ptr::copy_nonoverlapping(data.as_ptr(), body.as_mut_ptr(), len); - } - Ok(()) - } - _ => { - let buf = self.take_slice(6 + len)?; - unsafe { - let (header, body) = buf.split_at_mut(6); - let len_bytes = (len as u32).to_be_bytes(); - header.copy_from_slice(&[ - EXT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - type_id as u8, - ]); - core::ptr::copy_nonoverlapping(data.as_ptr(), body.as_mut_ptr(), len); - } - Ok(()) - } - } + }, + write_container = |writer, header, _reserve| { + writer.take_slice(header.len())?.copy_from_slice(header); + Ok(()) + }, } } @@ -685,663 +146,22 @@ impl VecWriter { } impl Write for VecWriter { - #[inline(always)] - fn write_nil(&mut self) -> Result<()> { - self.buffer.push(NIL_MARKER); - Ok(()) - } - - #[inline(always)] - fn write_boolean(&mut self, b: bool) -> Result<()> { - self.buffer.push(if b { TRUE_MARKER } else { FALSE_MARKER }); - Ok(()) - } - - #[inline(always)] - fn write_u8(&mut self, u: u8) -> Result<()> { - if u <= POS_FIXINT_END { - self.buffer.push(u); - } else { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT8_MARKER; - *ptr.add(1) = u; - self.buffer.set_len(self.buffer.len() + 2); - } - } - Ok(()) - } - - #[inline(always)] - fn write_u16(&mut self, u: u16) -> Result<()> { - match u { - 0..=127 => { - self.buffer.push(u as u8); - Ok(()) - } - 128..=255 => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT8_MARKER; - *ptr.add(1) = u as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - _ => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(u.to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_u32(&mut self, u: u32) -> Result<()> { - match u { - 0..=127 => { - self.buffer.push(u as u8); - Ok(()) - } - 128..=255 => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT8_MARKER; - *ptr.add(1) = u as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - 256..=65535 => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((u as u16).to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - _ => { - self.buffer.reserve(5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(u.to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_u64(&mut self, u: u64) -> Result<()> { - match u { - 0..=127 => { - self.buffer.push(u as u8); - Ok(()) - } - 128..=255 => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT8_MARKER; - *ptr.add(1) = u as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - 256..=65535 => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((u as u16).to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - 65536..=4294967295 => { - self.buffer.reserve(5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((u as u32).to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - _ => { - self.buffer.reserve(9); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = UINT64_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(u.to_be_bytes().as_ptr(), 8); - self.buffer.set_len(self.buffer.len() + 9); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_i8(&mut self, i: i8) -> Result<()> { - match i { - 0..=127 => { - self.buffer.push(i as u8); - Ok(()) - } - -32..=-1 => { - self.buffer.push(0xe0 | ((i + 32) as u8)); - Ok(()) - } - _ => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT8_MARKER; - *ptr.add(1) = i as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_i16(&mut self, i: i16) -> Result<()> { - match i { - 0..=127 => { - self.buffer.push(i as u8); - Ok(()) - } - -32..=-1 => { - self.buffer.push(0xe0 | ((i + 32) as u8)); - Ok(()) - } - -128..=127 => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT8_MARKER; - *ptr.add(1) = i as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - _ => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(i.to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_i32(&mut self, i: i32) -> Result<()> { - match i { - 0..=127 => { - self.buffer.push(i as u8); - Ok(()) - } - -32..=-1 => { - self.buffer.push(0xe0 | ((i + 32) as u8)); - Ok(()) - } - -128..=127 => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT8_MARKER; - *ptr.add(1) = i as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - -32768..=32767 => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((i as i16).to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - _ => { - self.buffer.reserve(5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(i.to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_i64(&mut self, i: i64) -> Result<()> { - match i { - 0..=127 => { - self.buffer.push(i as u8); - Ok(()) - } - -32..=-1 => { - self.buffer.push(0xe0 | ((i + 32) as u8)); - Ok(()) - } - -128..=127 => { - self.buffer.reserve(2); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT8_MARKER; - *ptr.add(1) = i as u8; - self.buffer.set_len(self.buffer.len() + 2); - } - Ok(()) - } - -32768..=32767 => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((i as i16).to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - -2147483648..=2147483647 => { - self.buffer.reserve(5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((i as i32).to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - _ => { - self.buffer.reserve(9); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = INT64_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(i.to_be_bytes().as_ptr(), 8); - self.buffer.set_len(self.buffer.len() + 9); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_f32(&mut self, f: f32) -> Result<()> { - self.buffer.reserve(5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FLOAT32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(f.to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - - #[inline(always)] - fn write_f64(&mut self, f: f64) -> Result<()> { - self.buffer.reserve(9); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FLOAT64_MARKER; - ptr.add(1) - .copy_from_nonoverlapping(f.to_be_bytes().as_ptr(), 8); - self.buffer.set_len(self.buffer.len() + 9); - } - Ok(()) - } - - #[inline(always)] - fn write_string(&mut self, s: &str) -> Result<()> { - let len = s.len(); - match len { - 0..=31 => { - self.buffer.reserve(1 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = 0xa0 | (len as u8); - ptr.add(1) - .copy_from_nonoverlapping(s.as_bytes().as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 1 + len); - } - Ok(()) - } - 32..=255 => { - self.buffer.reserve(2 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = STR8_MARKER; - *ptr.add(1) = len as u8; - ptr.add(2) - .copy_from_nonoverlapping(s.as_bytes().as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 2 + len); - } - Ok(()) - } - 256..=65535 => { - self.buffer.reserve(3 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = STR16_MARKER; - let len_bytes = (len as u16).to_be_bytes(); - ptr.add(1).copy_from_nonoverlapping(len_bytes.as_ptr(), 2); - ptr.add(3) - .copy_from_nonoverlapping(s.as_bytes().as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 3 + len); - } - Ok(()) - } - _ => { - self.buffer.reserve(5 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = STR32_MARKER; - let len_bytes = (len as u32).to_be_bytes(); - ptr.add(1).copy_from_nonoverlapping(len_bytes.as_ptr(), 4); - ptr.add(5) - .copy_from_nonoverlapping(s.as_bytes().as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 5 + len); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_binary(&mut self, data: &[u8]) -> Result<()> { - let len = data.len(); - match len { - 0..=255 => { - self.buffer.reserve(2 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = BIN8_MARKER; - *ptr.add(1) = len as u8; - ptr.add(2).copy_from_nonoverlapping(data.as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 2 + len); - } - Ok(()) - } - 256..=65535 => { - self.buffer.reserve(3 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = BIN16_MARKER; - let len_bytes = (len as u16).to_be_bytes(); - ptr.add(1).copy_from_nonoverlapping(len_bytes.as_ptr(), 2); - ptr.add(3).copy_from_nonoverlapping(data.as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 3 + len); - } - Ok(()) - } - _ => { - self.buffer.reserve(5 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = BIN32_MARKER; - let len_bytes = (len as u32).to_be_bytes(); - ptr.add(1).copy_from_nonoverlapping(len_bytes.as_ptr(), 4); - ptr.add(5).copy_from_nonoverlapping(data.as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 5 + len); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_timestamp(&mut self, seconds: i64, nanoseconds: u32) -> Result<()> { - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - - // timestamp 32: sec in [0, 2^32-1], nsec == 0 - if nanoseconds == 0 && (0..=u32::MAX as i64).contains(&seconds) { - self.buffer.reserve(6); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = TIMESTAMP32_MARKER; - *ptr.add(1) = 0xff; - ptr.add(2) - .copy_from_nonoverlapping((seconds as u32).to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 6); - } - return Ok(()); - } - - // timestamp 64: sec in [0, 2^34-1] - if (0..=(1i64 << 34) - 1).contains(&seconds) { - let data = ((nanoseconds as u64) << 34) | (seconds as u64); - self.buffer.reserve(10); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = TIMESTAMP64_MARKER; - *ptr.add(1) = 0xff; - ptr.add(2) - .copy_from_nonoverlapping(data.to_be_bytes().as_ptr(), 8); - self.buffer.set_len(self.buffer.len() + 10); - } - return Ok(()); - } - - // timestamp 96 - self.buffer.reserve(15); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = TIMESTAMP96_MARKER; - *ptr.add(1) = 12; - *ptr.add(2) = 0xff; - ptr.add(3) - .copy_from_nonoverlapping(nanoseconds.to_be_bytes().as_ptr(), 4); - ptr.add(7) - .copy_from_nonoverlapping(seconds.to_be_bytes().as_ptr(), 8); - self.buffer.set_len(self.buffer.len() + 15); - } - Ok(()) - } - - #[inline(always)] - fn write_array_len(&mut self, len: usize) -> Result<()> { - match len { - 0..=15 => { - self.buffer.reserve(len + 1); - self.buffer.push(FIXARRAY_START | (len as u8)); - Ok(()) - } - 16..=65535 => { - self.buffer.reserve(len.min(MAX_CONTAINER_PREALLOC) + 3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = ARRAY16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((len as u16).to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - _ => { - self.buffer.reserve(len.min(MAX_CONTAINER_PREALLOC) + 5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = ARRAY32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((len as u32).to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_map_len(&mut self, len: usize) -> Result<()> { - match len { - 0..=15 => { - self.buffer.reserve(len * 2 + 1); - self.buffer.push(FIXMAP_START | (len as u8)); - Ok(()) - } - 16..=65535 => { - self.buffer - .reserve(len.saturating_mul(2).min(MAX_CONTAINER_PREALLOC) + 3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = MAP16_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((len as u16).to_be_bytes().as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - _ => { - self.buffer - .reserve(len.saturating_mul(2).min(MAX_CONTAINER_PREALLOC) + 5); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = MAP32_MARKER; - ptr.add(1) - .copy_from_nonoverlapping((len as u32).to_be_bytes().as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 5); - } - Ok(()) - } - } - } - - #[inline(always)] - fn write_ext(&mut self, type_id: i8, data: &[u8]) -> Result<()> { - let len = data.len(); - match len { - 1 => { - self.buffer.reserve(3); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FIXEXT1_MARKER; - *ptr.add(1) = type_id as u8; - *ptr.add(2) = data[0]; - self.buffer.set_len(self.buffer.len() + 3); - } - Ok(()) - } - 2 => { - self.buffer.reserve(4); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FIXEXT2_MARKER; - *ptr.add(1) = type_id as u8; - ptr.add(2).copy_from_nonoverlapping(data.as_ptr(), 2); - self.buffer.set_len(self.buffer.len() + 4); - } - Ok(()) - } - 4 => { - self.buffer.reserve(6); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FIXEXT4_MARKER; - *ptr.add(1) = type_id as u8; - ptr.add(2).copy_from_nonoverlapping(data.as_ptr(), 4); - self.buffer.set_len(self.buffer.len() + 6); - } - Ok(()) - } - 8 => { - self.buffer.reserve(10); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FIXEXT8_MARKER; - *ptr.add(1) = type_id as u8; - ptr.add(2).copy_from_nonoverlapping(data.as_ptr(), 8); - self.buffer.set_len(self.buffer.len() + 10); - } - Ok(()) - } - 16 => { - self.buffer.reserve(18); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = FIXEXT16_MARKER; - *ptr.add(1) = type_id as u8; - ptr.add(2).copy_from_nonoverlapping(data.as_ptr(), 16); - self.buffer.set_len(self.buffer.len() + 18); - } - Ok(()) - } - 0..=255 => { - self.buffer.reserve(3 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = EXT8_MARKER; - *ptr.add(1) = len as u8; - *ptr.add(2) = type_id as u8; - ptr.add(3).copy_from_nonoverlapping(data.as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 3 + len); - } - Ok(()) - } - 256..=65535 => { - self.buffer.reserve(4 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = EXT16_MARKER; - let len_bytes = (len as u16).to_be_bytes(); - ptr.add(1).copy_from_nonoverlapping(len_bytes.as_ptr(), 2); - *ptr.add(3) = type_id as u8; - ptr.add(4).copy_from_nonoverlapping(data.as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 4 + len); - } - Ok(()) - } - _ => { - self.buffer.reserve(6 + len); - unsafe { - let ptr = self.buffer.as_mut_ptr().add(self.buffer.len()); - *ptr = EXT32_MARKER; - let len_bytes = (len as u32).to_be_bytes(); - ptr.add(1).copy_from_nonoverlapping(len_bytes.as_ptr(), 4); - *ptr.add(5) = type_id as u8; - ptr.add(6).copy_from_nonoverlapping(data.as_ptr(), len); - self.buffer.set_len(self.buffer.len() + 6 + len); - } - Ok(()) - } - } + impl_write_methods! { + write = |writer, data| { + writer.buffer.extend_from_slice(data); + Ok(()) + }, + write_parts = |writer, header, payload| { + writer.buffer.reserve(header.len() + payload.len()); + writer.buffer.extend_from_slice(header); + writer.buffer.extend_from_slice(payload); + Ok(()) + }, + write_container = |writer, header, reserve| { + writer.buffer.reserve(header.len() + reserve); + writer.buffer.extend_from_slice(header); + Ok(()) + }, } } @@ -1364,539 +184,12 @@ impl IOWriter { #[cfg(feature = "std")] impl Write for IOWriter { - #[inline(always)] - fn write_nil(&mut self) -> Result<()> { - self.write_all(&[NIL_MARKER])?; - Ok(()) - } - - #[inline(always)] - fn write_boolean(&mut self, b: bool) -> Result<()> { - self.write_all(&[if b { TRUE_MARKER } else { FALSE_MARKER }])?; - Ok(()) - } - - #[inline(always)] - fn write_u8(&mut self, u: u8) -> Result<()> { - if u <= 127 { - self.write_all(&[u])?; - } else { - self.write_all(&[UINT8_MARKER, u])?; - } - Ok(()) - } - - #[inline(always)] - fn write_u16(&mut self, u: u16) -> Result<()> { - match u { - 0..=127 => { - self.write_all(&[u as u8])?; - Ok(()) - } - 128..=255 => { - self.write_all(&[UINT8_MARKER, u as u8])?; - Ok(()) - } - _ => { - let len_bytes = u.to_be_bytes(); - self.write_all(&[UINT16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_u32(&mut self, u: u32) -> Result<()> { - match u { - 0..=127 => { - self.write_all(&[u as u8])?; - Ok(()) - } - 128..=255 => { - self.write_all(&[UINT8_MARKER, u as u8])?; - Ok(()) - } - 256..=65535 => { - let len_bytes = (u as u16).to_be_bytes(); - self.write_all(&[UINT16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - _ => { - let len_bytes = u.to_be_bytes(); - self.write_all(&[ - UINT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_u64(&mut self, u: u64) -> Result<()> { - match u { - 0..=127 => { - self.write_all(&[u as u8])?; - Ok(()) - } - 128..=255 => { - self.write_all(&[UINT8_MARKER, u as u8])?; - Ok(()) - } - 256..=65535 => { - let len_bytes = (u as u16).to_be_bytes(); - self.write_all(&[UINT16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - 65536..=4294967295 => { - let len_bytes = (u as u32).to_be_bytes(); - self.write_all(&[ - UINT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - _ => { - let len_bytes = u.to_be_bytes(); - self.write_all(&[ - UINT64_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - len_bytes[4], - len_bytes[5], - len_bytes[6], - len_bytes[7], - ])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_i8(&mut self, i: i8) -> Result<()> { - match i { - 0..=127 => { - self.write_all(&[i as u8])?; - Ok(()) - } - -32..=-1 => { - self.write_all(&[0xe0 | ((i + 32) as u8)])?; - Ok(()) - } - _ => { - self.write_all(&[INT8_MARKER, i as u8])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_i16(&mut self, i: i16) -> Result<()> { - match i { - 0..=127 => { - self.write_all(&[i as u8])?; - Ok(()) - } - -32..=-1 => { - self.write_all(&[0xe0 | ((i + 32) as u8)])?; - Ok(()) - } - -128..=127 => { - self.write_all(&[INT8_MARKER, i as u8])?; - Ok(()) - } - _ => { - let len_bytes = i.to_be_bytes(); - self.write_all(&[INT16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_i32(&mut self, i: i32) -> Result<()> { - match i { - 0..=127 => { - self.write_all(&[i as u8])?; - Ok(()) - } - -32..=-1 => { - self.write_all(&[0xe0 | ((i + 32) as u8)])?; - Ok(()) - } - -128..=127 => { - self.write_all(&[INT8_MARKER, i as u8])?; - Ok(()) - } - -32768..=32767 => { - let len_bytes = (i as i16).to_be_bytes(); - self.write_all(&[INT16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - _ => { - let len_bytes = i.to_be_bytes(); - self.write_all(&[ - INT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_i64(&mut self, i: i64) -> Result<()> { - match i { - 0..=127 => { - self.write_all(&[i as u8])?; - Ok(()) - } - -32..=-1 => { - self.write_all(&[0xe0 | ((i + 32) as u8)])?; - Ok(()) - } - -128..=127 => { - self.write_all(&[INT8_MARKER, i as u8])?; - Ok(()) - } - -32768..=32767 => { - let len_bytes = (i as i16).to_be_bytes(); - self.write_all(&[INT16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - -2147483648..=2147483647 => { - let len_bytes = (i as i32).to_be_bytes(); - self.write_all(&[ - INT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - _ => { - let len_bytes = i.to_be_bytes(); - self.write_all(&[ - INT64_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - len_bytes[4], - len_bytes[5], - len_bytes[6], - len_bytes[7], - ])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_f32(&mut self, f: f32) -> Result<()> { - let len_bytes = f.to_be_bytes(); - self.write_all(&[ - FLOAT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - - #[inline(always)] - fn write_f64(&mut self, f: f64) -> Result<()> { - let len_bytes = f.to_be_bytes(); - self.write_all(&[ - FLOAT64_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - len_bytes[4], - len_bytes[5], - len_bytes[6], - len_bytes[7], - ])?; - Ok(()) - } - - fn write_string(&mut self, s: &str) -> Result<()> { - let len = s.len(); - match len { - 0..=31 => { - self.write_all(&[0xa0 | (len as u8)])?; - self.write_all(s.as_bytes())?; - Ok(()) - } - 32..=255 => { - self.write_all(&[STR8_MARKER, len as u8])?; - self.write_all(s.as_bytes())?; - Ok(()) - } - 256..=65535 => { - let len_bytes = (len as u16).to_be_bytes(); - self.write_all(&[STR16_MARKER, len_bytes[0], len_bytes[1]])?; - self.write_all(s.as_bytes())?; - Ok(()) - } - _ => { - let len_bytes = (len as u32).to_be_bytes(); - self.write_all(&[ - STR32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - self.write_all(s.as_bytes())?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_binary(&mut self, data: &[u8]) -> Result<()> { - let len = data.len(); - match len { - 0..=255 => { - self.write_all(&[BIN8_MARKER, len as u8])?; - self.write_all(data)?; - Ok(()) - } - 256..=65535 => { - let len_bytes = (len as u16).to_be_bytes(); - self.write_all(&[BIN16_MARKER, len_bytes[0], len_bytes[1]])?; - self.write_all(data)?; - Ok(()) - } - _ => { - let len_bytes = (len as u32).to_be_bytes(); - self.write_all(&[ - BIN32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - self.write_all(data)?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_timestamp(&mut self, seconds: i64, nanoseconds: u32) -> Result<()> { - if nanoseconds >= 1_000_000_000 { - return Err(Error::InvalidTimestamp); - } - - // timestamp 32: sec in [0, 2^32-1], nsec == 0 - if nanoseconds == 0 && (0..=u32::MAX as i64).contains(&seconds) { - let sec_bytes = (seconds as u32).to_be_bytes(); - self.write_all(&[ - TIMESTAMP32_MARKER, - 0xff, - sec_bytes[0], - sec_bytes[1], - sec_bytes[2], - sec_bytes[3], - ])?; - return Ok(()); - } - - // timestamp 64: sec in [0, 2^34-1] - if (0..=(1i64 << 34) - 1).contains(&seconds) { - let data = ((nanoseconds as u64) << 34) | (seconds as u64); - let data_bytes = data.to_be_bytes(); - self.write_all(&[ - TIMESTAMP64_MARKER, - 0xff, - data_bytes[0], - data_bytes[1], - data_bytes[2], - data_bytes[3], - data_bytes[4], - data_bytes[5], - data_bytes[6], - data_bytes[7], - ])?; - return Ok(()); - } - - // timestamp 96 - let sec_bytes = seconds.to_be_bytes(); - let nsec_bytes = nanoseconds.to_be_bytes(); - self.write_all(&[ - TIMESTAMP96_MARKER, - 12, - 0xff, - nsec_bytes[0], - nsec_bytes[1], - nsec_bytes[2], - nsec_bytes[3], - sec_bytes[0], - sec_bytes[1], - sec_bytes[2], - sec_bytes[3], - sec_bytes[4], - sec_bytes[5], - sec_bytes[6], - sec_bytes[7], - ])?; - Ok(()) - } - - #[inline(always)] - fn write_array_len(&mut self, len: usize) -> Result<()> { - match len { - 0..=15 => { - self.write_all(&[FIXARRAY_START | (len as u8)])?; - Ok(()) - } - 16..=65535 => { - let len_bytes = (len as u16).to_be_bytes(); - self.write_all(&[ARRAY16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - _ => { - let len_bytes = (len as u32).to_be_bytes(); - self.write_all(&[ - ARRAY32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_map_len(&mut self, len: usize) -> Result<()> { - match len { - 0..=15 => { - self.write_all(&[FIXMAP_START | (len as u8)])?; - Ok(()) - } - 16..=65535 => { - let len_bytes = (len as u16).to_be_bytes(); - self.write_all(&[MAP16_MARKER, len_bytes[0], len_bytes[1]])?; - Ok(()) - } - _ => { - let len_bytes = (len as u32).to_be_bytes(); - self.write_all(&[ - MAP32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - ])?; - Ok(()) - } - } - } - - #[inline(always)] - fn write_ext(&mut self, type_id: i8, data: &[u8]) -> Result<()> { - let len = data.len(); - match len { - 1 => { - self.write_all(&[FIXEXT1_MARKER, type_id as u8, data[0]])?; - Ok(()) - } - 2 => { - self.write_all(&[FIXEXT2_MARKER, type_id as u8, data[0], data[1]])?; - Ok(()) - } - 4 => { - self.write_all(&[ - FIXEXT4_MARKER, - type_id as u8, - data[0], - data[1], - data[2], - data[3], - ])?; - Ok(()) - } - 8 => { - self.write_all(&[ - FIXEXT8_MARKER, - type_id as u8, - data[0], - data[1], - data[2], - data[3], - data[4], - data[5], - data[6], - data[7], - ])?; - Ok(()) - } - 16 => { - self.write_all(&[ - FIXEXT16_MARKER, - type_id as u8, - data[0], - data[1], - data[2], - data[3], - data[4], - data[5], - data[6], - data[7], - data[8], - data[9], - data[10], - data[11], - data[12], - data[13], - data[14], - data[15], - ])?; - Ok(()) - } - 0..=255 => { - self.write_all(&[EXT8_MARKER, len as u8, type_id as u8])?; - self.write_all(data)?; - Ok(()) - } - 256..=65535 => { - let len_bytes = (len as u16).to_be_bytes(); - self.write_all(&[EXT16_MARKER, len_bytes[0], len_bytes[1], type_id as u8])?; - self.write_all(data)?; - Ok(()) - } - _ => { - let len_bytes = (len as u32).to_be_bytes(); - self.write_all(&[ - EXT32_MARKER, - len_bytes[0], - len_bytes[1], - len_bytes[2], - len_bytes[3], - type_id as u8, - ])?; - self.write_all(data)?; - Ok(()) - } - } + impl_write_methods! { + write = |writer, data| writer.write_all(data), + write_parts = |writer, header, payload| { + writer.write_all(header)?; + writer.write_all(payload) + }, + write_container = |writer, header, _reserve| writer.write_all(header), } } diff --git a/zerompk/src/write_macro.rs b/zerompk/src/write_macro.rs new file mode 100644 index 0000000..3e482c0 --- /dev/null +++ b/zerompk/src/write_macro.rs @@ -0,0 +1,345 @@ +macro_rules! impl_write_methods { + ( + write = |$writer:ident, $data:ident| $write:expr, + write_parts = |$parts_writer:ident, $header:ident, $payload:ident| $write_parts:expr, + write_container = + |$container_writer:ident, $container_header:ident, $reserve:ident| $write_container:expr + $(,)? + ) => { + #[inline(always)] + fn write_nil(&mut self) -> Result<()> { + let bytes = [NIL_MARKER]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_boolean(&mut self, value: bool) -> Result<()> { + let bytes = [if value { TRUE_MARKER } else { FALSE_MARKER }]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_u8(&mut self, value: u8) -> Result<()> { + let bytes = [UINT8_MARKER, value]; + let len = if value <= POS_FIXINT_END { 1 } else { 2 }; + let $writer = &mut *self; + let $data = if len == 1 { &bytes[1..] } else { &bytes }; + $write + } + + #[inline(always)] + fn write_u16(&mut self, value: u16) -> Result<()> { + if value <= u8::MAX as u16 { + return self.write_u8(value as u8); + } + let [a, b] = value.to_be_bytes(); + let bytes = [UINT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_u32(&mut self, value: u32) -> Result<()> { + if value <= u16::MAX as u32 { + return self.write_u16(value as u16); + } + let [a, b, c, d] = value.to_be_bytes(); + let bytes = [UINT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_u64(&mut self, value: u64) -> Result<()> { + if value <= u32::MAX as u64 { + return self.write_u32(value as u32); + } + let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let bytes = [UINT64_MARKER, a, b, c, d, e, f, g, h]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_i8(&mut self, value: i8) -> Result<()> { + let bytes = [INT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = if (-32..=127).contains(&value) { + &bytes[1..] + } else { + &bytes + }; + $write + } + + #[inline(always)] + fn write_i16(&mut self, value: i16) -> Result<()> { + if (i8::MIN as i16..=i8::MAX as i16).contains(&value) { + return self.write_i8(value as i8); + } + let [a, b] = value.to_be_bytes(); + let bytes = [INT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_i32(&mut self, value: i32) -> Result<()> { + if (i16::MIN as i32..=i16::MAX as i32).contains(&value) { + return self.write_i16(value as i16); + } + let [a, b, c, d] = value.to_be_bytes(); + let bytes = [INT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_i64(&mut self, value: i64) -> Result<()> { + if (i32::MIN as i64..=i32::MAX as i64).contains(&value) { + return self.write_i32(value as i32); + } + let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let bytes = [INT64_MARKER, a, b, c, d, e, f, g, h]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_f32(&mut self, value: f32) -> Result<()> { + let [a, b, c, d] = value.to_be_bytes(); + let bytes = [FLOAT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_f64(&mut self, value: f64) -> Result<()> { + let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let bytes = [FLOAT64_MARKER, a, b, c, d, e, f, g, h]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_timestamp(&mut self, seconds: i64, nanoseconds: u32) -> Result<()> { + if nanoseconds >= 1_000_000_000 { + return Err(Error::InvalidTimestamp); + } + if nanoseconds == 0 && (0..=u32::MAX as i64).contains(&seconds) { + let [a, b, c, d] = (seconds as u32).to_be_bytes(); + let bytes = [TIMESTAMP32_MARKER, TIMESTAMP_EXT_TYPE as u8, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + return $write; + } + if (0..=(1i64 << 34) - 1).contains(&seconds) { + let value = ((nanoseconds as u64) << 34) | seconds as u64; + let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let bytes = [ + TIMESTAMP64_MARKER, + TIMESTAMP_EXT_TYPE as u8, + a, + b, + c, + d, + e, + f, + g, + h, + ]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + return $write; + } + let [a, b, c, d] = nanoseconds.to_be_bytes(); + let [e, f, g, h, i, j, k, l] = seconds.to_be_bytes(); + let bytes = [ + TIMESTAMP96_MARKER, + 12, + TIMESTAMP_EXT_TYPE as u8, + a, + b, + c, + d, + e, + f, + g, + h, + i, + j, + k, + l, + ]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + + #[inline(always)] + fn write_string(&mut self, value: &str) -> Result<()> { + let len = value.len(); + let mut header = [0; 5]; + let header_len = match len { + 0..=31 => { + header[0] = FIXSTR_START | len as u8; + 1 + } + 32..=255 => { + header[..2].copy_from_slice(&[STR8_MARKER, len as u8]); + 2 + } + 256..=65535 => { + header[0] = STR16_MARKER; + header[1..3].copy_from_slice(&(len as u16).to_be_bytes()); + 3 + } + _ => { + header[0] = STR32_MARKER; + header[1..].copy_from_slice(&(len as u32).to_be_bytes()); + 5 + } + }; + let $parts_writer = &mut *self; + let $header = &header[..header_len]; + let $payload = value.as_bytes(); + $write_parts + } + + #[inline(always)] + fn write_binary(&mut self, value: &[u8]) -> Result<()> { + let len = value.len(); + let mut header = [0; 5]; + let header_len = match len { + 0..=255 => { + header[..2].copy_from_slice(&[BIN8_MARKER, len as u8]); + 2 + } + 256..=65535 => { + header[0] = BIN16_MARKER; + header[1..3].copy_from_slice(&(len as u16).to_be_bytes()); + 3 + } + _ => { + header[0] = BIN32_MARKER; + header[1..].copy_from_slice(&(len as u32).to_be_bytes()); + 5 + } + }; + let $parts_writer = &mut *self; + let $header = &header[..header_len]; + let $payload = value; + $write_parts + } + + #[inline(always)] + fn write_ext(&mut self, type_id: i8, value: &[u8]) -> Result<()> { + let len = value.len(); + let mut header = [0; 6]; + let header_len = match len { + 1 => { + header[..2].copy_from_slice(&[FIXEXT1_MARKER, type_id as u8]); + 2 + } + 2 => { + header[..2].copy_from_slice(&[FIXEXT2_MARKER, type_id as u8]); + 2 + } + 4 => { + header[..2].copy_from_slice(&[FIXEXT4_MARKER, type_id as u8]); + 2 + } + 8 => { + header[..2].copy_from_slice(&[FIXEXT8_MARKER, type_id as u8]); + 2 + } + 16 => { + header[..2].copy_from_slice(&[FIXEXT16_MARKER, type_id as u8]); + 2 + } + 0..=255 => { + header[..3].copy_from_slice(&[EXT8_MARKER, len as u8, type_id as u8]); + 3 + } + 256..=65535 => { + header[0] = EXT16_MARKER; + header[1..3].copy_from_slice(&(len as u16).to_be_bytes()); + header[3] = type_id as u8; + 4 + } + _ => { + header[0] = EXT32_MARKER; + header[1..5].copy_from_slice(&(len as u32).to_be_bytes()); + header[5] = type_id as u8; + 6 + } + }; + let $parts_writer = &mut *self; + let $header = &header[..header_len]; + let $payload = value; + $write_parts + } + + #[inline(always)] + fn write_array_len(&mut self, len: usize) -> Result<()> { + let mut header = [0; 5]; + let header_len = match len { + 0..=15 => { + header[0] = FIXARRAY_START | len as u8; + 1 + } + 16..=65535 => { + header[0] = ARRAY16_MARKER; + header[1..3].copy_from_slice(&(len as u16).to_be_bytes()); + 3 + } + _ => { + header[0] = ARRAY32_MARKER; + header[1..].copy_from_slice(&(len as u32).to_be_bytes()); + 5 + } + }; + let $container_writer = &mut *self; + let $container_header = &header[..header_len]; + let $reserve = len.min(MAX_CONTAINER_PREALLOC); + $write_container + } + + #[inline(always)] + fn write_map_len(&mut self, len: usize) -> Result<()> { + let mut header = [0; 5]; + let header_len = match len { + 0..=15 => { + header[0] = FIXMAP_START | len as u8; + 1 + } + 16..=65535 => { + header[0] = MAP16_MARKER; + header[1..3].copy_from_slice(&(len as u16).to_be_bytes()); + 3 + } + _ => { + header[0] = MAP32_MARKER; + header[1..].copy_from_slice(&(len as u32).to_be_bytes()); + 5 + } + }; + let $container_writer = &mut *self; + let $container_header = &header[..header_len]; + let $reserve = len.saturating_mul(2).min(MAX_CONTAINER_PREALLOC); + $write_container + } + }; +} From c3b6e14a878f389a9bdb1bce99cd60d507ef0ece Mon Sep 17 00:00:00 2001 From: nuskey8 Date: Fri, 24 Jul 2026 16:26:12 +0900 Subject: [PATCH 2/2] optimize: write integer --- zerompk/src/write.rs | 110 ++++++++++-- zerompk/src/write_macro.rs | 334 ++++++++++++++++++++++++++----------- 2 files changed, 341 insertions(+), 103 deletions(-) diff --git a/zerompk/src/write.rs b/zerompk/src/write.rs index 5c70891..c2daea9 100644 --- a/zerompk/src/write.rs +++ b/zerompk/src/write.rs @@ -93,6 +93,17 @@ impl<'a> SliceWriter<'a> { SliceWriter { buffer, pos: 0 } } + #[inline(always)] + fn take_array(&mut self) -> Result<&mut [u8; N]> { + if N > self.buffer.len() - self.pos { + cold_path(); + return Err(Error::BufferTooSmall); + } + let array = unsafe { &mut *(self.buffer.as_mut_ptr().add(self.pos) as *mut [u8; N]) }; + self.pos += N; + Ok(array) + } + #[inline(always)] fn take_slice(&mut self, len: usize) -> Result<&mut [u8]> { if len > self.buffer.len() - self.pos { @@ -114,18 +125,74 @@ impl<'a> SliceWriter<'a> { impl<'a> Write for SliceWriter<'a> { impl_write_methods! { write = |writer, data| { - writer.take_slice(data.len())?.copy_from_slice(data); + match data { + [a] => *writer.take_array::<1>()? = [*a], + [a, b] => *writer.take_array::<2>()? = [*a, *b], + [a, b, c] => *writer.take_array::<3>()? = [*a, *b, *c], + [a, b, c, d, e] => *writer.take_array::<5>()? = [*a, *b, *c, *d, *e], + [a, b, c, d, e, f] => { + *writer.take_array::<6>()? = [*a, *b, *c, *d, *e, *f] + } + [a, b, c, d, e, f, g, h, i] => { + *writer.take_array::<9>()? = [*a, *b, *c, *d, *e, *f, *g, *h, *i] + } + [a, b, c, d, e, f, g, h, i, j] => { + *writer.take_array::<10>()? = [*a, *b, *c, *d, *e, *f, *g, *h, *i, *j] + } + _ => writer.take_slice(data.len())?.copy_from_slice(data), + } Ok(()) }, write_parts = |writer, header, payload| { let output = writer.take_slice(header.len() + payload.len())?; - let (output_header, output_payload) = output.split_at_mut(header.len()); - output_header.copy_from_slice(header); - output_payload.copy_from_slice(payload); + unsafe { + let ptr = output.as_mut_ptr(); + match header { + [a] => *ptr = *a, + [a, b] => { + *ptr = *a; + *ptr.add(1) = *b; + } + [a, b, c] => { + *ptr = *a; + *ptr.add(1) = *b; + *ptr.add(2) = *c; + } + [a, b, c, d] => { + *ptr = *a; + *ptr.add(1) = *b; + *ptr.add(2) = *c; + *ptr.add(3) = *d; + } + [a, b, c, d, e] => { + *ptr = *a; + *ptr.add(1) = *b; + *ptr.add(2) = *c; + *ptr.add(3) = *d; + *ptr.add(4) = *e; + } + [a, b, c, d, e, f] => { + *ptr = *a; + *ptr.add(1) = *b; + *ptr.add(2) = *c; + *ptr.add(3) = *d; + *ptr.add(4) = *e; + *ptr.add(5) = *f; + } + _ => unreachable!(), + } + ptr.add(header.len()) + .copy_from_nonoverlapping(payload.as_ptr(), payload.len()); + } Ok(()) }, write_container = |writer, header, _reserve| { - writer.take_slice(header.len())?.copy_from_slice(header); + match header { + [a] => *writer.take_array::<1>()? = [*a], + [a, b, c] => *writer.take_array::<3>()? = [*a, *b, *c], + [a, b, c, d, e] => *writer.take_array::<5>()? = [*a, *b, *c, *d, *e], + _ => unreachable!(), + } Ok(()) }, } @@ -148,18 +215,41 @@ impl VecWriter { impl Write for VecWriter { impl_write_methods! { write = |writer, data| { - writer.buffer.extend_from_slice(data); + if let [byte] = data { + writer.buffer.push(*byte); + } else { + writer.buffer.reserve(data.len()); + unsafe { + let len = writer.buffer.len(); + let output = writer.buffer.as_mut_ptr().add(len); + output.copy_from_nonoverlapping(data.as_ptr(), data.len()); + writer.buffer.set_len(len + data.len()); + } + } Ok(()) }, write_parts = |writer, header, payload| { - writer.buffer.reserve(header.len() + payload.len()); - writer.buffer.extend_from_slice(header); - writer.buffer.extend_from_slice(payload); + let additional = header.len() + payload.len(); + writer.buffer.reserve(additional); + unsafe { + let len = writer.buffer.len(); + let output = writer.buffer.as_mut_ptr().add(len); + output.copy_from_nonoverlapping(header.as_ptr(), header.len()); + output + .add(header.len()) + .copy_from_nonoverlapping(payload.as_ptr(), payload.len()); + writer.buffer.set_len(len + additional); + } Ok(()) }, write_container = |writer, header, reserve| { writer.buffer.reserve(header.len() + reserve); - writer.buffer.extend_from_slice(header); + unsafe { + let len = writer.buffer.len(); + let output = writer.buffer.as_mut_ptr().add(len); + output.copy_from_nonoverlapping(header.as_ptr(), header.len()); + writer.buffer.set_len(len + header.len()); + } Ok(()) }, } diff --git a/zerompk/src/write_macro.rs b/zerompk/src/write_macro.rs index 3e482c0..20031a7 100644 --- a/zerompk/src/write_macro.rs +++ b/zerompk/src/write_macro.rs @@ -33,86 +33,236 @@ macro_rules! impl_write_methods { #[inline(always)] fn write_u16(&mut self, value: u16) -> Result<()> { - if value <= u8::MAX as u16 { - return self.write_u8(value as u8); + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + 128..=255 => { + let bytes = [UINT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let [a, b] = value.to_be_bytes(); + let bytes = [UINT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } } - let [a, b] = value.to_be_bytes(); - let bytes = [UINT16_MARKER, a, b]; - let $writer = &mut *self; - let $data = bytes.as_slice(); - $write } #[inline(always)] fn write_u32(&mut self, value: u32) -> Result<()> { - if value <= u16::MAX as u32 { - return self.write_u16(value as u16); + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + 128..=255 => { + let bytes = [UINT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + 256..=65535 => { + let [a, b] = (value as u16).to_be_bytes(); + let bytes = [UINT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let [a, b, c, d] = value.to_be_bytes(); + let bytes = [UINT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } } - let [a, b, c, d] = value.to_be_bytes(); - let bytes = [UINT32_MARKER, a, b, c, d]; - let $writer = &mut *self; - let $data = bytes.as_slice(); - $write } #[inline(always)] fn write_u64(&mut self, value: u64) -> Result<()> { - if value <= u32::MAX as u64 { - return self.write_u32(value as u32); + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + 128..=255 => { + let bytes = [UINT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + 256..=65535 => { + let [a, b] = (value as u16).to_be_bytes(); + let bytes = [UINT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + 65536..=4294967295 => { + let [a, b, c, d] = (value as u32).to_be_bytes(); + let bytes = [UINT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let bytes = [UINT64_MARKER, a, b, c, d, e, f, g, h]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } } - let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); - let bytes = [UINT64_MARKER, a, b, c, d, e, f, g, h]; - let $writer = &mut *self; - let $data = bytes.as_slice(); - $write } #[inline(always)] fn write_i8(&mut self, value: i8) -> Result<()> { - let bytes = [INT8_MARKER, value as u8]; - let $writer = &mut *self; - let $data = if (-32..=127).contains(&value) { - &bytes[1..] - } else { - &bytes - }; - $write + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -32..=-1 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let bytes = [INT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + } } #[inline(always)] fn write_i16(&mut self, value: i16) -> Result<()> { - if (i8::MIN as i16..=i8::MAX as i16).contains(&value) { - return self.write_i8(value as i8); + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -32..=-1 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -128..=127 => { + let bytes = [INT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let [a, b] = value.to_be_bytes(); + let bytes = [INT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } } - let [a, b] = value.to_be_bytes(); - let bytes = [INT16_MARKER, a, b]; - let $writer = &mut *self; - let $data = bytes.as_slice(); - $write } #[inline(always)] fn write_i32(&mut self, value: i32) -> Result<()> { - if (i16::MIN as i32..=i16::MAX as i32).contains(&value) { - return self.write_i16(value as i16); + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -32..=-1 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -128..=127 => { + let bytes = [INT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -32768..=32767 => { + let [a, b] = (value as i16).to_be_bytes(); + let bytes = [INT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let [a, b, c, d] = value.to_be_bytes(); + let bytes = [INT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } } - let [a, b, c, d] = value.to_be_bytes(); - let bytes = [INT32_MARKER, a, b, c, d]; - let $writer = &mut *self; - let $data = bytes.as_slice(); - $write } #[inline(always)] fn write_i64(&mut self, value: i64) -> Result<()> { - if (i32::MIN as i64..=i32::MAX as i64).contains(&value) { - return self.write_i32(value as i32); + match value { + 0..=127 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -32..=-1 => { + let bytes = [value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -128..=127 => { + let bytes = [INT8_MARKER, value as u8]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -32768..=32767 => { + let [a, b] = (value as i16).to_be_bytes(); + let bytes = [INT16_MARKER, a, b]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + -2147483648..=2147483647 => { + let [a, b, c, d] = (value as i32).to_be_bytes(); + let bytes = [INT32_MARKER, a, b, c, d]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } + _ => { + let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let bytes = [INT64_MARKER, a, b, c, d, e, f, g, h]; + let $writer = &mut *self; + let $data = bytes.as_slice(); + $write + } } - let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); - let bytes = [INT64_MARKER, a, b, c, d, e, f, g, h]; - let $writer = &mut *self; - let $data = bytes.as_slice(); - $write } #[inline(always)] @@ -139,49 +289,56 @@ macro_rules! impl_write_methods { return Err(Error::InvalidTimestamp); } if nanoseconds == 0 && (0..=u32::MAX as i64).contains(&seconds) { - let [a, b, c, d] = (seconds as u32).to_be_bytes(); - let bytes = [TIMESTAMP32_MARKER, TIMESTAMP_EXT_TYPE as u8, a, b, c, d]; + let seconds = (seconds as u32).to_be_bytes(); + let bytes = [ + TIMESTAMP32_MARKER, + TIMESTAMP_EXT_TYPE as u8, + seconds[0], + seconds[1], + seconds[2], + seconds[3], + ]; let $writer = &mut *self; let $data = bytes.as_slice(); return $write; } if (0..=(1i64 << 34) - 1).contains(&seconds) { let value = ((nanoseconds as u64) << 34) | seconds as u64; - let [a, b, c, d, e, f, g, h] = value.to_be_bytes(); + let value = value.to_be_bytes(); let bytes = [ TIMESTAMP64_MARKER, TIMESTAMP_EXT_TYPE as u8, - a, - b, - c, - d, - e, - f, - g, - h, + value[0], + value[1], + value[2], + value[3], + value[4], + value[5], + value[6], + value[7], ]; let $writer = &mut *self; let $data = bytes.as_slice(); return $write; } - let [a, b, c, d] = nanoseconds.to_be_bytes(); - let [e, f, g, h, i, j, k, l] = seconds.to_be_bytes(); + let nanos = nanoseconds.to_be_bytes(); + let seconds = seconds.to_be_bytes(); let bytes = [ TIMESTAMP96_MARKER, 12, TIMESTAMP_EXT_TYPE as u8, - a, - b, - c, - d, - e, - f, - g, - h, - i, - j, - k, - l, + nanos[0], + nanos[1], + nanos[2], + nanos[3], + seconds[0], + seconds[1], + seconds[2], + seconds[3], + seconds[4], + seconds[5], + seconds[6], + seconds[7], ]; let $writer = &mut *self; let $data = bytes.as_slice(); @@ -249,24 +406,15 @@ macro_rules! impl_write_methods { let len = value.len(); let mut header = [0; 6]; let header_len = match len { - 1 => { - header[..2].copy_from_slice(&[FIXEXT1_MARKER, type_id as u8]); - 2 - } - 2 => { - header[..2].copy_from_slice(&[FIXEXT2_MARKER, type_id as u8]); - 2 - } - 4 => { - header[..2].copy_from_slice(&[FIXEXT4_MARKER, type_id as u8]); - 2 - } - 8 => { - header[..2].copy_from_slice(&[FIXEXT8_MARKER, type_id as u8]); - 2 - } - 16 => { - header[..2].copy_from_slice(&[FIXEXT16_MARKER, type_id as u8]); + 1 | 2 | 4 | 8 | 16 => { + header[0] = match len { + 1 => FIXEXT1_MARKER, + 2 => FIXEXT2_MARKER, + 4 => FIXEXT4_MARKER, + 8 => FIXEXT8_MARKER, + _ => FIXEXT16_MARKER, + }; + header[1] = type_id as u8; 2 } 0..=255 => {