wry_bindgen_runtime/wire/
ipc.rs1use alloc::string::{String, ToString};
11use alloc::vec::Vec;
12use core::fmt;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct DecodeError {
16 message: String,
17}
18
19impl DecodeError {
20 pub fn custom(message: impl Into<String>) -> Self {
21 Self {
22 message: message.into(),
23 }
24 }
25
26 pub(crate) fn message_too_short(expected: usize, actual: usize) -> Self {
27 Self::custom(
28 format_args!("message too short: expected at least {expected} bytes, got {actual}")
29 .to_string(),
30 )
31 }
32
33 pub(crate) fn u8_buffer_empty() -> Self {
34 Self::custom("u8 buffer empty when trying to read")
35 }
36
37 pub(crate) fn u16_buffer_empty() -> Self {
38 Self::custom("u16 buffer empty when trying to read")
39 }
40
41 pub(crate) fn u32_buffer_empty() -> Self {
42 Self::custom("u32 buffer empty when trying to read")
43 }
44
45 pub(crate) fn string_buffer_too_short(expected: usize, actual: usize) -> Self {
46 Self::custom(
47 format_args!("string buffer too short: expected {expected} bytes, got {actual}")
48 .to_string(),
49 )
50 }
51
52 pub(crate) fn invalid_utf8(position: usize) -> Self {
53 Self::custom(format_args!("invalid UTF-8 at position {position}").to_string())
54 }
55
56 pub(crate) fn invalid_header_offsets(
57 u16_offset: u32,
58 u8_offset: u32,
59 str_offset: u32,
60 total_len: usize,
61 ) -> Self {
62 Self::custom(format_args!(
63 "invalid header offsets: u16={u16_offset}, u8={u8_offset}, str={str_offset}, total_len={total_len}"
64 ).to_string())
65 }
66}
67
68impl fmt::Display for DecodeError {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 self.message.fmt(f)
71 }
72}
73
74impl core::error::Error for DecodeError {}
75
76impl From<DecodeError> for String {
77 fn from(err: DecodeError) -> String {
78 err.to_string()
79 }
80}
81
82pub struct DecodedData<'a> {
83 u8_buf: &'a [u8],
84 u16_buf: &'a [u16],
85 u32_buf: &'a [u32],
86 str_buf: &'a [u8],
87}
88
89impl<'a> DecodedData<'a> {
90 pub(crate) fn from_bytes(bytes: &'a [u8]) -> Result<Self, DecodeError> {
92 if bytes.len() < 12 {
93 return Err(DecodeError::message_too_short(12, bytes.len()));
94 }
95
96 let header: [u32; 3] = bytemuck::cast_slice(&bytes[0..12])
97 .try_into()
98 .map_err(|_| DecodeError::custom("failed to parse header"))?;
99 let [u16_offset, u8_offset, str_offset] = header;
100
101 let total_len = bytes.len();
103 if u16_offset as usize > total_len
104 || u8_offset as usize > total_len
105 || str_offset as usize > total_len
106 || u16_offset < 12
107 || u8_offset < u16_offset
108 || str_offset < u8_offset
109 {
110 return Err(DecodeError::invalid_header_offsets(
111 u16_offset, u8_offset, str_offset, total_len,
112 ));
113 }
114
115 let u32_buf = bytemuck::cast_slice(&bytes[12..u16_offset as usize]);
116 let u16_buf = bytemuck::cast_slice(&bytes[u16_offset as usize..u8_offset as usize]);
117 let u8_buf = &bytes[u8_offset as usize..str_offset as usize];
118 let str_buf = &bytes[str_offset as usize..];
119
120 Ok(Self {
121 u8_buf,
122 u16_buf,
123 u32_buf,
124 str_buf,
125 })
126 }
127
128 pub(crate) fn take_u8(&mut self) -> Result<u8, DecodeError> {
130 let [first, rest @ ..] = &self.u8_buf else {
131 return Err(DecodeError::u8_buffer_empty());
132 };
133 self.u8_buf = rest;
134 Ok(*first)
135 }
136
137 pub(crate) fn take_u16(&mut self) -> Result<u16, DecodeError> {
139 let [first, rest @ ..] = &self.u16_buf else {
140 return Err(DecodeError::u16_buffer_empty());
141 };
142 self.u16_buf = rest;
143 Ok(*first)
144 }
145
146 pub(crate) fn take_u32(&mut self) -> Result<u32, DecodeError> {
148 let [first, rest @ ..] = &self.u32_buf else {
149 return Err(DecodeError::u32_buffer_empty());
150 };
151 self.u32_buf = rest;
152 Ok(*first)
153 }
154
155 pub(crate) fn take_u64(&mut self) -> Result<u64, DecodeError> {
157 let low = self.take_u32()? as u64;
158 let high = self.take_u32()? as u64;
159 Ok((high << 32) | low)
160 }
161
162 pub(crate) fn take_u128(&mut self) -> Result<u128, DecodeError> {
164 let low = self.take_u64()? as u128;
165 let high = self.take_u64()? as u128;
166 Ok((high << 64) | low)
167 }
168
169 pub(crate) fn take_str(&mut self) -> Result<&'a str, DecodeError> {
171 let len = self.take_u32()? as usize;
172 let actual_len = self.str_buf.len();
173 let Some((buf, rem)) = self.str_buf.split_at_checked(len) else {
174 return Err(DecodeError::string_buffer_too_short(len, actual_len));
175 };
176 let s =
177 core::str::from_utf8(buf).map_err(|e| DecodeError::invalid_utf8(e.valid_up_to()))?;
178 self.str_buf = rem;
179 Ok(s)
180 }
181}
182
183#[derive(Default)]
184pub struct EncodedData {
185 u8_buf: Vec<u8>,
186 u16_buf: Vec<u16>,
187 u32_buf: Vec<u32>,
188 str_buf: Vec<u8>,
189 needs_flush: bool,
192}
193
194impl EncodedData {
195 #[doc(hidden)]
196 pub fn mark_needs_flush(&mut self) {
197 self.needs_flush = true;
198 }
199
200 pub(crate) fn take_needs_flush(&mut self) -> bool {
201 core::mem::take(&mut self.needs_flush)
202 }
203
204 pub(crate) fn push_u8(&mut self, value: u8) {
205 self.u8_buf.push(value);
206 }
207
208 pub(crate) fn push_u16(&mut self, value: u16) {
209 self.u16_buf.push(value);
210 }
211
212 pub(crate) fn push_u32(&mut self, value: u32) {
213 self.u32_buf.push(value);
214 }
215
216 pub(crate) fn push_u64(&mut self, value: u64) {
217 self.push_u32((value & 0xFFFFFFFF) as u32);
218 self.push_u32((value >> 32) as u32);
219 }
220
221 pub(crate) fn push_u128(&mut self, value: u128) {
222 self.push_u64((value & 0xFFFFFFFFFFFFFFFF) as u64);
223 self.push_u64((value >> 64) as u64);
224 }
225
226 pub(crate) fn push_str(&mut self, value: &str) {
227 let len = u32::try_from(value.len()).expect("string length exceeds u32::MAX");
228 self.push_u32(len);
229 self.str_buf.extend_from_slice(value.as_bytes());
230 }
231
232 pub(crate) fn into_bytes(self) -> Vec<u8> {
234 let u16_offset = 12 + self.u32_buf.len() * 4;
235 let u8_offset = u16_offset + self.u16_buf.len() * 2;
236 let str_offset = u8_offset + self.u8_buf.len();
237
238 let total_len = str_offset + self.str_buf.len();
239 let mut bytes = Vec::with_capacity(total_len);
240
241 bytes.extend_from_slice(&(u16_offset as u32).to_le_bytes());
243 bytes.extend_from_slice(&(u8_offset as u32).to_le_bytes());
244 bytes.extend_from_slice(&(str_offset as u32).to_le_bytes());
245
246 for &u in &self.u32_buf {
248 bytes.extend_from_slice(&u.to_le_bytes());
249 }
250
251 for &u in &self.u16_buf {
253 bytes.extend_from_slice(&u.to_le_bytes());
254 }
255
256 bytes.extend_from_slice(&self.u8_buf);
258
259 bytes.extend_from_slice(&self.str_buf);
261
262 bytes
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use super::*;
269
270 #[test]
271 fn encoded_data_roundtrips_buffer_sections() {
272 let mut encoder = EncodedData::default();
273 encoder.push_u8(7);
274 encoder.push_u32(99);
275
276 let bytes = encoder.into_bytes();
277 let mut data = DecodedData::from_bytes(&bytes).unwrap();
278 assert_eq!(data.take_u8().unwrap(), 7);
279 assert_eq!(data.take_u32().unwrap(), 99);
280 }
281
282 #[test]
283 fn flush_flag_is_consumed_once() {
284 let mut encoder = EncodedData::default();
285 encoder.mark_needs_flush();
286 assert!(encoder.take_needs_flush());
287 assert!(!encoder.take_needs_flush());
288 }
289}