1#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct BufferDecodeError {
53 pub context: &'static str,
56}
57
58impl std::fmt::Display for BufferDecodeError {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 write!(f, "malformed WeaveFFI value buffer: {}", self.context)
61 }
62}
63
64impl std::error::Error for BufferDecodeError {}
65
66#[derive(Debug, Default)]
74pub struct BufferWriter {
75 buf: Vec<u8>,
76}
77
78impl BufferWriter {
79 #[must_use]
81 pub fn new() -> Self {
82 Self::default()
83 }
84
85 #[must_use]
87 pub fn finish(self) -> Vec<u8> {
88 self.buf
89 }
90
91 pub fn write_bool(&mut self, v: bool) {
93 self.buf.push(u8::from(v));
94 }
95
96 pub fn write_i8(&mut self, v: i8) {
98 self.buf.extend_from_slice(&v.to_le_bytes());
99 }
100
101 pub fn write_u8(&mut self, v: u8) {
103 self.buf.push(v);
104 }
105
106 pub fn write_i16(&mut self, v: i16) {
108 self.buf.extend_from_slice(&v.to_le_bytes());
109 }
110
111 pub fn write_u16(&mut self, v: u16) {
113 self.buf.extend_from_slice(&v.to_le_bytes());
114 }
115
116 pub fn write_i32(&mut self, v: i32) {
119 self.buf.extend_from_slice(&v.to_le_bytes());
120 }
121
122 pub fn write_u32(&mut self, v: u32) {
124 self.buf.extend_from_slice(&v.to_le_bytes());
125 }
126
127 pub fn write_i64(&mut self, v: i64) {
129 self.buf.extend_from_slice(&v.to_le_bytes());
130 }
131
132 pub fn write_u64(&mut self, v: u64) {
134 self.buf.extend_from_slice(&v.to_le_bytes());
135 }
136
137 pub fn write_f32(&mut self, v: f32) {
139 self.buf.extend_from_slice(&v.to_le_bytes());
140 }
141
142 pub fn write_f64(&mut self, v: f64) {
144 self.buf.extend_from_slice(&v.to_le_bytes());
145 }
146
147 pub fn write_len(&mut self, len: usize) {
154 let len = u32::try_from(len).expect("WeaveFFI buffer length exceeds u32::MAX");
155 self.write_u32(len);
156 }
157
158 pub fn write_string(&mut self, v: &str) {
162 self.write_len(v.len());
163 self.buf.extend_from_slice(v.as_bytes());
164 }
165
166 pub fn write_bytes(&mut self, v: &[u8]) {
168 self.write_len(v.len());
169 self.buf.extend_from_slice(v);
170 }
171
172 pub fn write_option_flag(&mut self, present: bool) {
175 self.buf.push(u8::from(present));
176 }
177}
178
179#[derive(Debug)]
185pub struct BufferReader<'a> {
186 data: &'a [u8],
187 pos: usize,
188}
189
190impl<'a> BufferReader<'a> {
191 #[must_use]
193 pub fn new(data: &'a [u8]) -> Self {
194 Self { data, pos: 0 }
195 }
196
197 #[must_use]
199 pub fn remaining(&self) -> usize {
200 self.data.len() - self.pos
201 }
202
203 fn take(&mut self, n: usize, context: &'static str) -> Result<&'a [u8], BufferDecodeError> {
204 if self.remaining() < n {
205 return Err(BufferDecodeError { context });
206 }
207 let slice = &self.data[self.pos..self.pos + n];
208 self.pos += n;
209 Ok(slice)
210 }
211
212 pub fn read_bool(&mut self) -> Result<bool, BufferDecodeError> {
219 match self.take(1, "bool")?[0] {
220 0 => Ok(false),
221 1 => Ok(true),
222 _ => Err(BufferDecodeError {
223 context: "bool byte out of range",
224 }),
225 }
226 }
227
228 pub fn read_i8(&mut self) -> Result<i8, BufferDecodeError> {
234 Ok(i8::from_le_bytes([self.take(1, "i8")?[0]]))
235 }
236
237 pub fn read_u8(&mut self) -> Result<u8, BufferDecodeError> {
243 Ok(self.take(1, "u8")?[0])
244 }
245
246 pub fn read_i16(&mut self) -> Result<i16, BufferDecodeError> {
252 let b = self.take(2, "i16")?;
253 Ok(i16::from_le_bytes([b[0], b[1]]))
254 }
255
256 pub fn read_u16(&mut self) -> Result<u16, BufferDecodeError> {
262 let b = self.take(2, "u16")?;
263 Ok(u16::from_le_bytes([b[0], b[1]]))
264 }
265
266 pub fn read_i32(&mut self) -> Result<i32, BufferDecodeError> {
273 let b = self.take(4, "i32")?;
274 Ok(i32::from_le_bytes([b[0], b[1], b[2], b[3]]))
275 }
276
277 pub fn read_u32(&mut self) -> Result<u32, BufferDecodeError> {
283 let b = self.take(4, "u32")?;
284 Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
285 }
286
287 pub fn read_i64(&mut self) -> Result<i64, BufferDecodeError> {
293 let b = self.take(8, "i64")?;
294 Ok(i64::from_le_bytes([
295 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
296 ]))
297 }
298
299 pub fn read_u64(&mut self) -> Result<u64, BufferDecodeError> {
305 let b = self.take(8, "u64")?;
306 Ok(u64::from_le_bytes([
307 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
308 ]))
309 }
310
311 pub fn read_f32(&mut self) -> Result<f32, BufferDecodeError> {
317 let b = self.take(4, "f32")?;
318 Ok(f32::from_le_bytes([b[0], b[1], b[2], b[3]]))
319 }
320
321 pub fn read_f64(&mut self) -> Result<f64, BufferDecodeError> {
327 let b = self.take(8, "f64")?;
328 Ok(f64::from_le_bytes([
329 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
330 ]))
331 }
332
333 pub fn read_len(&mut self) -> Result<usize, BufferDecodeError> {
341 let len = self.read_u32()? as usize;
342 if len > self.remaining() {
345 return Err(BufferDecodeError {
346 context: "length prefix exceeds remaining buffer",
347 });
348 }
349 Ok(len)
350 }
351
352 pub fn read_string(&mut self) -> Result<String, BufferDecodeError> {
359 let len = self.read_len()?;
360 let bytes = self.take(len, "string bytes")?;
361 String::from_utf8(bytes.to_vec()).map_err(|_| BufferDecodeError {
362 context: "string is not valid UTF-8",
363 })
364 }
365
366 pub fn read_bytes(&mut self) -> Result<Vec<u8>, BufferDecodeError> {
372 let len = self.read_len()?;
373 Ok(self.take(len, "byte buffer")?.to_vec())
374 }
375
376 pub fn read_option_flag(&mut self) -> Result<bool, BufferDecodeError> {
383 match self.take(1, "option flag")?[0] {
384 0 => Ok(false),
385 1 => Ok(true),
386 _ => Err(BufferDecodeError {
387 context: "option flag byte out of range",
388 }),
389 }
390 }
391
392 pub fn expect_end(&self) -> Result<(), BufferDecodeError> {
399 if self.remaining() != 0 {
400 return Err(BufferDecodeError {
401 context: "trailing bytes after value",
402 });
403 }
404 Ok(())
405 }
406}
407
408pub trait BufferValue: Sized {
417 fn write_value(&self, w: &mut BufferWriter);
419
420 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError>;
427}
428
429macro_rules! scalar_buffer_value {
430 ($($t:ty => ($write:ident, $read:ident)),* $(,)?) => {
431 $(
432 impl BufferValue for $t {
433 fn write_value(&self, w: &mut BufferWriter) {
434 w.$write(*self);
435 }
436 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError> {
437 r.$read()
438 }
439 }
440 )*
441 };
442}
443
444scalar_buffer_value! {
445 bool => (write_bool, read_bool),
446 i8 => (write_i8, read_i8),
447 u8 => (write_u8, read_u8),
448 i16 => (write_i16, read_i16),
449 u16 => (write_u16, read_u16),
450 i32 => (write_i32, read_i32),
451 u32 => (write_u32, read_u32),
452 i64 => (write_i64, read_i64),
453 u64 => (write_u64, read_u64),
454 f32 => (write_f32, read_f32),
455 f64 => (write_f64, read_f64),
456}
457
458impl BufferValue for String {
459 fn write_value(&self, w: &mut BufferWriter) {
460 w.write_string(self);
461 }
462 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError> {
463 r.read_string()
464 }
465}
466
467impl<T: BufferValue> BufferValue for Option<T> {
468 fn write_value(&self, w: &mut BufferWriter) {
469 match self {
470 Some(v) => {
471 w.write_option_flag(true);
472 v.write_value(w);
473 }
474 None => w.write_option_flag(false),
475 }
476 }
477 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError> {
478 if r.read_option_flag()? {
479 Ok(Some(T::read_value(r)?))
480 } else {
481 Ok(None)
482 }
483 }
484}
485
486impl<T: BufferValue> BufferValue for Vec<T> {
487 fn write_value(&self, w: &mut BufferWriter) {
488 w.write_len(self.len());
489 for item in self {
490 item.write_value(w);
491 }
492 }
493 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError> {
494 let len = r.read_len()?;
495 let mut out = Vec::with_capacity(len.min(r.remaining()));
496 for _ in 0..len {
497 out.push(T::read_value(r)?);
498 }
499 Ok(out)
500 }
501}
502
503impl<K: BufferValue + Ord, V: BufferValue> BufferValue for std::collections::BTreeMap<K, V> {
504 fn write_value(&self, w: &mut BufferWriter) {
505 w.write_len(self.len());
506 for (k, v) in self {
507 k.write_value(w);
508 v.write_value(w);
509 }
510 }
511 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError> {
512 let len = r.read_len()?;
513 let mut out = Self::new();
514 for _ in 0..len {
515 let k = K::read_value(r)?;
516 let v = V::read_value(r)?;
517 out.insert(k, v);
518 }
519 Ok(out)
520 }
521}
522
523impl<K: BufferValue + std::hash::Hash + Eq, V: BufferValue> BufferValue
524 for std::collections::HashMap<K, V>
525{
526 fn write_value(&self, w: &mut BufferWriter) {
527 w.write_len(self.len());
528 for (k, v) in self {
529 k.write_value(w);
530 v.write_value(w);
531 }
532 }
533 fn read_value(r: &mut BufferReader<'_>) -> Result<Self, BufferDecodeError> {
534 let len = r.read_len()?;
535 let mut out = Self::with_capacity(len.min(r.remaining()));
536 for _ in 0..len {
537 let k = K::read_value(r)?;
538 let v = V::read_value(r)?;
539 out.insert(k, v);
540 }
541 Ok(out)
542 }
543}
544
545#[must_use]
547pub fn encode_value<T: BufferValue>(value: &T) -> Vec<u8> {
548 let mut w = BufferWriter::new();
549 value.write_value(&mut w);
550 w.finish()
551}
552
553pub fn decode_value<T: BufferValue>(data: &[u8]) -> Result<T, BufferDecodeError> {
561 let mut r = BufferReader::new(data);
562 let value = T::read_value(&mut r)?;
563 r.expect_end()?;
564 Ok(value)
565}
566
567#[cfg(test)]
568mod tests {
569 use super::*;
570 use std::collections::BTreeMap;
571
572 fn roundtrip<T: BufferValue + PartialEq + std::fmt::Debug>(value: T) {
573 let bytes = encode_value(&value);
574 let back: T = decode_value(&bytes).unwrap();
575 assert_eq!(back, value);
576 }
577
578 #[test]
579 fn scalars_roundtrip() {
580 roundtrip(true);
581 roundtrip(false);
582 roundtrip(-5i8);
583 roundtrip(200u8);
584 roundtrip(-1234i16);
585 roundtrip(54321u16);
586 roundtrip(-7i32);
587 roundtrip(4_000_000_000u32);
588 roundtrip(i64::MIN);
589 roundtrip(u64::MAX);
590 roundtrip(1.5f32);
591 roundtrip(-2.25f64);
592 }
593
594 #[test]
595 fn strings_roundtrip_including_interior_nul() {
596 roundtrip(String::new());
597 roundtrip("hello".to_string());
598 roundtrip("emoji \u{1F980} and\0nul".to_string());
599 }
600
601 #[test]
602 fn options_roundtrip() {
603 roundtrip::<Option<i32>>(None);
604 roundtrip(Some(42i32));
605 roundtrip(Some("text".to_string()));
606 roundtrip::<Option<Option<i64>>>(Some(None));
607 roundtrip::<Option<Option<i64>>>(Some(Some(9)));
608 }
609
610 #[test]
611 fn collections_roundtrip() {
612 roundtrip(vec![1u8, 2, 3]);
613 roundtrip(vec!["a".to_string(), String::new(), "ccc".to_string()]);
614 roundtrip(vec![vec![1i32, 2], vec![], vec![3]]);
615 roundtrip(vec![Some(1i32), None, Some(3)]);
616 let mut m = BTreeMap::new();
617 m.insert("a".to_string(), vec![1i64, 2]);
618 m.insert("b".to_string(), vec![]);
619 roundtrip(m);
620 }
621
622 #[test]
623 fn known_byte_layout() {
624 let bytes = encode_value(&vec!["a".to_string(), String::new()]);
626 assert_eq!(bytes, [2, 0, 0, 0, 1, 0, 0, 0, b'a', 0, 0, 0, 0].as_slice());
627 }
628
629 #[test]
630 fn truncated_buffer_is_rejected() {
631 let bytes = encode_value(&"hello".to_string());
632 let err = decode_value::<String>(&bytes[..bytes.len() - 1]).unwrap_err();
633 assert!(err.to_string().contains("malformed"));
634 }
635
636 #[test]
637 fn trailing_bytes_are_rejected() {
638 let mut bytes = encode_value(&7i32);
639 bytes.push(0);
640 assert!(decode_value::<i32>(&bytes).is_err());
641 }
642
643 #[test]
644 fn hostile_length_prefix_is_rejected() {
645 let bytes = [0xFF, 0xFF, 0xFF, 0xFF];
648 assert!(decode_value::<Vec<u8>>(&bytes).is_err());
649 }
650
651 #[test]
652 fn invalid_bool_and_flag_bytes_are_rejected() {
653 assert!(decode_value::<bool>(&[2]).is_err());
654 assert!(decode_value::<Option<i32>>(&[9]).is_err());
655 }
656
657 #[test]
658 fn invalid_utf8_is_rejected() {
659 let bytes = [2, 0, 0, 0, 0xFF, 0xFE];
660 assert!(decode_value::<String>(&bytes).is_err());
661 }
662}