1use super::IntEncodedWithFixedSize;
2use crate::{Encodable, Encoder, leb128};
34pub struct MemEncoder {
5pub data: Vec<u8>,
6}
78impl MemEncoder {
9pub fn new() -> MemEncoder {
10MemEncoder { data: ::alloc::vec::Vec::new()vec![] }
11 }
1213#[inline]
14pub fn position(&self) -> usize {
15self.data.len()
16 }
1718pub fn finish(self) -> Vec<u8> {
19self.data
20 }
2122/// Write up to `N` bytes to this encoder.
23 ///
24 /// This function can be used to avoid the overhead of calling memcpy for writes that
25 /// have runtime-variable length, but are small and have a small fixed upper bound.
26 ///
27 /// This can be used to do in-place encoding as is done for leb128 (without this function
28 /// we would need to write to a temporary buffer then memcpy into the encoder), and it can
29 /// also be used to implement the varint scheme we use for rmeta and dep graph encoding,
30 /// where we only want to encode the first few bytes of an integer. Note that common
31 /// architectures support fixed-size writes up to 8 bytes with one instruction, so while this
32 /// does in some sense do wasted work, we come out ahead.
33#[inline]
34pub fn write_with<const N: usize>(&mut self, visitor: impl FnOnce(&mut [u8; N]) -> usize) {
35self.data.reserve(N);
3637let old_len = self.data.len();
3839// SAFETY: The above `reserve` ensures that there is enough
40 // room to write the encoded value to the vector's internal buffer.
41 // The memory is also initialized as 0.
42let buf = unsafe {
43let buf = self.data.as_mut_ptr().add(old_len) as *mut [u8; N];
44*buf = [0; N];
45&mut *buf46 };
47let written = visitor(buf);
48if written > N {
49Self::panic_invalid_write::<N>(written);
50 }
51unsafe { self.data.set_len(old_len + written) };
52 }
5354#[cold]
55 #[inline(never)]
56fn panic_invalid_write<const N: usize>(written: usize) {
57{
::core::panicking::panic_fmt(format_args!("MemEncoder::write_with::<{0}> cannot be used to write {1} bytes",
N, written));
};panic!("MemEncoder::write_with::<{N}> cannot be used to write {written} bytes");
58 }
5960/// Helper for calls where [`MemEncoder::write_with`] always writes the whole array.
61#[inline]
62pub fn write_array<const N: usize>(&mut self, buf: [u8; N]) {
63self.write_with(|dest| {
64*dest = buf;
65N66 })
67 }
68}
6970macro_rules!write_leb128 {
71 ($this_fn:ident, $int_ty:ty, $write_leb_fn:ident) => {
72#[inline]
73fn $this_fn(&mut self, v: $int_ty) {
74self.write_with(|buf| leb128::$write_leb_fn(buf, v))
75 }
76 };
77}
7879impl Encoderfor MemEncoder {
80self
v
self.write_with(|buf| leb128::write_usize_leb128(buf, v));write_leb128!(emit_usize, usize, write_usize_leb128);
81self
v
self.write_with(|buf| leb128::write_u128_leb128(buf, v));write_leb128!(emit_u128, u128, write_u128_leb128);
82self
v
self.write_with(|buf| leb128::write_u64_leb128(buf, v));write_leb128!(emit_u64, u64, write_u64_leb128);
83self
v
self.write_with(|buf| leb128::write_u32_leb128(buf, v));write_leb128!(emit_u32, u32, write_u32_leb128);
8485#[inline]
86fn emit_u16(&mut self, v: u16) {
87self.write_array(v.to_le_bytes());
88 }
8990#[inline]
91fn emit_u8(&mut self, v: u8) {
92self.write_array([v]);
93 }
9495self
v
self.write_with(|buf| leb128::write_isize_leb128(buf, v));write_leb128!(emit_isize, isize, write_isize_leb128);
96self
v
self.write_with(|buf| leb128::write_i128_leb128(buf, v));write_leb128!(emit_i128, i128, write_i128_leb128);
97self
v
self.write_with(|buf| leb128::write_i64_leb128(buf, v));write_leb128!(emit_i64, i64, write_i64_leb128);
98self
v
self.write_with(|buf| leb128::write_i32_leb128(buf, v));write_leb128!(emit_i32, i32, write_i32_leb128);
99100#[inline]
101fn emit_i16(&mut self, v: i16) {
102self.write_array(v.to_le_bytes());
103 }
104105#[inline]
106fn emit_raw_bytes(&mut self, s: &[u8]) {
107self.data.extend_from_slice(s);
108 }
109}
110111// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
112// since the default implementations call `encode` on their slices internally.
113impl Encodable<MemEncoder> for [u8] {
114fn encode(&self, e: &mut MemEncoder) {
115 Encoder::emit_usize(e, self.len());
116e.emit_raw_bytes(self);
117 }
118}
119120impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
121#[inline]
122fn encode(&self, e: &mut MemEncoder) {
123let start_pos = e.position();
124e.write_array(self.0.to_le_bytes());
125let end_pos = e.position();
126if true {
match (&(end_pos - start_pos), &IntEncodedWithFixedSize::ENCODED_SIZE) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
};
};debug_assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
127 }
128}