Auto merge of #83273 - cjgillot:endecode, r=michaelwoerister

Simplify encoder and decoder

Extracted from https://github.com/rust-lang/rust/pull/83036 and https://github.com/rust-lang/rust/pull/82780.
This commit is contained in:
bors 2021-03-22 12:18:57 +00:00
commit d04c3aa865
11 changed files with 126 additions and 158 deletions

View file

@ -1,8 +1,5 @@
use crate::stable_hasher; use crate::stable_hasher;
use rustc_serialize::{ use rustc_serialize::{Decodable, Encodable};
opaque::{self, EncodeResult, FileEncodeResult},
Decodable, Encodable,
};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::mem::{self, MaybeUninit}; use std::mem::{self, MaybeUninit};
@ -63,16 +60,6 @@ pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint {
pub fn to_hex(&self) -> String { pub fn to_hex(&self) -> String {
format!("{:x}{:x}", self.0, self.1) format!("{:x}{:x}", self.0, self.1)
} }
pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array();
decoder.read_raw_bytes(&mut bytes)?;
let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
}
} }
impl std::fmt::Display for Fingerprint { impl std::fmt::Display for Fingerprint {
@ -130,55 +117,22 @@ fn finish(hasher: stable_hasher::StableHasher) -> Self {
impl_stable_hash_via_hash!(Fingerprint); impl_stable_hash_via_hash!(Fingerprint);
impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint { impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
#[inline]
fn encode(&self, s: &mut E) -> Result<(), E::Error> { fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.encode_fingerprint(self) let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
} s.emit_raw_bytes(&bytes)?;
}
impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
fn decode(d: &mut D) -> Result<Self, D::Error> {
d.decode_fingerprint()
}
}
pub trait FingerprintEncoder: rustc_serialize::Encoder {
fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>;
}
pub trait FingerprintDecoder: rustc_serialize::Decoder {
fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error>;
}
impl<E: rustc_serialize::Encoder> FingerprintEncoder for E {
default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> {
panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::<E>());
}
}
impl FingerprintEncoder for opaque::Encoder {
fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult {
let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) };
self.emit_raw_bytes(&bytes);
Ok(()) Ok(())
} }
} }
impl FingerprintEncoder for opaque::FileEncoder { impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
fn encode_fingerprint(&mut self, f: &Fingerprint) -> FileEncodeResult { #[inline]
let bytes: [u8; 16] = unsafe { mem::transmute([f.0.to_le(), f.1.to_le()]) }; fn decode(d: &mut D) -> Result<Self, D::Error> {
self.emit_raw_bytes(&bytes) let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array();
} d.read_raw_bytes(&mut bytes)?;
}
impl<D: rustc_serialize::Decoder> FingerprintDecoder for D { let [l, r]: [u64; 2] = unsafe { mem::transmute(bytes) };
default fn decode_fingerprint(&mut self) -> Result<Fingerprint, D::Error> { Ok(Fingerprint(u64::from_le(l), u64::from_le(r)))
panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::<D>());
}
}
impl FingerprintDecoder for opaque::Decoder<'_> {
fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
Fingerprint::decode_opaque(self)
} }
} }

View file

@ -15,6 +15,7 @@
use std::path::Path; use std::path::Path;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::Encoder;
/// The first few bytes of files generated by incremental compilation. /// The first few bytes of files generated by incremental compilation.
const FILE_MAGIC: &[u8] = b"RSIC"; const FILE_MAGIC: &[u8] = b"RSIC";

View file

