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 Emit for &[u8] {
144    #[inline]
145    fn emit_raw<V: ByteSliceMut>(&self, mut buf: V) -> usize {
146        buf[..self.len()].copy_from_slice(self);
147
148        self.len()
149    }
150
151    #[inline]
152    fn needs_emit(&self) -> bool {
153        false
154    }
155}
156
157impl Emit for Vec<u8> {
158    #[inline]
159    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
160        self.as_slice().emit_raw(buf)
161    }
162
163    #[inline]
164    fn needs_emit(&self) -> bool {
165        true
166    }
167}
168
169impl<E: Emit> Emit for &E {
170    #[inline]
171    fn emit_raw<V: ByteSliceMut>(&self, buf: V) -> usize {
172        E::emit_raw(self, buf)
173    }
174
175    #[inline]
176    fn needs_emit(&self) -> bool {
177        E::needs_emit(self)
178    }
179}
180
181/// A promise from the programmer to the compiler that an implementation
182/// of [`Emit`] does not perform any reads from uninitialised memory.
183///
184/// # Safety
185/// Implementors will be given an uninitialised slice of bytes, and must
186/// not meaningfully read from its contents. They are obligated, when
187/// implementing [`Emit`], to have written a value to all bytes when
188/// given a slice by `emit_uninit`.
189pub unsafe trait EmitDoesNotRelyOnBufContents {}
190
191// Safety: We know this holds true for all our derived emits, by design.
192unsafe impl<E: Emit + EmitDoesNotRelyOnBufContents> EmitDoesNotRelyOnBufContents
193    for &E
194{
195}
196unsafe impl EmitDoesNotRelyOnBufContents for &[u8] {}
197unsafe impl EmitDoesNotRelyOnBufContents for Vec<u8> {}
198unsafe impl<T: EmitDoesNotRelyOnBufContents> EmitDoesNotRelyOnBufContents
199    for Vec<T>
200{
201}