1#![cfg_attr(not(feature = "std"), no_std)]
26
27extern crate alloc;
28
29mod hash;
30mod parse;
31mod value;
32
33pub use hash::{
34 hash_function,
35 hash_interface,
36 hash_list,
38 hash_option,
39 hash_record,
40 hash_result,
41 hash_tuple,
42 hash_variant,
43 Binding,
44 TypeHash,
45 TypeHasher,
46 HASH_BOOL,
48 HASH_CHAR,
49 HASH_F32,
50 HASH_F64,
51 HASH_FLAGS,
52 HASH_S16,
53 HASH_S32,
54 HASH_S64,
55 HASH_S8,
56 HASH_SELF_REF,
57 HASH_STRING,
58 HASH_U16,
59 HASH_U32,
60 HASH_U64,
61 HASH_U8,
62};
63pub use parse::{parse_value, ParseError};
64pub use value::{FromValue, KnownValueType, Value, ValueType};
65
66#[cfg(feature = "derive")]
68pub use packr_derive::GraphValue;
69
70use alloc::boxed::Box;
75
76#[derive(Debug, Clone)]
78pub enum ConversionError {
79 TypeMismatch { expected: String, got: String },
81 MissingField(String),
83 MissingIndex(usize),
85 WrongFieldCount { expected: usize, got: usize },
87 ExpectedRecord(String),
89 ExpectedTuple(String),
91 ExpectedVariant(String),
93 ExpectedList(String),
95 ExpectedOption(String),
97 UnknownTag { tag: usize, max: usize },
99 MissingPayload,
101 UnexpectedPayload,
103 FieldError(String, Box<ConversionError>),
105 IndexError(usize, Box<ConversionError>),
107 PayloadError(Box<ConversionError>),
109}
110
111impl core::fmt::Display for ConversionError {
112 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
113 match self {
114 Self::TypeMismatch { expected, got } => {
115 write!(f, "type mismatch: expected {}, got {}", expected, got)
116 }
117 Self::MissingField(name) => write!(f, "missing field: {}", name),
118 Self::MissingIndex(idx) => write!(f, "missing index: {}", idx),
119 Self::WrongFieldCount { expected, got } => {
120 write!(f, "wrong field count: expected {}, got {}", expected, got)
121 }
122 Self::ExpectedRecord(got) => write!(f, "expected record, got {}", got),
123 Self::ExpectedTuple(got) => write!(f, "expected tuple, got {}", got),
124 Self::ExpectedVariant(got) => write!(f, "expected variant, got {}", got),
125 Self::ExpectedList(got) => write!(f, "expected list, got {}", got),
126 Self::ExpectedOption(got) => write!(f, "expected option, got {}", got),
127 Self::UnknownTag { tag, max } => {
128 write!(f, "unknown variant tag {} (max {})", tag, max)
129 }
130 Self::MissingPayload => write!(f, "missing payload for variant"),
131 Self::UnexpectedPayload => write!(f, "unexpected payload for unit variant"),
132 Self::FieldError(name, e) => write!(f, "field '{}': {}", name, e),
133 Self::IndexError(idx, e) => write!(f, "index {}: {}", idx, e),
134 Self::PayloadError(e) => write!(f, "payload: {}", e),
135 }
136 }
137}
138
139#[doc(hidden)]
145pub mod __private {
146 pub use alloc::boxed::Box;
147 pub use alloc::format;
148 pub use alloc::string::String;
149 pub use alloc::vec;
150 pub use alloc::vec::Vec;
151 pub use core::convert::From;
152 pub use core::convert::TryFrom;
153 pub use core::option::Option::{self, None, Some};
154 pub use core::result::Result;
155 pub use core::result::Result::{Err, Ok};
156}
157
158use alloc::format;
159use alloc::string::String;
160use alloc::vec;
161use alloc::vec::Vec;
162use hashbrown::{HashMap, HashSet};
163
164#[derive(Debug, Clone)]
165pub enum AbiError {
166 TypeMismatch { expected: String, got: String },
167 InvalidEncoding(String),
168 BufferTooSmall { need: usize, have: usize },
169 InvalidTag(u8),
170}
171
172const MAGIC: u32 = u32::from_le_bytes(*b"CGRF");
173const VERSION: u16 = 2;
174
175#[derive(Debug, Clone, Copy)]
176pub struct Limits {
177 pub max_buffer_size: usize,
178 pub max_node_count: usize,
179 pub max_payload_size: usize,
180 pub max_sequence_len: usize,
181}
182
183impl Default for Limits {
184 fn default() -> Self {
185 Self {
186 max_buffer_size: 16 * 1024 * 1024,
187 max_node_count: 1_000_000,
188 max_payload_size: 8 * 1024 * 1024,
189 max_sequence_len: 1_000_000,
190 }
191 }
192}
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq)]
195pub enum NodeKind {
196 Bool = 0x01,
197 S32 = 0x02,
198 S64 = 0x03,
199 F32 = 0x04,
200 F64 = 0x05,
201 String = 0x06,
202 List = 0x07,
203 Variant = 0x08,
204 Record = 0x09,
205 Option = 0x0A,
206 Tuple = 0x0B,
207 U8 = 0x0C,
208 U16 = 0x0D,
209 U32 = 0x0E,
210 U64 = 0x0F,
211 S8 = 0x10,
212 S16 = 0x11,
213 Char = 0x12,
214 Flags = 0x13,
215 Result = 0x14,
216 Array = 0x15,
217}
218
219#[derive(Debug, Clone)]
220pub struct Node {
221 pub kind: NodeKind,
222 pub payload: Vec<u8>,
223}
224
225#[derive(Debug, Clone)]
226pub struct GraphBuffer {
227 pub nodes: Vec<Node>,
228 pub root: u32,
229}
230
231pub struct Encoder {
232 nodes: Vec<Node>,
233}
234
235impl Encoder {
236 pub fn new() -> Self {
237 Self { nodes: Vec::new() }
238 }
239
240 pub fn push_node(&mut self, node: Node) -> u32 {
241 let index = self.nodes.len() as u32;
242 self.nodes.push(node);
243 index
244 }
245
246 pub fn finish(self, root: u32) -> GraphBuffer {
247 GraphBuffer {
248 nodes: self.nodes,
249 root,
250 }
251 }
252}
253
254impl Default for Encoder {
255 fn default() -> Self {
256 Self::new()
257 }
258}
259
260pub struct Decoder<'a> {
261 pub buffer: &'a GraphBuffer,
262}
263
264impl<'a> Decoder<'a> {
265 pub fn new(buffer: &'a GraphBuffer) -> Self {
266 Self { buffer }
267 }
268
269 pub fn node(&self, index: u32) -> Option<&'a Node> {
270 self.buffer.nodes.get(index as usize)
271 }
272}
273
274pub trait GraphCodec {
275 fn encode_graph(&self, encoder: &mut Encoder) -> Result<u32, AbiError>;
276 fn decode_graph(decoder: &Decoder<'_>, root: u32) -> Result<Self, AbiError>
277 where
278 Self: Sized;
279}
280
281pub fn encode(value: &Value) -> Result<Vec<u8>, AbiError> {
283 let mut encoder = Encoder::new();
284 let root = value.encode_graph(&mut encoder)?;
285 let buffer = encoder.finish(root);
286 Ok(buffer.to_bytes())
287}
288
289pub fn decode(bytes: &[u8]) -> Result<Value, AbiError> {
291 let limits = Limits::default();
292 decode_with_limits(bytes, &limits)
293}
294
295pub fn decode_with_limits(bytes: &[u8], limits: &Limits) -> Result<Value, AbiError> {
297 let buffer = GraphBuffer::from_bytes_with_limits(bytes, limits)?;
298 buffer.validate_basic_with_limits(limits)?;
299 let decoder = Decoder::new(&buffer);
300 Value::decode_graph(&decoder, buffer.root)
301}
302
303impl GraphBuffer {
304 pub fn to_bytes(&self) -> Vec<u8> {
305 let mut out = Vec::new();
306 out.extend_from_slice(&MAGIC.to_le_bytes());
307 out.extend_from_slice(&VERSION.to_le_bytes());
308 out.extend_from_slice(&0u16.to_le_bytes());
309 out.extend_from_slice(&(self.nodes.len() as u32).to_le_bytes());
310 out.extend_from_slice(&self.root.to_le_bytes());
311
312 for node in &self.nodes {
313 let kind = node.kind as u8;
314 out.push(kind);
315 out.push(0u8);
316 out.extend_from_slice(&0u16.to_le_bytes());
317 out.extend_from_slice(&(node.payload.len() as u32).to_le_bytes());
318 out.extend_from_slice(&node.payload);
319 }
320
321 out
322 }
323
324 pub fn from_bytes(bytes: &[u8]) -> Result<Self, AbiError> {
325 let limits = Limits::default();
326 Self::from_bytes_with_limits(bytes, &limits)
327 }
328
329 pub fn from_bytes_with_limits(bytes: &[u8], limits: &Limits) -> Result<Self, AbiError> {
330 if bytes.len() > limits.max_buffer_size {
331 return Err(AbiError::InvalidEncoding(String::from("Buffer too large")));
332 }
333
334 let mut cursor = Cursor::new(bytes);
335 let magic = cursor.read_u32()?;
336 if magic != MAGIC {
337 return Err(AbiError::InvalidEncoding(String::from("Invalid magic")));
338 }
339
340 let version = cursor.read_u16()?;
341 if version != VERSION {
342 return Err(AbiError::InvalidEncoding(String::from(
343 "Unsupported version",
344 )));
345 }
346
347 let _flags = cursor.read_u16()?;
348 let node_count = cursor.read_u32()? as usize;
349 if node_count > limits.max_node_count {
350 return Err(AbiError::InvalidEncoding(String::from(
351 "Node count exceeds limit",
352 )));
353 }
354 let root = cursor.read_u32()?;
355
356 let mut nodes = Vec::with_capacity(node_count);
357 for _ in 0..node_count {
358 let kind = node_kind_from_u8(cursor.read_u8()?)?;
359 let _node_flags = cursor.read_u8()?;
360 let _reserved = cursor.read_u16()?;
361 let payload_len = cursor.read_u32()? as usize;
362 if payload_len > limits.max_payload_size {
363 return Err(AbiError::InvalidEncoding(String::from("Payload too large")));
364 }
365 let payload = cursor.read_bytes(payload_len)?.to_vec();
366 nodes.push(Node { kind, payload });
367 }
368
369 if (root as usize) >= nodes.len() {
370 return Err(AbiError::InvalidEncoding(String::from(
371 "Root index out of range",
372 )));
373 }
374
375 if !cursor.is_eof() {
376 return Err(AbiError::InvalidEncoding(String::from("Trailing bytes")));
377 }
378
379 Ok(Self { nodes, root })
380 }
381
382 pub fn validate_basic(&self) -> Result<(), AbiError> {
383 let limits = Limits::default();
384 self.validate_basic_with_limits(&limits)
385 }
386
387 pub fn validate_basic_with_limits(&self, limits: &Limits) -> Result<(), AbiError> {
388 let node_count = self.nodes.len();
389 if (self.root as usize) >= node_count {
390 return Err(AbiError::InvalidEncoding(String::from(
391 "Root index out of range",
392 )));
393 }
394 if node_count > limits.max_node_count {
395 return Err(AbiError::InvalidEncoding(String::from(
396 "Node count exceeds limit",
397 )));
398 }
399
400 for (index, node) in self.nodes.iter().enumerate() {
401 if node.payload.len() > limits.max_payload_size {
402 return Err(AbiError::InvalidEncoding(format!(
403 "Payload too large at node {index}"
404 )));
405 }
406 let mut cursor = Cursor::new(&node.payload);
407 match node.kind {
408 NodeKind::Bool => {
409 let value = cursor.read_u8()?;
410 if value > 1 {
411 return Err(AbiError::InvalidEncoding(format!(
412 "Invalid bool payload at node {index}"
413 )));
414 }
415 }
416 NodeKind::S32 | NodeKind::F32 | NodeKind::U32 => {
417 cursor.read_bytes(4)?;
418 }
419 NodeKind::S64 | NodeKind::F64 | NodeKind::U64 => {
420 cursor.read_bytes(8)?;
421 }
422 NodeKind::U8 | NodeKind::S8 => {
423 cursor.read_bytes(1)?;
424 }
425 NodeKind::U16 | NodeKind::S16 => {
426 cursor.read_bytes(2)?;
427 }
428 NodeKind::Char => {
429 let value = cursor.read_u32()?;
430 if char::from_u32(value).is_none() {
431 return Err(AbiError::InvalidEncoding(format!(
432 "Invalid char scalar at node {index}"
433 )));
434 }
435 }
436 NodeKind::Flags => {
437 cursor.read_bytes(8)?;
438 }
439 NodeKind::String => {
440 let len = cursor.read_u32()? as usize;
441 let bytes = cursor.read_bytes(len)?;
442 if core::str::from_utf8(bytes).is_err() {
443 return Err(AbiError::InvalidEncoding(format!(
444 "Invalid UTF-8 string at node {index}"
445 )));
446 }
447 }
448 NodeKind::Tuple => {
449 let count = cursor.read_u32()? as usize;
451 if count > limits.max_sequence_len {
452 return Err(AbiError::InvalidEncoding(format!(
453 "Sequence too large at node {index}"
454 )));
455 }
456 for _ in 0..count {
457 let child = cursor.read_u32()? as usize;
458 if child >= node_count {
459 return Err(AbiError::InvalidEncoding(format!(
460 "Child index out of range at node {index}"
461 )));
462 }
463 }
464 }
465 NodeKind::Array => {
468 let elem_type = decode_value_type(&mut cursor)?;
470 let width = fixed_width(&elem_type).ok_or_else(|| {
471 AbiError::InvalidEncoding(format!(
472 "Non-primitive element type in Array at node {index}"
473 ))
474 })?;
475 let count = cursor.read_u32()? as usize;
476 if count > limits.max_sequence_len {
477 return Err(AbiError::InvalidEncoding(format!(
478 "Sequence too large at node {index}"
479 )));
480 }
481 cursor.read_bytes(count * width)?;
482 }
483 NodeKind::List
484 | NodeKind::Option
485 | NodeKind::Record
486 | NodeKind::Variant
487 | NodeKind::Result => {
488 }
491 }
492
493 if !matches!(
495 node.kind,
496 NodeKind::List
497 | NodeKind::Option
498 | NodeKind::Record
499 | NodeKind::Variant
500 | NodeKind::Result
501 ) && !cursor.is_eof()
502 {
503 return Err(AbiError::InvalidEncoding(format!(
504 "Trailing payload bytes at node {index}"
505 )));
506 }
507 }
508
509 Ok(())
510 }
511}
512
513struct Cursor<'a> {
514 bytes: &'a [u8],
515 pos: usize,
516}
517
518impl<'a> Cursor<'a> {
519 fn new(bytes: &'a [u8]) -> Self {
520 Self { bytes, pos: 0 }
521 }
522
523 fn is_eof(&self) -> bool {
524 self.pos >= self.bytes.len()
525 }
526
527 fn read_bytes(&mut self, len: usize) -> Result<&'a [u8], AbiError> {
528 if self.pos + len > self.bytes.len() {
529 return Err(AbiError::BufferTooSmall {
530 need: self.pos + len,
531 have: self.bytes.len(),
532 });
533 }
534 let start = self.pos;
535 self.pos += len;
536 Ok(&self.bytes[start..self.pos])
537 }
538
539 fn read_u8(&mut self) -> Result<u8, AbiError> {
540 let bytes = self.read_bytes(1)?;
541 Ok(bytes[0])
542 }
543
544 fn read_u16(&mut self) -> Result<u16, AbiError> {
545 let bytes = self.read_bytes(2)?;
546 Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
547 }
548
549 fn read_u32(&mut self) -> Result<u32, AbiError> {
550 let bytes = self.read_bytes(4)?;
551 Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
552 }
553
554 fn read_u64(&mut self) -> Result<u64, AbiError> {
555 let bytes = self.read_bytes(8)?;
556 Ok(u64::from_le_bytes([
557 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
558 ]))
559 }
560}
561
562fn node_kind_from_u8(value: u8) -> Result<NodeKind, AbiError> {
563 match value {
564 0x01 => Ok(NodeKind::Bool),
565 0x02 => Ok(NodeKind::S32),
566 0x03 => Ok(NodeKind::S64),
567 0x04 => Ok(NodeKind::F32),
568 0x05 => Ok(NodeKind::F64),
569 0x06 => Ok(NodeKind::String),
570 0x07 => Ok(NodeKind::List),
571 0x08 => Ok(NodeKind::Variant),
572 0x09 => Ok(NodeKind::Record),
573 0x0A => Ok(NodeKind::Option),
574 0x0B => Ok(NodeKind::Tuple),
575 0x0C => Ok(NodeKind::U8),
576 0x0D => Ok(NodeKind::U16),
577 0x0E => Ok(NodeKind::U32),
578 0x0F => Ok(NodeKind::U64),
579 0x10 => Ok(NodeKind::S8),
580 0x11 => Ok(NodeKind::S16),
581 0x12 => Ok(NodeKind::Char),
582 0x13 => Ok(NodeKind::Flags),
583 0x14 => Ok(NodeKind::Result),
584 0x15 => Ok(NodeKind::Array),
585 _ => Err(AbiError::InvalidTag(value)),
586 }
587}
588
589const TYPE_BOOL: u8 = 0x01;
591const TYPE_S32: u8 = 0x02;
592const TYPE_S64: u8 = 0x03;
593const TYPE_F32: u8 = 0x04;
594const TYPE_F64: u8 = 0x05;
595const TYPE_STRING: u8 = 0x06;
596const TYPE_LIST: u8 = 0x07;
597const TYPE_VARIANT: u8 = 0x08;
598const TYPE_RECORD: u8 = 0x09;
599const TYPE_OPTION: u8 = 0x0A;
600const TYPE_TUPLE: u8 = 0x0B;
601const TYPE_U8: u8 = 0x0C;
602const TYPE_U16: u8 = 0x0D;
603const TYPE_U32: u8 = 0x0E;
604const TYPE_U64: u8 = 0x0F;
605const TYPE_S8: u8 = 0x10;
606const TYPE_S16: u8 = 0x11;
607const TYPE_CHAR: u8 = 0x12;
608const TYPE_FLAGS: u8 = 0x13;
609const TYPE_RESULT: u8 = 0x14;
610
611fn fixed_width(ty: &ValueType) -> Option<usize> {
613 match ty {
614 ValueType::Bool | ValueType::U8 | ValueType::S8 => Some(1),
615 ValueType::U16 | ValueType::S16 => Some(2),
616 ValueType::U32 | ValueType::S32 | ValueType::F32 | ValueType::Char => Some(4),
617 ValueType::U64 | ValueType::S64 | ValueType::F64 | ValueType::Flags => Some(8),
618 _ => None,
619 }
620}
621
622fn encode_array_element(
624 value: &Value,
625 expected: &ValueType,
626 out: &mut Vec<u8>,
627) -> Result<(), AbiError> {
628 match (value, expected) {
629 (Value::Bool(v), ValueType::Bool) => out.push(if *v { 1 } else { 0 }),
630 (Value::U8(v), ValueType::U8) => out.push(*v),
631 (Value::S8(v), ValueType::S8) => out.push(*v as u8),
632 (Value::U16(v), ValueType::U16) => out.extend_from_slice(&v.to_le_bytes()),
633 (Value::S16(v), ValueType::S16) => out.extend_from_slice(&v.to_le_bytes()),
634 (Value::U32(v), ValueType::U32) => out.extend_from_slice(&v.to_le_bytes()),
635 (Value::S32(v), ValueType::S32) => out.extend_from_slice(&v.to_le_bytes()),
636 (Value::U64(v), ValueType::U64) => out.extend_from_slice(&v.to_le_bytes()),
637 (Value::S64(v), ValueType::S64) => out.extend_from_slice(&v.to_le_bytes()),
638 (Value::F32(v), ValueType::F32) => out.extend_from_slice(&v.to_le_bytes()),
639 (Value::F64(v), ValueType::F64) => out.extend_from_slice(&v.to_le_bytes()),
640 (Value::Char(v), ValueType::Char) => out.extend_from_slice(&(*v as u32).to_le_bytes()),
641 (Value::Flags(v), ValueType::Flags) => out.extend_from_slice(&v.to_le_bytes()),
642 _ => {
643 return Err(AbiError::InvalidEncoding(String::from(
644 "Array element type mismatch",
645 )))
646 }
647 }
648 Ok(())
649}
650
651fn decode_array_element(cursor: &mut Cursor<'_>, elem_type: &ValueType) -> Result<Value, AbiError> {
653 Ok(match elem_type {
654 ValueType::Bool => Value::Bool(cursor.read_u8()? != 0),
655 ValueType::U8 => Value::U8(cursor.read_u8()?),
656 ValueType::S8 => Value::S8(cursor.read_u8()? as i8),
657 ValueType::U16 => Value::U16(cursor.read_u16()?),
658 ValueType::S16 => Value::S16(cursor.read_u16()? as i16),
659 ValueType::U32 => Value::U32(cursor.read_u32()?),
660 ValueType::S32 => Value::S32(cursor.read_u32()? as i32),
661 ValueType::U64 => Value::U64(cursor.read_u64()?),
662 ValueType::S64 => Value::S64(cursor.read_u64()? as i64),
663 ValueType::F32 => {
664 let raw = cursor.read_u32()?;
665 Value::F32(f32::from_le_bytes(raw.to_le_bytes()))
666 }
667 ValueType::F64 => {
668 let raw = cursor.read_u64()?;
669 Value::F64(f64::from_le_bytes(raw.to_le_bytes()))
670 }
671 ValueType::Char => {
672 let raw = cursor.read_u32()?;
673 Value::Char(
674 char::from_u32(raw).ok_or_else(|| {
675 AbiError::InvalidEncoding(String::from("Invalid char in array"))
676 })?,
677 )
678 }
679 ValueType::Flags => Value::Flags(cursor.read_u64()?),
680 _ => {
681 return Err(AbiError::InvalidEncoding(String::from(
682 "Non-primitive type in array",
683 )))
684 }
685 })
686}
687
688fn encode_value_type(ty: &ValueType, out: &mut Vec<u8>) {
690 match ty {
691 ValueType::Bool => out.push(TYPE_BOOL),
692 ValueType::U8 => out.push(TYPE_U8),
693 ValueType::U16 => out.push(TYPE_U16),
694 ValueType::U32 => out.push(TYPE_U32),
695 ValueType::U64 => out.push(TYPE_U64),
696 ValueType::S8 => out.push(TYPE_S8),
697 ValueType::S16 => out.push(TYPE_S16),
698 ValueType::S32 => out.push(TYPE_S32),
699 ValueType::S64 => out.push(TYPE_S64),
700 ValueType::F32 => out.push(TYPE_F32),
701 ValueType::F64 => out.push(TYPE_F64),
702 ValueType::Char => out.push(TYPE_CHAR),
703 ValueType::String => out.push(TYPE_STRING),
704 ValueType::Flags => out.push(TYPE_FLAGS),
705 ValueType::List(elem) => {
706 out.push(TYPE_LIST);
707 encode_value_type(elem, out);
708 }
709 ValueType::Option(inner) => {
710 out.push(TYPE_OPTION);
711 encode_value_type(inner, out);
712 }
713 ValueType::Result { ok, err } => {
714 out.push(TYPE_RESULT);
715 encode_value_type(ok, out);
716 encode_value_type(err, out);
717 }
718 ValueType::Record(name) => {
719 out.push(TYPE_RECORD);
720 let bytes = name.as_bytes();
721 out.extend_from_slice(&(bytes.len() as u32).to_le_bytes());
722 out.extend_from_slice(bytes);
723 }
724 ValueType::Variant(name) => {
725 out.push(TYPE_VARIANT);
726 let bytes = name.as_bytes();
727 out.extend_from_slice(&(bytes.len() as u32).to_le_bytes());
728 out.extend_from_slice(bytes);
729 }
730 ValueType::Tuple(elems) => {
731 out.push(TYPE_TUPLE);
732 out.extend_from_slice(&(elems.len() as u32).to_le_bytes());
733 for elem in elems {
734 encode_value_type(elem, out);
735 }
736 }
737 }
738}
739
740fn decode_value_type(cursor: &mut Cursor<'_>) -> Result<ValueType, AbiError> {
742 let tag = cursor.read_u8()?;
743 match tag {
744 TYPE_BOOL => Ok(ValueType::Bool),
745 TYPE_U8 => Ok(ValueType::U8),
746 TYPE_U16 => Ok(ValueType::U16),
747 TYPE_U32 => Ok(ValueType::U32),
748 TYPE_U64 => Ok(ValueType::U64),
749 TYPE_S8 => Ok(ValueType::S8),
750 TYPE_S16 => Ok(ValueType::S16),
751 TYPE_S32 => Ok(ValueType::S32),
752 TYPE_S64 => Ok(ValueType::S64),
753 TYPE_F32 => Ok(ValueType::F32),
754 TYPE_F64 => Ok(ValueType::F64),
755 TYPE_CHAR => Ok(ValueType::Char),
756 TYPE_STRING => Ok(ValueType::String),
757 TYPE_FLAGS => Ok(ValueType::Flags),
758 TYPE_LIST => {
759 let elem = decode_value_type(cursor)?;
760 Ok(ValueType::List(Box::new(elem)))
761 }
762 TYPE_OPTION => {
763 let inner = decode_value_type(cursor)?;
764 Ok(ValueType::Option(Box::new(inner)))
765 }
766 TYPE_RESULT => {
767 let ok = decode_value_type(cursor)?;
768 let err = decode_value_type(cursor)?;
769 Ok(ValueType::Result {
770 ok: Box::new(ok),
771 err: Box::new(err),
772 })
773 }
774 TYPE_RECORD => {
775 let len = cursor.read_u32()? as usize;
776 let bytes = cursor.read_bytes(len)?;
777 let name = core::str::from_utf8(bytes).map_err(|_| {
778 AbiError::InvalidEncoding(String::from("Invalid UTF-8 in type name"))
779 })?;
780 Ok(ValueType::Record(String::from(name)))
781 }
782 TYPE_VARIANT => {
783 let len = cursor.read_u32()? as usize;
784 let bytes = cursor.read_bytes(len)?;
785 let name = core::str::from_utf8(bytes).map_err(|_| {
786 AbiError::InvalidEncoding(String::from("Invalid UTF-8 in type name"))
787 })?;
788 Ok(ValueType::Variant(String::from(name)))
789 }
790 TYPE_TUPLE => {
791 let count = cursor.read_u32()? as usize;
792 let mut elems = Vec::with_capacity(count);
793 for _ in 0..count {
794 elems.push(decode_value_type(cursor)?);
795 }
796 Ok(ValueType::Tuple(elems))
797 }
798 _ => Err(AbiError::InvalidTag(tag)),
799 }
800}
801
802impl GraphCodec for Value {
803 fn encode_graph(&self, encoder: &mut Encoder) -> Result<u32, AbiError> {
804 match self {
805 Value::Bool(value) => Ok(encoder.push_node(Node {
806 kind: NodeKind::Bool,
807 payload: vec![u8::from(*value)],
808 })),
809 Value::U8(value) => Ok(encoder.push_node(Node {
810 kind: NodeKind::U8,
811 payload: vec![*value],
812 })),
813 Value::U16(value) => Ok(encoder.push_node(Node {
814 kind: NodeKind::U16,
815 payload: value.to_le_bytes().to_vec(),
816 })),
817 Value::U32(value) => Ok(encoder.push_node(Node {
818 kind: NodeKind::U32,
819 payload: value.to_le_bytes().to_vec(),
820 })),
821 Value::U64(value) => Ok(encoder.push_node(Node {
822 kind: NodeKind::U64,
823 payload: value.to_le_bytes().to_vec(),
824 })),
825 Value::S8(value) => Ok(encoder.push_node(Node {
826 kind: NodeKind::S8,
827 payload: value.to_le_bytes().to_vec(),
828 })),
829 Value::S16(value) => Ok(encoder.push_node(Node {
830 kind: NodeKind::S16,
831 payload: value.to_le_bytes().to_vec(),
832 })),
833 Value::S32(value) => Ok(encoder.push_node(Node {
834 kind: NodeKind::S32,
835 payload: value.to_le_bytes().to_vec(),
836 })),
837 Value::S64(value) => Ok(encoder.push_node(Node {
838 kind: NodeKind::S64,
839 payload: value.to_le_bytes().to_vec(),
840 })),
841 Value::F32(value) => Ok(encoder.push_node(Node {
842 kind: NodeKind::F32,
843 payload: value.to_le_bytes().to_vec(),
844 })),
845 Value::F64(value) => Ok(encoder.push_node(Node {
846 kind: NodeKind::F64,
847 payload: value.to_le_bytes().to_vec(),
848 })),
849 Value::Char(value) => Ok(encoder.push_node(Node {
850 kind: NodeKind::Char,
851 payload: (*value as u32).to_le_bytes().to_vec(),
852 })),
853 Value::Flags(mask) => Ok(encoder.push_node(Node {
854 kind: NodeKind::Flags,
855 payload: mask.to_le_bytes().to_vec(),
856 })),
857 Value::String(value) => {
858 let bytes = value.as_bytes();
859 let mut payload = Vec::with_capacity(4 + bytes.len());
860 payload.extend_from_slice(&(bytes.len() as u32).to_le_bytes());
861 payload.extend_from_slice(bytes);
862 Ok(encoder.push_node(Node {
863 kind: NodeKind::String,
864 payload,
865 }))
866 }
867 Value::List { elem_type, items }
868 if fixed_width(elem_type).is_some()
869 && items.iter().all(|v| v.infer_type() == *elem_type) =>
870 {
871 let width = fixed_width(elem_type).unwrap();
874 let mut payload = Vec::with_capacity(1 + 4 + items.len() * width);
875 encode_value_type(elem_type, &mut payload);
876 payload.extend_from_slice(&(items.len() as u32).to_le_bytes());
877 for item in items {
878 encode_array_element(item, elem_type, &mut payload)?;
879 }
880 Ok(encoder.push_node(Node {
881 kind: NodeKind::Array,
882 payload,
883 }))
884 }
885 Value::List { elem_type, items } => {
886 if fixed_width(elem_type).is_some() {
888 return Err(AbiError::InvalidEncoding(String::from(
889 "List with primitive elem_type contains non-matching items; \
890 fix the elem_type or the items",
891 )));
892 }
893 let mut child_indices = Vec::with_capacity(items.len());
895 for item in items {
896 child_indices.push(item.encode_graph(encoder)?);
897 }
898 let mut payload = Vec::new();
900 encode_value_type(elem_type, &mut payload);
901 payload.extend_from_slice(&(child_indices.len() as u32).to_le_bytes());
902 for child in child_indices {
903 payload.extend_from_slice(&child.to_le_bytes());
904 }
905 Ok(encoder.push_node(Node {
906 kind: NodeKind::List,
907 payload,
908 }))
909 }
910 Value::Tuple(items) => {
911 let mut child_indices = Vec::with_capacity(items.len());
912 for item in items {
913 child_indices.push(item.encode_graph(encoder)?);
914 }
915 let mut payload = Vec::with_capacity(4 + 4 * child_indices.len());
916 payload.extend_from_slice(&(child_indices.len() as u32).to_le_bytes());
917 for child in child_indices {
918 payload.extend_from_slice(&child.to_le_bytes());
919 }
920 Ok(encoder.push_node(Node {
921 kind: NodeKind::Tuple,
922 payload,
923 }))
924 }
925 Value::Option { inner_type, value } => {
926 let mut payload = Vec::new();
928 encode_value_type(inner_type, &mut payload);
929 if let Some(inner) = value {
930 payload.push(1);
931 let child = inner.encode_graph(encoder)?;
932 payload.extend_from_slice(&child.to_le_bytes());
933 } else {
934 payload.push(0);
935 }
936 Ok(encoder.push_node(Node {
937 kind: NodeKind::Option,
938 payload,
939 }))
940 }
941 Value::Result {
942 ok_type,
943 err_type,
944 value,
945 } => {
946 let mut payload = Vec::new();
948 encode_value_type(ok_type, &mut payload);
949 encode_value_type(err_type, &mut payload);
950 match value {
951 Ok(inner) => {
952 payload.extend_from_slice(&0u32.to_le_bytes()); payload.push(1);
954 let child = inner.encode_graph(encoder)?;
955 payload.extend_from_slice(&child.to_le_bytes());
956 }
957 Err(inner) => {
958 payload.extend_from_slice(&1u32.to_le_bytes()); payload.push(1);
960 let child = inner.encode_graph(encoder)?;
961 payload.extend_from_slice(&child.to_le_bytes());
962 }
963 }
964 Ok(encoder.push_node(Node {
965 kind: NodeKind::Result,
966 payload,
967 }))
968 }
969 Value::Record { type_name, fields } => {
970 let mut child_indices = Vec::with_capacity(fields.len());
972 for (_, value) in fields {
973 child_indices.push(value.encode_graph(encoder)?);
974 }
975 let mut payload = Vec::new();
977 let name_bytes = type_name.as_bytes();
978 payload.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
979 payload.extend_from_slice(name_bytes);
980 payload.extend_from_slice(&(fields.len() as u32).to_le_bytes());
981 for (name, _) in fields {
982 let field_name_bytes = name.as_bytes();
983 payload.extend_from_slice(&(field_name_bytes.len() as u32).to_le_bytes());
984 payload.extend_from_slice(field_name_bytes);
985 }
986 for child in child_indices {
987 payload.extend_from_slice(&child.to_le_bytes());
988 }
989 Ok(encoder.push_node(Node {
990 kind: NodeKind::Record,
991 payload,
992 }))
993 }
994 Value::Variant {
995 type_name,
996 case_name,
997 tag,
998 payload: var_payload,
999 } => {
1000 let mut child_indices = Vec::with_capacity(var_payload.len());
1002 for item in var_payload {
1003 child_indices.push(item.encode_graph(encoder)?);
1004 }
1005 let mut payload = Vec::new();
1007 let type_bytes = type_name.as_bytes();
1008 payload.extend_from_slice(&(type_bytes.len() as u32).to_le_bytes());
1009 payload.extend_from_slice(type_bytes);
1010 let case_bytes = case_name.as_bytes();
1011 payload.extend_from_slice(&(case_bytes.len() as u32).to_le_bytes());
1012 payload.extend_from_slice(case_bytes);
1013 payload.extend_from_slice(&(*tag as u32).to_le_bytes());
1014 payload.extend_from_slice(&(child_indices.len() as u32).to_le_bytes());
1015 for child in child_indices {
1016 payload.extend_from_slice(&child.to_le_bytes());
1017 }
1018 Ok(encoder.push_node(Node {
1019 kind: NodeKind::Variant,
1020 payload,
1021 }))
1022 }
1023 }
1024 }
1025
1026 fn decode_graph(decoder: &Decoder<'_>, root: u32) -> Result<Self, AbiError> {
1027 let mut cache = HashMap::new();
1028 let mut visiting = HashSet::new();
1029 decode_value(decoder, root, &mut cache, &mut visiting)
1030 }
1031}
1032
1033fn decode_value(
1034 decoder: &Decoder<'_>,
1035 index: u32,
1036 cache: &mut HashMap<u32, Value>,
1037 visiting: &mut HashSet<u32>,
1038) -> Result<Value, AbiError> {
1039 if let Some(value) = cache.get(&index) {
1040 return Ok(value.clone());
1041 }
1042
1043 if !visiting.insert(index) {
1044 return Err(AbiError::InvalidEncoding(String::from(
1045 "Cycle detected in graph buffer",
1046 )));
1047 }
1048
1049 let node = decoder
1050 .node(index)
1051 .ok_or_else(|| AbiError::InvalidEncoding(format!("Node index {index} out of range")))?;
1052 let mut cursor = Cursor::new(&node.payload);
1053 let value = match node.kind {
1054 NodeKind::Bool => Value::Bool(cursor.read_u8()? == 1),
1055 NodeKind::U8 => Value::U8(cursor.read_u8()?),
1056 NodeKind::U16 => Value::U16(cursor.read_u16()?),
1057 NodeKind::U32 => Value::U32(cursor.read_u32()?),
1058 NodeKind::U64 => Value::U64(cursor.read_u64()?),
1059 NodeKind::S8 => {
1060 let raw = cursor.read_u8()?;
1061 Value::S8(i8::from_le_bytes([raw]))
1062 }
1063 NodeKind::S16 => {
1064 let raw = cursor.read_u16()?;
1065 Value::S16(i16::from_le_bytes(raw.to_le_bytes()))
1066 }
1067 NodeKind::S32 => {
1068 let raw = cursor.read_u32()?;
1069 Value::S32(i32::from_le_bytes(raw.to_le_bytes()))
1070 }
1071 NodeKind::S64 => {
1072 let raw = cursor.read_u64()?;
1073 Value::S64(i64::from_le_bytes(raw.to_le_bytes()))
1074 }
1075 NodeKind::F32 => {
1076 let raw = cursor.read_u32()?;
1077 Value::F32(f32::from_le_bytes(raw.to_le_bytes()))
1078 }
1079 NodeKind::F64 => {
1080 let raw = cursor.read_u64()?;
1081 Value::F64(f64::from_le_bytes(raw.to_le_bytes()))
1082 }
1083 NodeKind::Char => {
1084 let raw = cursor.read_u32()?;
1085 let ch = char::from_u32(raw)
1086 .ok_or_else(|| AbiError::InvalidEncoding(String::from("Invalid char scalar")))?;
1087 Value::Char(ch)
1088 }
1089 NodeKind::Flags => Value::Flags(cursor.read_u64()?),
1090 NodeKind::String => {
1091 let len = cursor.read_u32()? as usize;
1092 let bytes = cursor.read_bytes(len)?;
1093 let s = core::str::from_utf8(bytes)
1094 .map_err(|_| AbiError::InvalidEncoding(String::from("Invalid UTF-8")))?;
1095 Value::String(String::from(s))
1096 }
1097 NodeKind::Array => {
1098 let elem_type = decode_value_type(&mut cursor)?;
1100 let count = cursor.read_u32()? as usize;
1101 let mut items = Vec::with_capacity(count);
1102 for _ in 0..count {
1103 items.push(decode_array_element(&mut cursor, &elem_type)?);
1104 }
1105 Value::List { elem_type, items }
1106 }
1107 NodeKind::List => {
1108 let elem_type = decode_value_type(&mut cursor)?;
1110 if fixed_width(&elem_type).is_some() {
1111 return Err(AbiError::InvalidEncoding(String::from(
1112 "List node with primitive elem_type; expected Array node",
1113 )));
1114 }
1115 let count = cursor.read_u32()? as usize;
1116 let mut items = Vec::with_capacity(count);
1117 for _ in 0..count {
1118 let child = cursor.read_u32()?;
1119 items.push(decode_value(decoder, child, cache, visiting)?);
1120 }
1121 Value::List { elem_type, items }
1122 }
1123 NodeKind::Record => {
1124 let type_name_len = cursor.read_u32()? as usize;
1126 let type_name_bytes = cursor.read_bytes(type_name_len)?;
1127 let type_name = core::str::from_utf8(type_name_bytes).map_err(|_| {
1128 AbiError::InvalidEncoding(String::from("Invalid UTF-8 in type name"))
1129 })?;
1130 let type_name = String::from(type_name);
1131 let count = cursor.read_u32()? as usize;
1132 let mut field_names = Vec::with_capacity(count);
1133 for _ in 0..count {
1134 let name_len = cursor.read_u32()? as usize;
1135 let name_bytes = cursor.read_bytes(name_len)?;
1136 let name = core::str::from_utf8(name_bytes).map_err(|_| {
1137 AbiError::InvalidEncoding(String::from("Invalid UTF-8 in field name"))
1138 })?;
1139 field_names.push(String::from(name));
1140 }
1141 let mut fields = Vec::with_capacity(count);
1142 for name in field_names {
1143 let child = cursor.read_u32()?;
1144 let value = decode_value(decoder, child, cache, visiting)?;
1145 fields.push((name, value));
1146 }
1147 Value::Record { type_name, fields }
1148 }
1149 NodeKind::Tuple => {
1150 let count = cursor.read_u32()? as usize;
1151 let mut items = Vec::with_capacity(count);
1152 for _ in 0..count {
1153 let child = cursor.read_u32()?;
1154 items.push(decode_value(decoder, child, cache, visiting)?);
1155 }
1156 Value::Tuple(items)
1157 }
1158 NodeKind::Option => {
1159 let inner_type = decode_value_type(&mut cursor)?;
1161 let has_value = cursor.read_u8()?;
1162 let value = if has_value == 1 {
1163 let child = cursor.read_u32()?;
1164 Some(alloc::boxed::Box::new(decode_value(
1165 decoder, child, cache, visiting,
1166 )?))
1167 } else {
1168 None
1169 };
1170 Value::Option { inner_type, value }
1171 }
1172 NodeKind::Result => {
1173 let ok_type = decode_value_type(&mut cursor)?;
1175 let err_type = decode_value_type(&mut cursor)?;
1176 let tag = cursor.read_u32()?;
1177 let has_payload = cursor.read_u8()?;
1178 let value = if has_payload == 1 {
1179 let child = cursor.read_u32()?;
1180 let inner = decode_value(decoder, child, cache, visiting)?;
1181 if tag == 0 {
1182 Ok(alloc::boxed::Box::new(inner))
1183 } else {
1184 Err(alloc::boxed::Box::new(inner))
1185 }
1186 } else {
1187 return Err(AbiError::InvalidEncoding(String::from(
1188 "Result must have payload",
1189 )));
1190 };
1191 Value::Result {
1192 ok_type,
1193 err_type,
1194 value,
1195 }
1196 }
1197 NodeKind::Variant => {
1198 let type_name_len = cursor.read_u32()? as usize;
1200 let type_name_bytes = cursor.read_bytes(type_name_len)?;
1201 let type_name = core::str::from_utf8(type_name_bytes).map_err(|_| {
1202 AbiError::InvalidEncoding(String::from("Invalid UTF-8 in type name"))
1203 })?;
1204 let type_name = String::from(type_name);
1205 let case_name_len = cursor.read_u32()? as usize;
1206 let case_name_bytes = cursor.read_bytes(case_name_len)?;
1207 let case_name = core::str::from_utf8(case_name_bytes).map_err(|_| {
1208 AbiError::InvalidEncoding(String::from("Invalid UTF-8 in case name"))
1209 })?;
1210 let case_name = String::from(case_name);
1211 let tag = cursor.read_u32()? as usize;
1212 let payload_count = cursor.read_u32()? as usize;
1213 let mut payload = Vec::with_capacity(payload_count);
1214 for _ in 0..payload_count {
1215 let child = cursor.read_u32()?;
1216 payload.push(decode_value(decoder, child, cache, visiting)?);
1217 }
1218 Value::Variant {
1219 type_name,
1220 case_name,
1221 tag,
1222 payload,
1223 }
1224 }
1225 };
1226
1227 if !cursor.is_eof() {
1228 return Err(AbiError::InvalidEncoding(format!(
1229 "Trailing payload bytes at node {index}"
1230 )));
1231 }
1232
1233 visiting.remove(&index);
1234 cache.insert(index, value.clone());
1235 Ok(value)
1236}