@ -7,7 +7,6 @@
use rustc_ast as ast; use rustc_ast as ast;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh; use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell};
@ -351,12 +350,6 @@ fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefIndex, String> {
} }
} }
impl<'a, 'tcx> FingerprintDecoder for DecodeContext<'a, 'tcx> {
fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
Fingerprint::decode_opaque(&mut self.opaque)
}
}
impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext { impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> { fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> {
let cdata = decoder.cdata(); let cdata = decoder.cdata();

View file

@ -1,7 +1,6 @@
use crate::rmeta::table::{FixedSizeEncoding, TableBuilder}; use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
use crate::rmeta::*; use crate::rmeta::*;
use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
@ -116,6 +115,7 @@ fn emit_unit(&mut self) -> Result<(), Self::Error> {
emit_f32(f32); emit_f32(f32);
emit_char(char); emit_char(char);
emit_str(&str); emit_str(&str);
emit_raw_bytes(&[u8]);
} }
} }
@ -307,12 +307,6 @@ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
} }
} }
impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> {
fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
self.opaque.encode_fingerprint(f)
}
}
impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
const CLEAR_CROSS_CRATE: bool = true; const CLEAR_CROSS_CRATE: bool = true;
@ -2064,10 +2058,10 @@ pub(super) fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata {
fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
let mut encoder = opaque::Encoder::new(vec![]); let mut encoder = opaque::Encoder::new(vec![]);
encoder.emit_raw_bytes(METADATA_HEADER); encoder.emit_raw_bytes(METADATA_HEADER).unwrap();
// Will be filled with the root position after encoding everything. // Will be filled with the root position after encoding everything.
encoder.emit_raw_bytes(&[0, 0, 0, 0]); encoder.emit_raw_bytes(&[0, 0, 0, 0]).unwrap();
let source_map_files = tcx.sess.source_map().files(); let source_map_files = tcx.sess.source_map().files();
let source_file_cache = (source_map_files[0].clone(), 0); let source_file_cache = (source_map_files[0].clone(), 0);

View file

@ -2,6 +2,7 @@
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_serialize::opaque::Encoder; use rustc_serialize::opaque::Encoder;
use rustc_serialize::Encoder as _;
use std::convert::TryInto; use std::convert::TryInto;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
@ -172,7 +173,7 @@ pub(crate) fn set(&mut self, i: I, value: T) {
pub(crate) fn encode(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> { pub(crate) fn encode(&self, buf: &mut Encoder) -> Lazy<Table<I, T>> {
let pos = buf.position(); let pos = buf.position();
buf.emit_raw_bytes(&self.bytes); buf.emit_raw_bytes(&self.bytes).unwrap();
Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), self.bytes.len()) Lazy::from_position_and_meta(NonZeroUsize::new(pos as usize).unwrap(), self.bytes.len())
} }
} }

View file

@ -472,6 +472,11 @@ impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
read_str -> Cow<'_, str>; read_str -> Cow<'_, str>;
} }
#[inline]
fn read_raw_bytes(&mut self, bytes: &mut [std::mem::MaybeUninit<u8>]) -> Result<(), Self::Error> {
self.opaque.read_raw_bytes(bytes)
}
fn error(&mut self, err: &str) -> Self::Error { fn error(&mut self, err: &str) -> Self::Error {
self.opaque.error(err) self.opaque.error(err)
} }

View file

