use crate::leb128::{self, max_leb128_len};
-use crate::serialize;
+use crate::serialize::{self, Encoder as _};
use std::borrow::Cow;
+use std::convert::TryInto;
use std::fs::File;
use std::io::{self, Write};
use std::mem::MaybeUninit;
pub fn position(&self) -> usize {
self.data.len()
}
-
- #[inline]
- pub fn emit_raw_bytes(&mut self, s: &[u8]) {
- self.data.extend_from_slice(s);
- }
}
macro_rules! write_leb128 {
#[inline]
fn emit_str(&mut self, v: &str) -> EncodeResult {
self.emit_usize(v.len())?;
- self.emit_raw_bytes(v.as_bytes());
+ self.emit_raw_bytes(v.as_bytes())
+ }
+
+ #[inline]
+ fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
+ self.data.extend_from_slice(s);
Ok(())
}
}
self.flushed + self.buffered
}
- #[inline]
- pub fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult {
- self.write_all(s)
- }
-
pub fn flush(&mut self) -> FileEncodeResult {
// This is basically a copy of `BufWriter::flush`. If `BufWriter` ever
// offers a raw buffer access API, we can use it, and remove this.
self.emit_usize(v.len())?;
self.emit_raw_bytes(v.as_bytes())
}
+
+ #[inline]
+ fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult {
+ self.write_all(s)
+ }
}
// -----------------------------------------------------------------------------
}
#[inline]
- pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
+ pub fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] {
let start = self.position;
- let end = start + s.len();
- assert!(end <= self.data.len());
-
- // SAFETY: Both `src` and `dst` point to at least `s.len()` elements:
- // `src` points to at least `s.len()` elements by above assert, and
- // `dst` points to `s.len()` elements by derivation from `s`.
- unsafe {
- let src = self.data.as_ptr().add(start);
- let dst = s.as_mut_ptr() as *mut u8;
- ptr::copy_nonoverlapping(src, dst, s.len());
- }
-
- self.position = end;
-
- Ok(())
+ self.position += bytes;
+ &self.data[start..self.position]
}
}
fn error(&mut self, err: &str) -> Self::Error {
err.to_string()
}
+
+ #[inline]
+ fn read_raw_bytes_into(&mut self, s: &mut [u8]) -> Result<(), String> {
+ let start = self.position;
+ self.position += s.len();
+ s.copy_from_slice(&self.data[start..self.position]);
+ Ok(())
+ }
}
// Specializations for contiguous byte sequences follow. The default implementations for slices
impl serialize::Encodable<Encoder> for [u8] {
fn encode(&self, e: &mut Encoder) -> EncodeResult {
serialize::Encoder::emit_usize(e, self.len())?;
- e.emit_raw_bytes(self);
- Ok(())
+ e.emit_raw_bytes(self)
}
}
impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
let len = serialize::Decoder::read_usize(d)?;
+ Ok(d.read_raw_bytes(len).to_owned())
+ }
+}
- let mut v = Vec::with_capacity(len);
- let buf = &mut v.spare_capacity_mut()[..len];
- d.read_raw_bytes(buf)?;
+// An integer that will always encode to 8 bytes.
+pub struct IntEncodedWithFixedSize(pub u64);
- unsafe {
- v.set_len(len);
- }
+impl IntEncodedWithFixedSize {
+ pub const ENCODED_SIZE: usize = 8;
+}
+
+impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize {
+ #[inline]
+ fn encode(&self, e: &mut Encoder) -> EncodeResult {
+ let _start_pos = e.position();
+ e.emit_raw_bytes(&self.0.to_le_bytes())?;
+ let _end_pos = e.position();
+ debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
+ Ok(())
+ }
+}
+
+impl serialize::Encodable<FileEncoder> for IntEncodedWithFixedSize {
+ #[inline]
+ fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
+ let _start_pos = e.position();
+ e.emit_raw_bytes(&self.0.to_le_bytes())?;
+ let _end_pos = e.position();
+ debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
+ Ok(())
+ }
+}
+
+impl<'a> serialize::Decodable<Decoder<'a>> for IntEncodedWithFixedSize {
+ #[inline]
+ fn decode(decoder: &mut Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> {
+ let _start_pos = decoder.position();
+ let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
+ let _end_pos = decoder.position();
+ debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
- Ok(v)
+ let value = u64::from_le_bytes(bytes.try_into().unwrap());
+ Ok(IntEncodedWithFixedSize(value))
}
}