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}