substrate_data/schema/plain/
tuples.rs1use crate::frame::{Packer, Unpacker};
4use crate::model::borrowed::ValueRef;
5use crate::model::value::{Seg, Value};
6use crate::schema::{Expected, Reader, Schema, Shape};
7
8macro_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 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}