@ -4,7 +4,6 @@
use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder}; use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use crate::ty::context::TyCtxt; use crate::ty::context::TyCtxt;
use crate::ty::{self, Ty}; use crate::ty::{self, Ty};
use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell}; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
@ -17,7 +16,7 @@
use rustc_query_system::dep_graph::DepContext; use rustc_query_system::dep_graph::DepContext;
use rustc_query_system::query::QueryContext; use rustc_query_system::query::QueryContext;
use rustc_serialize::{ use rustc_serialize::{
opaque::{self, FileEncodeResult, FileEncoder}, opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
Decodable, Decoder, Encodable, Encoder, Decodable, Decoder, Encodable, Encoder,
}; };
use rustc_session::{CrateDisambiguator, Session}; use rustc_session::{CrateDisambiguator, Session};
@ -913,12 +912,6 @@ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
} }
} }
impl<'a, 'tcx> FingerprintDecoder for CacheDecoder<'a, 'tcx> {
fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error> {
Fingerprint::decode_opaque(&mut self.opaque)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> { impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
RefDecodable::decode(d) RefDecodable::decode(d)
@ -1011,12 +1004,6 @@ fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
} }
} }
impl<'a, 'tcx, E: OpaqueEncoder> FingerprintEncoder for CacheEncoder<'a, 'tcx, E> {
fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), E::Error> {
self.encoder.encode_fingerprint(f)
}
}
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
where where
E: 'a + OpaqueEncoder, E: 'a + OpaqueEncoder,
@ -1167,6 +1154,7 @@ fn emit_unit(&mut self) -> Result<(), Self::Error> {
emit_f32(f32); emit_f32(f32);
emit_char(char); emit_char(char);
emit_str(&str); emit_str(&str);
emit_raw_bytes(&[u8]);
} }
} }
@ -1180,42 +1168,6 @@ fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) -> FileEncodeResul
} }
} }
// An integer that will always encode to 8 bytes.
struct IntEncodedWithFixedSize(u64);
impl IntEncodedWithFixedSize {
pub const ENCODED_SIZE: usize = 8;
}
impl<E: OpaqueEncoder> Encodable<E> for IntEncodedWithFixedSize {
fn encode(&self, e: &mut E) -> Result<(), E::Error> {
let start_pos = e.position();
for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
((self.0 >> (i * 8)) as u8).encode(e)?;
}
let end_pos = e.position();
assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
}
}
impl<'a> Decodable<opaque::Decoder<'a>> for IntEncodedWithFixedSize {
fn decode(decoder: &mut opaque::Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> {
let mut value: u64 = 0;
let start_pos = decoder.position();
for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
let byte: u8 = Decodable::decode(decoder)?;
value |= (byte as u64) << (i * 8);
}
let end_pos = decoder.position();
assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(IntEncodedWithFixedSize(value))
}
}
pub fn encode_query_results<'a, 'tcx, CTX, Q>( pub fn encode_query_results<'a, 'tcx, CTX, Q>(
tcx: CTX, tcx: CTX,
encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>,

View file

@ -188,6 +188,7 @@
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::mem::swap; use std::mem::swap;
use std::mem::MaybeUninit;
use std::num::FpCategory as Fp; use std::num::FpCategory as Fp;
use std::ops::Index; use std::ops::Index;
use std::str::FromStr; use std::str::FromStr;
@ -553,6 +554,12 @@ fn emit_char(&mut self, v: char) -> EncodeResult {
fn emit_str(&mut self, v: &str) -> EncodeResult { fn emit_str(&mut self, v: &str) -> EncodeResult {
escape_str(self.writer, v) escape_str(self.writer, v)
} }
fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
for &c in s.iter() {
self.emit_u8(c)?;
}
Ok(())
}
fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
where where
@ -879,6 +886,12 @@ fn emit_char(&mut self, v: char) -> EncodeResult {
fn emit_str(&mut self, v: &str) -> EncodeResult { fn emit_str(&mut self, v: &str) -> EncodeResult {
escape_str(self.writer, v) escape_str(self.writer, v)
} }
fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error> {
for &c in s.iter() {
self.emit_u8(c)?;
}
Ok(())
}
fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
where where
@ -2354,6 +2367,14 @@ fn read_str(&mut self) -> DecodeResult<Cow<'_, str>> {
expect!(self.pop(), String).map(Cow::Owned) expect!(self.pop(), String).map(Cow::Owned)
} }
fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), Self::Error> {
for c in s.iter_mut() {
let h = self.read_u8()?;
unsafe { *c.as_mut_ptr() = h };
}
Ok(())
}
fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T> fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T>
where where
F: FnOnce(&mut Decoder) -> DecodeResult<T>, F: FnOnce(&mut Decoder) -> DecodeResult<T>,

View file

@ -17,6 +17,8 @@
#![feature(vec_spare_capacity)] #![feature(vec_spare_capacity)]
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
#![feature(int_bits_const)] #![feature(int_bits_const)]
#![feature(maybe_uninit_array_assume_init)]
#![feature(maybe_uninit_uninit_array)]
#![feature(maybe_uninit_slice)] #![feature(maybe_uninit_slice)]
#![feature(new_uninit)] #![feature(new_uninit)]
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]

View file

