Skip to main content

substrate_data/schema/plain/
tuples.rs

1//! The schemas of tuples: lists of their items in order.
2
3use crate::frame::{Packer, Unpacker};
4use crate::model::borrowed::ValueRef;
5use crate::model::value::{Seg, Value};
6use crate::schema::{Expected, Reader, Schema, Shape};
7
8/// A tuple, written as a list of its items in order: a pair `[a, b]` (a
9/// point, a size), a triple `[x, y, z]` (a position).
10macro_rules! tuples {
11    ($($n:literal => ($($t:ident $i:tt),+);)+) => {$(
12        impl<$($t: Schema),+> Schema for ($($t,)+) {
13            fn shape() -> Shape {
14                Shape::List(Value::shape)
15            }
16            fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
17                let ValueRef::List(items) = v else {
18                    cx.expected(Expected::Items($n), v);
19                    return None;
20                };
21                if items.len() != $n {
22                    cx.problem(format!("expected {} items, found {}", $n, items.len()));
23                    return None;
24                }
25                let read = ($(cx.at(Seg::Index($i), |cx| $t::read(&items[$i], cx)),)+);
26                Some(($(read.$i?,)+))
27            }
28            fn write(&self) -> Value {
29                Value::List(vec![$(self.$i.write()),+])
30            }
31            /// In a frame it's a list of any values, as its shape says:
32            /// each item in its binary form.
33            fn pack(&self, p: &mut Packer) {
34                let at = p.begin_list($n);
35                $(p.put_tagged(&self.$i);)+
36                p.end(at);
37            }
38            fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
39                let (n, end) = u.list()?;
40                if n != $n {
41                    return None;
42                }
43                let items = ($(u.tagged::<$t>()?,)+);
44                u.skip_to(end)?;
45                Some(items)
46            }
47        }
48    )+};
49}
50
51tuples! {
52    2 => (A 0, B 1);
53    3 => (A 0, B 1, C 2);
54    4 => (A 0, B 1, C 2, D 3);
55}