Skip to main content

ingot_types/
emit.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use super::*;
6
7/// Serialise a network packet/header into a byte buffer.
8pub trait Emit: HeaderLen {
9    /// Writes this packet's contents into a target buffer without
10    /// performing length checks.
11    ///
12    /// `buf` must have a length equal to [`Header::packet_length`].
13    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize;
14
15    /// Returns whether this packet needs a full re-emit, and
16    /// has not been simply modified in-place.
17    ///
18    /// A header requires a full emit if it is either owned, or
19    /// a variable-length field needs to be emitted.
20    fn needs_emit(&self) -> bool;
21
22    /// Writes this packet's contents into a target buffer.
23    #[inline]
24    fn emit<V: ByteSliceMut>(&self, buf: V) -> ParseResult<usize> {
25        if buf.len() != self.packet_length() {
26            return Err(ParseError::TooSmall);
27        }
28
29        Ok(self.emit_raw(buf))
30    }
31
32    /// Writes this packet's contents into the start of a target buffer.
33    #[inline]
34    fn emit_prefix<V: SplitByteSliceMut>(&self, buf: V) -> ParseResult<V> {
35        let (into, out) = buf
36            .split_at(self.packet_length())
37            .map_err(|_| ParseError::TooSmall)?;
38
39        self.emit_raw(into);
40        Ok(out)
41    }
42
43    /// Writes this packet's contents at the end of a target buffer.
44    #[inline]
45    fn emit_suffix<V: SplitByteSliceMut>(&self, buf: V) -> ParseResult<V> {
46        let l = buf.len();
47
48        let (into, out) = buf
49            .split_at(l - self.packet_length())
50            .map_err(|_| ParseError::TooSmall)?;
51
52        self.emit_raw(into);
53
54        Ok(out)
55    }
56
57    /// Writes this packet's contents into a newly allocated `Vec` of length
58    /// [`Header::packet_length`].
59    ///
60    /// Prefer [`Self::emit_vec`] when it is available. This method
61    /// zero-initialises memory, whereas `emit_vec` avoids doing so if
62    /// the type has declared its `emit_raw` can handle this case soundly.
63    #[inline]
64    fn to_vec(&self) -> Vec<u8> {
65        let len = self.packet_length();
66
67        let mut out = vec![0u8; len];
68
69        let o_len = self.emit(&mut out[..]).expect(
70            "mismatch between packet requested length and required length",
71        );
72
73        assert_eq!(o_len, len);
74
75        out
76    }
77
78    /// Writes this packet's contents into uninitialised memory.
79    #[inline]
80    fn emit_uninit(&self, buf: &mut [MaybeUninit<u8>]) -> ParseResult<usize>
81    where
82        Self: EmitDoesNotRelyOnBufContents,
83    {
84        // SAFETY: `u8` does not have any validity constraints or Drop.
85        // Accordingly, assuming their initialisation will not trigger
86        // any adverse dropck behaviour, and any value is trivially a valid u8.
87        // We are here if the implementor *promises* not to rely on
88        // buf's contents.
89        // We do not return a reference to the initialised region,
90        // it is up to the caller to inform their datastructure that
91        // bytes are initialised.
92
93        // NOTE: reimpl'ing `slice_assume_init_mut` (unstable).
94        let buf = unsafe { &mut *(buf as *mut [_] as *mut [u8]) };
95
96        self.emit(buf)
97    }
98
99    /// Writes this packet's contents into a newly allocated `Vec` of length
100    /// [`Header::packet_length`], without zero-filling the contents.
101    ///
102    /// This method is faster than [`Emit::to_vec`], but requires programmer
103    /// assurance via [`EmitDoesNotRelyOnBufContents`].
104    #[inline]
105    fn emit_vec(&self) -> Vec<u8>
106    where
107        Self: EmitDoesNotRelyOnBufContents,
108    {
109        let len = self.packet_length();
110
111        let mut out = Vec::with_capacity(len);
112
113        let o_len = self.emit_uninit(out.spare_capacity_mut()).expect(
114            "mismatch between packet requested length and required length",
115        );
116        assert_eq!(o_len, len);
117        unsafe {
118            out.set_len(o_len);
119        }
120
121        out
122    }
123}
124
125impl<T: Emit> Emit for Vec<T> {
126    #[inline]
127    fn emit_raw<V: ByteSliceMut>(&self, mut buf: V) -> usize {
128        let mut emitted = 0;
129
130        for el in self {
131            emitted += el.emit_raw(&mut buf[emitted..]);
132        }
133
134        emitted
135    }
136
137    #[inline]
138    fn needs_emit(&self) -> bool {
139        true
140    }
141}
142
143impl<T: Emit> Emit for Option<T> {
144    #[inline]
145    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
146        self.as_ref().map(|e| e.emit_raw(buf)).unwrap_or(0)
147    }
148
149    fn needs_emit(&self) -> bool {
150        self.as_ref().map(T::needs_emit).unwrap_or(false)
151    }
152}
153
154impl Emit for &[u8] {
155    #[inline]
156    fn emit_raw<V: ByteSliceMut>(&self, mut buf: V) -> usize {
157        buf[..self.len()].copy_from_slice(self);
158
159        self.len()
160    }
161
162    #[inline]
163    fn needs_emit(&self) -> bool {
164        false
165    }
166}
167
168impl Emit for Vec<u8> {
169    #[inline]
170    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
171        self.as_slice().emit_raw(buf)
172    }
173
174    #[inline]
175    fn needs_emit(&self) -> bool {
176        true
177    }
178}
179
180impl<E: Emit> Emit for &E {
181    #[inline]
182    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
183        E::emit_raw(self, buf)
184    }
185
186    #[inline]
187    fn needs_emit(&self) -> bool {
188        E::needs_emit(self)
189    }
190}
191
192/// A promise from the programmer to the compiler that an implementation
193/// of [`Emit`] does not perform any reads from uninitialised memory.
194///
195/// # Safety
196/// Implementors will be given an uninitialised slice of bytes, and must
197/// not meaningfully read from its contents. They are obligated, when
198/// implementing [`Emit`], to have written a value to all bytes when
199/// given a slice by `emit_uninit`.
200pub unsafe trait EmitDoesNotRelyOnBufContents {}
201
202// Safety: We know this holds true for all our derived emits, by design.
203unsafe impl<E: Emit + EmitDoesNotRelyOnBufContents> EmitDoesNotRelyOnBufContents
204    for &E
205{
206}
207unsafe impl EmitDoesNotRelyOnBufContents for &[u8] {}
208unsafe impl EmitDoesNotRelyOnBufContents for Vec<u8> {}
209unsafe impl<T: EmitDoesNotRelyOnBufContents> EmitDoesNotRelyOnBufContents
210    for Vec<T>
211{
212}
213unsafe impl<T: EmitDoesNotRelyOnBufContents> EmitDoesNotRelyOnBufContents
214    for Option<T>
215{
216}