@ -1,5 +1,5 @@
use crate::leb128::{self, max_leb128_len}; use crate::leb128::{self, max_leb128_len};
use crate::serialize; use crate::serialize::{self, Decoder as _, Encoder as _};
use std::borrow::Cow; use std::borrow::Cow;
use std::fs::File; use std::fs::File;
use std::io::{self, Write}; use std::io::{self, Write};
@ -30,11 +30,6 @@ pub fn into_inner(self) -> Vec<u8> {
pub fn position(&self) -> usize { pub fn position(&self) -> usize {
self.data.len() self.data.len()
} }
#[inline]
pub fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s);
}
} }
macro_rules! write_leb128 { macro_rules! write_leb128 {
@ -154,7 +149,12 @@ fn emit_char(&mut self, v: char) -> EncodeResult {
#[inline] #[inline]
fn emit_str(&mut self, v: &str) -> EncodeResult { fn emit_str(&mut self, v: &str) -> EncodeResult {
self.emit_usize(v.len())?; 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(()) Ok(())
} }
} }
@ -208,11 +208,6 @@ pub fn position(&self) -> usize {
self.flushed + self.buffered 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 { pub fn flush(&mut self) -> FileEncodeResult {
// This is basically a copy of `BufWriter::flush`. If `BufWriter` ever // This is basically a copy of `BufWriter::flush`. If `BufWriter` ever
// offers a raw buffer access API, we can use it, and remove this. // offers a raw buffer access API, we can use it, and remove this.
@ -508,6 +503,11 @@ fn emit_str(&mut self, v: &str) -> FileEncodeResult {
self.emit_usize(v.len())?; 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]) -> FileEncodeResult {
self.write_all(s)
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -539,26 +539,6 @@ pub fn set_position(&mut self, pos: usize) {
pub fn advance(&mut self, bytes: usize) { pub fn advance(&mut self, bytes: usize) {
self.position += bytes; self.position += bytes;
} }
#[inline]
pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
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(())
}
} }
macro_rules! read_leb128 { macro_rules! read_leb128 {
@ -677,6 +657,26 @@ fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error> {
fn error(&mut self, err: &str) -> Self::Error { fn error(&mut self, err: &str) -> Self::Error {
err.to_string() err.to_string()
} }
#[inline]
fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
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(())
}
} }
// Specializations for contiguous byte sequences follow. The default implementations for slices // Specializations for contiguous byte sequences follow. The default implementations for slices
@ -689,8 +689,7 @@ fn error(&mut self, err: &str) -> Self::Error {
impl serialize::Encodable<Encoder> for [u8] { impl serialize::Encodable<Encoder> for [u8] {
fn encode(&self, e: &mut Encoder) -> EncodeResult { fn encode(&self, e: &mut Encoder) -> EncodeResult {
serialize::Encoder::emit_usize(e, self.len())?; serialize::Encoder::emit_usize(e, self.len())?;
e.emit_raw_bytes(self); e.emit_raw_bytes(self)
Ok(())
} }
} }
@ -718,3 +717,46 @@ fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
Ok(v) Ok(v)
} }
} }
// An integer that will always encode to 8 bytes.
pub struct IntEncodedWithFixedSize(pub u64);
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 mut bytes = MaybeUninit::uninit_array();
let _start_pos = decoder.position();
decoder.read_raw_bytes(&mut bytes)?;
let _end_pos = decoder.position();
debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
let value = u64::from_le_bytes(unsafe { MaybeUninit::array_assume_init(bytes) });
Ok(IntEncodedWithFixedSize(value))
}
}

View file

@ -7,6 +7,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::path; use std::path;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -33,6 +34,7 @@ pub trait Encoder {
fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>; fn emit_f32(&mut self, v: f32) -> Result<(), Self::Error>;
fn emit_char(&mut self, v: char) -> Result<(), Self::Error>; fn emit_char(&mut self, v: char) -> Result<(), Self::Error>;
fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>;
fn emit_raw_bytes(&mut self, s: &[u8]) -> Result<(), Self::Error>;
// Compound types: // Compound types:
#[inline] #[inline]
@ -224,6 +226,7 @@ pub trait Decoder {
fn read_f32(&mut self) -> Result<f32, Self::Error>; fn read_f32(&mut self) -> Result<f32, Self::Error>;
fn read_char(&mut self) -> Result<char, Self::Error>; fn read_char(&mut self) -> Result<char, Self::Error>;
fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error>; fn read_str(&mut self) -> Result<Cow<'_, str>, Self::Error>;
fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), Self::Error>;
// Compound types: // Compound types:
#[inline] #[inline]