use crate::leb128::{self, max_leb128_len};
-use crate::serialize::{self, Decoder as _, Encoder as _};
+use crate::serialize::{Decodable, Decoder, Encodable, Encoder};
use std::convert::TryInto;
use std::fs::File;
use std::io::{self, Write};
// Encoder
// -----------------------------------------------------------------------------
-pub type EncodeResult = Result<(), !>;
-
-pub struct Encoder {
+pub struct MemEncoder {
pub data: Vec<u8>,
}
-impl Encoder {
- pub fn new(data: Vec<u8>) -> Encoder {
- Encoder { data }
- }
-
- pub fn into_inner(self) -> Vec<u8> {
- self.data
+impl MemEncoder {
+ pub fn new() -> MemEncoder {
+ MemEncoder { data: vec![] }
}
#[inline]
pub fn position(&self) -> usize {
self.data.len()
}
+
+ pub fn finish(self) -> Vec<u8> {
+ self.data
+ }
}
macro_rules! write_leb128 {
let encoded = leb128::$fun(buf, $value);
$enc.data.set_len(old_len + encoded.len());
}
-
- Ok(())
}};
}
/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout
const STR_SENTINEL: u8 = 0xC1;
-impl serialize::Encoder for Encoder {
- type Error = !;
-
+impl Encoder for MemEncoder {
#[inline]
- fn emit_unit(&mut self) -> EncodeResult {
- Ok(())
- }
-
- #[inline]
- fn emit_usize(&mut self, v: usize) -> EncodeResult {
+ fn emit_usize(&mut self, v: usize) {
write_leb128!(self, v, usize, write_usize_leb128)
}
#[inline]
- fn emit_u128(&mut self, v: u128) -> EncodeResult {
- write_leb128!(self, v, u128, write_u128_leb128)
+ fn emit_u128(&mut self, v: u128) {
+ write_leb128!(self, v, u128, write_u128_leb128);
}
#[inline]
- fn emit_u64(&mut self, v: u64) -> EncodeResult {
- write_leb128!(self, v, u64, write_u64_leb128)
+ fn emit_u64(&mut self, v: u64) {
+ write_leb128!(self, v, u64, write_u64_leb128);
}
#[inline]
- fn emit_u32(&mut self, v: u32) -> EncodeResult {
- write_leb128!(self, v, u32, write_u32_leb128)
+ fn emit_u32(&mut self, v: u32) {
+ write_leb128!(self, v, u32, write_u32_leb128);
}
#[inline]
- fn emit_u16(&mut self, v: u16) -> EncodeResult {
+ fn emit_u16(&mut self, v: u16) {
self.data.extend_from_slice(&v.to_le_bytes());
- Ok(())
}
#[inline]
- fn emit_u8(&mut self, v: u8) -> EncodeResult {
+ fn emit_u8(&mut self, v: u8) {
self.data.push(v);
- Ok(())
}
#[inline]
- fn emit_isize(&mut self, v: isize) -> EncodeResult {
+ fn emit_isize(&mut self, v: isize) {
write_leb128!(self, v, isize, write_isize_leb128)
}
#[inline]
- fn emit_i128(&mut self, v: i128) -> EncodeResult {
+ fn emit_i128(&mut self, v: i128) {
write_leb128!(self, v, i128, write_i128_leb128)
}
#[inline]
- fn emit_i64(&mut self, v: i64) -> EncodeResult {
+ fn emit_i64(&mut self, v: i64) {
write_leb128!(self, v, i64, write_i64_leb128)
}
#[inline]
- fn emit_i32(&mut self, v: i32) -> EncodeResult {
+ fn emit_i32(&mut self, v: i32) {
write_leb128!(self, v, i32, write_i32_leb128)
}
#[inline]
- fn emit_i16(&mut self, v: i16) -> EncodeResult {
+ fn emit_i16(&mut self, v: i16) {
self.data.extend_from_slice(&v.to_le_bytes());
- Ok(())
}
#[inline]
- fn emit_i8(&mut self, v: i8) -> EncodeResult {
- self.emit_u8(v as u8)
+ fn emit_i8(&mut self, v: i8) {
+ self.emit_u8(v as u8);
}
#[inline]
- fn emit_bool(&mut self, v: bool) -> EncodeResult {
- self.emit_u8(if v { 1 } else { 0 })
+ fn emit_bool(&mut self, v: bool) {
+ self.emit_u8(if v { 1 } else { 0 });
}
#[inline]
- fn emit_f64(&mut self, v: f64) -> EncodeResult {
+ fn emit_f64(&mut self, v: f64) {
let as_u64: u64 = v.to_bits();
- self.emit_u64(as_u64)
+ self.emit_u64(as_u64);
}
#[inline]
- fn emit_f32(&mut self, v: f32) -> EncodeResult {
+ fn emit_f32(&mut self, v: f32) {
let as_u32: u32 = v.to_bits();
- self.emit_u32(as_u32)
+ self.emit_u32(as_u32);
}
#[inline]
- fn emit_char(&mut self, v: char) -> EncodeResult {
- self.emit_u32(v as u32)
+ fn emit_char(&mut self, v: char) {
+ self.emit_u32(v as u32);
}
#[inline]
- fn emit_str(&mut self, v: &str) -> EncodeResult {
- self.emit_usize(v.len())?;
- self.emit_raw_bytes(v.as_bytes())?;
- self.emit_u8(STR_SENTINEL)
+ fn emit_str(&mut self, v: &str) {
+ self.emit_usize(v.len());
+ self.emit_raw_bytes(v.as_bytes());
+ self.emit_u8(STR_SENTINEL);
}
#[inline]
- fn emit_raw_bytes(&mut self, s: &[u8]) -> EncodeResult {
+ fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s);
- Ok(())
}
}
-pub type FileEncodeResult = Result<(), io::Error>;
+pub type FileEncodeResult = Result<usize, io::Error>;
// `FileEncoder` encodes data to file via fixed-size buffer.
//
// When encoding large amounts of data to a file, using `FileEncoder` may be
-// preferred over using `Encoder` to encode to a `Vec`, and then writing the
+// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
// `Vec` to file, as the latter uses as much memory as there is encoded data,
// while the former uses the fixed amount of memory allocated to the buffer.
// `FileEncoder` also has the advantage of not needing to reallocate as data
buffered: usize,
flushed: usize,
file: File,
+ // This is used to implement delayed error handling, as described in the
+ // comment on `trait Encoder`.
+ res: Result<(), io::Error>,
}
impl FileEncoder {
let file = File::create(path)?;
- Ok(FileEncoder { buf: Box::new_uninit_slice(capacity), buffered: 0, flushed: 0, file })
+ Ok(FileEncoder {
+ buf: Box::new_uninit_slice(capacity),
+ buffered: 0,
+ flushed: 0,
+ file,
+ res: Ok(()),
+ })
}
#[inline]
self.flushed + self.buffered
}
- pub fn flush(&mut self) -> FileEncodeResult {
+ pub fn flush(&mut self) {
// This is basically a copy of `BufWriter::flush`. If `BufWriter` ever
// offers a raw buffer access API, we can use it, and remove this.
}
}
+ // If we've already had an error, do nothing. It'll get reported after
+ // `finish` is called.
+ if self.res.is_err() {
+ return;
+ }
+
let mut guard = BufGuard::new(
unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[..self.buffered]) },
&mut self.buffered,
while !guard.done() {
match self.file.write(guard.remaining()) {
Ok(0) => {
- return Err(io::Error::new(
+ self.res = Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write the buffered data",
));
+ return;
}
Ok(n) => guard.consume(n),
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
- Err(e) => return Err(e),
+ Err(e) => {
+ self.res = Err(e);
+ return;
+ }
}
}
-
- Ok(())
}
#[inline]
}
#[inline]
- fn write_one(&mut self, value: u8) -> FileEncodeResult {
+ fn write_one(&mut self, value: u8) {
// We ensure this during `FileEncoder` construction.
debug_assert!(self.capacity() >= 1);
let mut buffered = self.buffered;
if std::intrinsics::unlikely(buffered >= self.capacity()) {
- self.flush()?;
+ self.flush();
buffered = 0;
}
}
self.buffered = buffered + 1;
-
- Ok(())
}
#[inline]
- fn write_all(&mut self, buf: &[u8]) -> FileEncodeResult {
+ fn write_all(&mut self, buf: &[u8]) {
let capacity = self.capacity();
let buf_len = buf.len();
let mut buffered = self.buffered;
if std::intrinsics::unlikely(buf_len > capacity - buffered) {
- self.flush()?;
+ self.flush();
buffered = 0;
}
}
self.buffered = buffered + buf_len;
-
- Ok(())
} else {
- self.write_all_unbuffered(buf)
+ self.write_all_unbuffered(buf);
}
}
- fn write_all_unbuffered(&mut self, mut buf: &[u8]) -> FileEncodeResult {
+ fn write_all_unbuffered(&mut self, mut buf: &[u8]) {
+ // If we've already had an error, do nothing. It'll get reported after
+ // `finish` is called.
+ if self.res.is_err() {
+ return;
+ }
+
if self.buffered > 0 {
- self.flush()?;
+ self.flush();
}
// This is basically a copy of `Write::write_all` but also updates our
while !buf.is_empty() {
match self.file.write(buf) {
Ok(0) => {
- return Err(io::Error::new(
+ self.res = Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
+ return;
}
Ok(n) => {
buf = &buf[n..];
self.flushed += n;
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
- Err(e) => return Err(e),
+ Err(e) => {
+ self.res = Err(e);
+ return;
+ }
}
}
+ }
+
+ pub fn finish(mut self) -> Result<usize, io::Error> {
+ self.flush();
- Ok(())
+ let res = std::mem::replace(&mut self.res, Ok(()));
+ res.map(|()| self.position())
}
}
impl Drop for FileEncoder {
fn drop(&mut self) {
+ // Likely to be a no-op, because `finish` should have been called and
+ // it also flushes. But do it just in case.
let _result = self.flush();
}
}
// This can't overflow. See assertion in `FileEncoder::with_capacity`.
if std::intrinsics::unlikely(buffered + MAX_ENCODED_LEN > $enc.capacity()) {
- $enc.flush()?;
+ $enc.flush();
buffered = 0;
}
let encoded = leb128::$fun(buf, $value);
$enc.buffered = buffered + encoded.len();
-
- Ok(())
}};
}
-impl serialize::Encoder for FileEncoder {
- type Error = io::Error;
-
- #[inline]
- fn emit_unit(&mut self) -> FileEncodeResult {
- Ok(())
- }
-
+impl Encoder for FileEncoder {
#[inline]
- fn emit_usize(&mut self, v: usize) -> FileEncodeResult {
+ fn emit_usize(&mut self, v: usize) {
file_encoder_write_leb128!(self, v, usize, write_usize_leb128)
}
#[inline]
- fn emit_u128(&mut self, v: u128) -> FileEncodeResult {
+ fn emit_u128(&mut self, v: u128) {
file_encoder_write_leb128!(self, v, u128, write_u128_leb128)
}
#[inline]
- fn emit_u64(&mut self, v: u64) -> FileEncodeResult {
+ fn emit_u64(&mut self, v: u64) {
file_encoder_write_leb128!(self, v, u64, write_u64_leb128)
}
#[inline]
- fn emit_u32(&mut self, v: u32) -> FileEncodeResult {
+ fn emit_u32(&mut self, v: u32) {
file_encoder_write_leb128!(self, v, u32, write_u32_leb128)
}
#[inline]
- fn emit_u16(&mut self, v: u16) -> FileEncodeResult {
- self.write_all(&v.to_le_bytes())
+ fn emit_u16(&mut self, v: u16) {
+ self.write_all(&v.to_le_bytes());
}
#[inline]
- fn emit_u8(&mut self, v: u8) -> FileEncodeResult {
- self.write_one(v)
+ fn emit_u8(&mut self, v: u8) {
+ self.write_one(v);
}
#[inline]
- fn emit_isize(&mut self, v: isize) -> FileEncodeResult {
+ fn emit_isize(&mut self, v: isize) {
file_encoder_write_leb128!(self, v, isize, write_isize_leb128)
}
#[inline]
- fn emit_i128(&mut self, v: i128) -> FileEncodeResult {
+ fn emit_i128(&mut self, v: i128) {
file_encoder_write_leb128!(self, v, i128, write_i128_leb128)
}
#[inline]
- fn emit_i64(&mut self, v: i64) -> FileEncodeResult {
+ fn emit_i64(&mut self, v: i64) {
file_encoder_write_leb128!(self, v, i64, write_i64_leb128)
}
#[inline]
- fn emit_i32(&mut self, v: i32) -> FileEncodeResult {
+ fn emit_i32(&mut self, v: i32) {
file_encoder_write_leb128!(self, v, i32, write_i32_leb128)
}
#[inline]
- fn emit_i16(&mut self, v: i16) -> FileEncodeResult {
- self.write_all(&v.to_le_bytes())
+ fn emit_i16(&mut self, v: i16) {
+ self.write_all(&v.to_le_bytes());
}
#[inline]
- fn emit_i8(&mut self, v: i8) -> FileEncodeResult {
- self.emit_u8(v as u8)
+ fn emit_i8(&mut self, v: i8) {
+ self.emit_u8(v as u8);
}
#[inline]
- fn emit_bool(&mut self, v: bool) -> FileEncodeResult {
- self.emit_u8(if v { 1 } else { 0 })
+ fn emit_bool(&mut self, v: bool) {
+ self.emit_u8(if v { 1 } else { 0 });
}
#[inline]
- fn emit_f64(&mut self, v: f64) -> FileEncodeResult {
+ fn emit_f64(&mut self, v: f64) {
let as_u64: u64 = v.to_bits();
- self.emit_u64(as_u64)
+ self.emit_u64(as_u64);
}
#[inline]
- fn emit_f32(&mut self, v: f32) -> FileEncodeResult {
+ fn emit_f32(&mut self, v: f32) {
let as_u32: u32 = v.to_bits();
- self.emit_u32(as_u32)
+ self.emit_u32(as_u32);
}
#[inline]
- fn emit_char(&mut self, v: char) -> FileEncodeResult {
- self.emit_u32(v as u32)
+ fn emit_char(&mut self, v: char) {
+ self.emit_u32(v as u32);
}
#[inline]
- fn emit_str(&mut self, v: &str) -> FileEncodeResult {
- self.emit_usize(v.len())?;
- self.emit_raw_bytes(v.as_bytes())?;
- self.emit_u8(STR_SENTINEL)
+ fn emit_str(&mut self, v: &str) {
+ self.emit_usize(v.len());
+ self.emit_raw_bytes(v.as_bytes());
+ self.emit_u8(STR_SENTINEL);
}
#[inline]
- fn emit_raw_bytes(&mut self, s: &[u8]) -> FileEncodeResult {
- self.write_all(s)
+ fn emit_raw_bytes(&mut self, s: &[u8]) {
+ self.write_all(s);
}
}
// Decoder
// -----------------------------------------------------------------------------
-pub struct Decoder<'a> {
+pub struct MemDecoder<'a> {
pub data: &'a [u8],
position: usize,
}
-impl<'a> Decoder<'a> {
+impl<'a> MemDecoder<'a> {
#[inline]
- pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> {
- Decoder { data, position }
+ pub fn new(data: &'a [u8], position: usize) -> MemDecoder<'a> {
+ MemDecoder { data, position }
}
#[inline]
($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }};
}
-impl<'a> serialize::Decoder for Decoder<'a> {
+impl<'a> Decoder for MemDecoder<'a> {
#[inline]
fn read_u128(&mut self) -> u128 {
read_leb128!(self, read_u128_leb128)
// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
// since the default implementations call `encode` on their slices internally.
-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)
+impl Encodable<MemEncoder> for [u8] {
+ fn encode(&self, e: &mut MemEncoder) {
+ Encoder::emit_usize(e, self.len());
+ e.emit_raw_bytes(self);
}
}
-impl serialize::Encodable<FileEncoder> for [u8] {
- fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
- serialize::Encoder::emit_usize(e, self.len())?;
- e.emit_raw_bytes(self)
+impl Encodable<FileEncoder> for [u8] {
+ fn encode(&self, e: &mut FileEncoder) {
+ Encoder::emit_usize(e, self.len());
+ e.emit_raw_bytes(self);
}
}
// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
// since the default implementations call `decode` to produce a `Vec<u8>` internally.
-impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
- fn decode(d: &mut Decoder<'a>) -> Self {
- let len = serialize::Decoder::read_usize(d);
+impl<'a> Decodable<MemDecoder<'a>> for Vec<u8> {
+ fn decode(d: &mut MemDecoder<'a>) -> Self {
+ let len = Decoder::read_usize(d);
d.read_raw_bytes(len).to_owned()
}
}
pub const ENCODED_SIZE: usize = 8;
}
-impl serialize::Encodable<Encoder> for IntEncodedWithFixedSize {
+impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
#[inline]
- fn encode(&self, e: &mut Encoder) -> EncodeResult {
+ fn encode(&self, e: &mut MemEncoder) {
let _start_pos = e.position();
- e.emit_raw_bytes(&self.0.to_le_bytes())?;
+ 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 {
+impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
#[inline]
- fn encode(&self, e: &mut FileEncoder) -> FileEncodeResult {
+ fn encode(&self, e: &mut FileEncoder) {
let _start_pos = e.position();
- e.emit_raw_bytes(&self.0.to_le_bytes())?;
+ 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 {
+impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize {
#[inline]
- fn decode(decoder: &mut Decoder<'a>) -> IntEncodedWithFixedSize {
+ fn decode(decoder: &mut MemDecoder<'a>) -> IntEncodedWithFixedSize {
let _start_pos = decoder.position();
let bytes = decoder.read_raw_bytes(IntEncodedWithFixedSize::ENCODED_SIZE);
let value = u64::from_le_bytes(bytes.try_into().unwrap());