1use alloc::string::{String, ToString};
11use alloc::vec::Vec;
12use base64::Engine;
13use core::fmt;
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum DecodeError {
18 MessageTooShort { expected: usize, actual: usize },
20 U8BufferEmpty,
22 U16BufferEmpty,
24 U32BufferEmpty,
26 StringBufferTooShort { expected: usize, actual: usize },
28 InvalidUtf8 { position: usize },
30 InvalidMessageType { value: u8 },
32 InvalidHeaderOffsets {
34 u16_offset: u32,
35 u8_offset: u32,
36 str_offset: u32,
37 total_len: usize,
38 },
39 Custom(String),
41}
42
43impl fmt::Display for DecodeError {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 DecodeError::MessageTooShort { expected, actual } => {
47 write!(
48 f,
49 "message too short: expected at least {expected} bytes, got {actual}"
50 )
51 }
52 DecodeError::U8BufferEmpty => write!(f, "u8 buffer empty when trying to read"),
53 DecodeError::U16BufferEmpty => write!(f, "u16 buffer empty when trying to read"),
54 DecodeError::U32BufferEmpty => write!(f, "u32 buffer empty when trying to read"),
55 DecodeError::StringBufferTooShort { expected, actual } => {
56 write!(
57 f,
58 "string buffer too short: expected {expected} bytes, got {actual}"
59 )
60 }
61 DecodeError::InvalidUtf8 { position } => {
62 write!(f, "invalid UTF-8 at position {position}")
63 }
64 DecodeError::InvalidMessageType { value } => {
65 write!(f, "invalid message type: {value}")
66 }
67 DecodeError::InvalidHeaderOffsets {
68 u16_offset,
69 u8_offset,
70 str_offset,
71 total_len,
72 } => {
73 write!(
74 f,
75 "invalid header offsets: u16={u16_offset}, u8={u8_offset}, str={str_offset}, total_len={total_len}"
76 )
77 }
78 DecodeError::Custom(msg) => write!(f, "{msg}"),
79 }
80 }
81}
82
83impl core::error::Error for DecodeError {}
84
85impl From<DecodeError> for String {
86 fn from(err: DecodeError) -> String {
87 err.to_string()
88 }
89}
90
91#[repr(u8)]
93#[derive(Debug, Clone, Copy, PartialEq, Eq)]
94pub(crate) enum MessageType {
95 Evaluate = 0,
97 Respond = 1,
99}
100
101#[derive(Debug, Clone)]
118pub(crate) struct IPCMessage {
119 data: Vec<u8>,
120}
121
122impl IPCMessage {
123 pub fn new(data: Vec<u8>) -> Self {
125 Self { data }
126 }
127
128 pub fn new_respond(push_data: impl FnOnce(&mut EncodedData)) -> Self {
130 let mut encoder = EncodedData::new();
131 encoder.push_u8(MessageType::Respond as u8);
132
133 push_data(&mut encoder);
134
135 IPCMessage::new(encoder.to_bytes())
136 }
137
138 pub fn ty(&self) -> Result<MessageType, DecodeError> {
140 let mut decoded = DecodedData::from_bytes(&self.data)?;
141 let message_type = decoded.take_u8()?;
142 match message_type {
143 0 => Ok(MessageType::Evaluate),
144 1 => Ok(MessageType::Respond),
145 v => Err(DecodeError::InvalidMessageType { value: v }),
146 }
147 }
148
149 pub fn decoded(&self) -> Result<DecodedVariant<'_>, DecodeError> {
151 let mut decoded = DecodedData::from_bytes(&self.data)?;
152 let message_type = decoded.take_u8()?;
153 let message_type = match message_type {
154 0 => DecodedVariant::Evaluate { data: decoded },
155 1 => DecodedVariant::Respond { data: decoded },
156 v => return Err(DecodeError::InvalidMessageType { value: v }),
157 };
158 Ok(message_type)
159 }
160
161 pub fn data(&self) -> &[u8] {
163 &self.data
164 }
165
166 pub fn into_data(self) -> Vec<u8> {
168 self.data
169 }
170}
171
172#[derive(Debug)]
174pub(crate) enum DecodedVariant<'a> {
175 Respond { data: DecodedData<'a> },
177 Evaluate { data: DecodedData<'a> },
179}
180
181#[derive(Debug)]
183pub struct DecodedData<'a> {
184 u8_buf: &'a [u8],
185 u16_buf: &'a [u16],
186 u32_buf: &'a [u32],
187 str_buf: &'a [u8],
188}
189
190impl<'a> DecodedData<'a> {
191 pub(crate) fn from_bytes(bytes: &'a [u8]) -> Result<Self, DecodeError> {
193 if bytes.len() < 12 {
194 return Err(DecodeError::MessageTooShort {
195 expected: 12,
196 actual: bytes.len(),
197 });
198 }
199
200 let header: [u32; 3] = bytemuck::cast_slice(&bytes[0..12])
201 .try_into()
202 .map_err(|_| DecodeError::Custom("failed to parse header".to_string()))?;
203 let [u16_offset, u8_offset, str_offset] = header;
204
205 let total_len = bytes.len();
207 if u16_offset as usize > total_len
208 || u8_offset as usize > total_len
209 || str_offset as usize > total_len
210 || u16_offset < 12
211 || u8_offset < u16_offset
212 || str_offset < u8_offset
213 {
214 return Err(DecodeError::InvalidHeaderOffsets {
215 u16_offset,
216 u8_offset,
217 str_offset,
218 total_len,
219 });
220 }
221
222 let u32_buf = bytemuck::cast_slice(&bytes[12..u16_offset as usize]);
223 let u16_buf = bytemuck::cast_slice(&bytes[u16_offset as usize..u8_offset as usize]);
224 let u8_buf = &bytes[u8_offset as usize..str_offset as usize];
225 let str_buf = &bytes[str_offset as usize..];
226
227 Ok(Self {
228 u8_buf,
229 u16_buf,
230 u32_buf,
231 str_buf,
232 })
233 }
234
235 pub(crate) fn take_u8(&mut self) -> Result<u8, DecodeError> {
237 let [first, rest @ ..] = &self.u8_buf else {
238 return Err(DecodeError::U8BufferEmpty);
239 };
240 self.u8_buf = rest;
241 Ok(*first)
242 }
243
244 pub(crate) fn take_u16(&mut self) -> Result<u16, DecodeError> {
246 let [first, rest @ ..] = &self.u16_buf else {
247 return Err(DecodeError::U16BufferEmpty);
248 };
249 self.u16_buf = rest;
250 Ok(*first)
251 }
252
253 pub(crate) fn take_u32(&mut self) -> Result<u32, DecodeError> {
255 let [first, rest @ ..] = &self.u32_buf else {
256 return Err(DecodeError::U32BufferEmpty);
257 };
258 self.u32_buf = rest;
259 Ok(*first)
260 }
261
262 pub(crate) fn take_u64(&mut self) -> Result<u64, DecodeError> {
264 let low = self.take_u32()? as u64;
265 let high = self.take_u32()? as u64;
266 Ok((high << 32) | low)
267 }
268
269 pub(crate) fn take_u128(&mut self) -> Result<u128, DecodeError> {
271 let low = self.take_u64()? as u128;
272 let high = self.take_u64()? as u128;
273 Ok((high << 64) | low)
274 }
275
276 pub(crate) fn take_str(&mut self) -> Result<&'a str, DecodeError> {
278 let len = self.take_u32()? as usize;
279 let actual_len = self.str_buf.len();
280 let Some((buf, rem)) = self.str_buf.split_at_checked(len) else {
281 return Err(DecodeError::StringBufferTooShort {
282 expected: len,
283 actual: actual_len,
284 });
285 };
286 let s = core::str::from_utf8(buf).map_err(|e| DecodeError::InvalidUtf8 {
287 position: e.valid_up_to(),
288 })?;
289 self.str_buf = rem;
290 Ok(s)
291 }
292
293 pub(crate) fn is_empty(&self) -> bool {
295 self.u8_buf.is_empty()
296 && self.u16_buf.is_empty()
297 && self.u32_buf.is_empty()
298 && self.str_buf.is_empty()
299 }
300}
301
302#[derive(Debug, Default)]
304pub struct EncodedData {
305 pub(crate) u8_buf: Vec<u8>,
306 pub(crate) u16_buf: Vec<u16>,
307 pub(crate) u32_buf: Vec<u32>,
308 pub(crate) str_buf: Vec<u8>,
309 pub(crate) needs_flush: bool,
312}
313
314impl EncodedData {
315 pub fn new() -> Self {
317 Self {
318 u8_buf: Vec::new(),
319 u16_buf: Vec::new(),
320 u32_buf: Vec::new(),
321 str_buf: Vec::new(),
322 needs_flush: false,
323 }
324 }
325
326 pub fn mark_needs_flush(&mut self) {
329 self.needs_flush = true;
330 }
331
332 pub(crate) fn byte_len(&self) -> usize {
334 12 + self.u32_buf.len() * 4
335 + self.u16_buf.len() * 2
336 + self.u8_buf.len()
337 + self.str_buf.len()
338 }
339
340 pub(crate) fn push_u8(&mut self, value: u8) {
342 self.u8_buf.push(value);
343 }
344
345 pub(crate) fn push_u16(&mut self, value: u16) {
347 self.u16_buf.push(value);
348 }
349
350 pub(crate) fn push_u32(&mut self, value: u32) {
352 self.u32_buf.push(value);
353 }
354
355 pub fn prepend_u32(&mut self, value: u32) {
358 self.u32_buf.insert(0, value);
359 }
360
361 pub(crate) fn push_u64(&mut self, value: u64) {
363 self.push_u32((value & 0xFFFFFFFF) as u32);
364 self.push_u32((value >> 32) as u32);
365 }
366
367 pub(crate) fn push_u128(&mut self, value: u128) {
369 self.push_u64((value & 0xFFFFFFFFFFFFFFFF) as u64);
370 self.push_u64((value >> 64) as u64);
371 }
372
373 pub(crate) fn push_str(&mut self, value: &str) {
375 self.push_u32(value.len() as u32);
376 self.str_buf.extend_from_slice(value.as_bytes());
377 }
378
379 pub(crate) fn to_bytes(&self) -> Vec<u8> {
381 let u16_offset = 12 + self.u32_buf.len() * 4;
382 let u8_offset = u16_offset + self.u16_buf.len() * 2;
383 let str_offset = u8_offset + self.u8_buf.len();
384
385 let total_len = str_offset + self.str_buf.len();
386 let mut bytes = Vec::with_capacity(total_len);
387
388 bytes.extend_from_slice(&(u16_offset as u32).to_le_bytes());
390 bytes.extend_from_slice(&(u8_offset as u32).to_le_bytes());
391 bytes.extend_from_slice(&(str_offset as u32).to_le_bytes());
392
393 for &u in &self.u32_buf {
395 bytes.extend_from_slice(&u.to_le_bytes());
396 }
397
398 for &u in &self.u16_buf {
400 bytes.extend_from_slice(&u.to_le_bytes());
401 }
402
403 bytes.extend_from_slice(&self.u8_buf);
405
406 bytes.extend_from_slice(&self.str_buf);
408
409 bytes
410 }
411
412 pub(crate) fn extend(&mut self, other: &EncodedData) {
414 self.u8_buf.extend_from_slice(&other.u8_buf);
415 self.u16_buf.extend_from_slice(&other.u16_buf);
416 self.u32_buf.extend_from_slice(&other.u32_buf);
417 self.str_buf.extend_from_slice(&other.str_buf);
418 }
419}
420
421pub(crate) fn decode_data(bytes: &[u8]) -> Option<IPCMessage> {
423 let engine = base64::engine::general_purpose::STANDARD;
424 let data = engine.decode(bytes).ok()?;
425 Some(IPCMessage { data })
426}