tarantool_rs/
tuple.rs

1use std::io::Write;
2
3use crate::errors::EncodingError;
4
5pub trait TupleElement {
6    fn encode_into_writer<W: Write>(&self, buf: W) -> Result<(), EncodingError>;
7}
8
9impl<T: serde::Serialize> TupleElement for T {
10    fn encode_into_writer<W: Write>(&self, mut buf: W) -> Result<(), EncodingError> {
11        rmp_serde::encode::write(&mut buf, self)?;
12        Ok(())
13    }
14}
15
16/// Trait, describing type, which can be encoded into
17/// MessagePack tuple.
18///
19/// It is mostly used to pass arguments to Tarantool requests,
20/// like passing arguments for `CALL`.
21pub trait Tuple {
22    fn encode_into_writer<W: Write>(&self, buf: W) -> Result<(), EncodingError>;
23}
24
25impl<T: TupleElement> Tuple for Vec<T> {
26    fn encode_into_writer<W: Write>(&self, mut buf: W) -> Result<(), EncodingError> {
27        rmp::encode::write_array_len(&mut buf, self.len() as u32)?;
28        for x in self.iter() {
29            x.encode_into_writer(&mut buf)?;
30        }
31        Ok(())
32    }
33}
34
35impl<T: TupleElement> Tuple for &[T] {
36    fn encode_into_writer<W: Write>(&self, mut buf: W) -> Result<(), EncodingError> {
37        rmp::encode::write_array_len(&mut buf, self.len() as u32)?;
38        for x in self.iter() {
39            x.encode_into_writer(&mut buf)?;
40        }
41        Ok(())
42    }
43}
44
45impl Tuple for () {
46    fn encode_into_writer<W: Write>(&self, mut buf: W) -> Result<(), EncodingError> {
47        rmp::encode::write_array_len(&mut buf, 0)?;
48        Ok(())
49    }
50}
51
52impl<T: Tuple> Tuple for &T {
53    fn encode_into_writer<W: Write>(&self, buf: W) -> Result<(), EncodingError> {
54        (*self).encode_into_writer(buf)
55    }
56}
57
58// `= self` idea is from https://stackoverflow.com/a/56700760/5033855
59macro_rules! impl_tuple_for_tuple {
60    ( $param:tt ) => {
61        impl<$param : $crate::TupleElement> Tuple for ($param,) {
62            fn encode_into_writer<W: Write>(&self, mut buf: W) -> Result<(), EncodingError> {
63                rmp::encode::write_array_len(&mut buf, 1)?;
64                self.0.encode_into_writer(&mut buf)?;
65                Ok(())
66            }
67        }
68    };
69    ( $param:tt, $($params:tt),* ) => {
70        impl<$param : $crate::TupleElement , $($params : $crate::TupleElement,)*> Tuple for ($param, $($params,)*) {
71            #[allow(non_snake_case)]
72            fn encode_into_writer<W: Write>(&self, mut buf: W) -> Result<(), EncodingError> {
73                rmp::encode::write_array_len(&mut buf, count_tts!($param $($params)+) as u32)?;
74
75                let ($param, $($params,)+) = self;
76
77                $param.encode_into_writer(&mut buf)?;
78
79                $(
80                    $params.encode_into_writer(&mut buf)?;
81                )+
82
83                Ok(())
84            }
85        }
86
87        impl_tuple_for_tuple! { $($params),* }
88    };
89}
90
91// Counting macro from https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html
92macro_rules! count_tts {
93    ($($tts:tt)*) => {0usize $(+ replace_expr!($tts 1usize))*};
94}
95
96macro_rules! replace_expr {
97    ($_t:tt $sub:expr) => {
98        $sub
99    };
100}
101
102impl_tuple_for_tuple! {
103    T32, T31, T30, T29, T28, T27, T26, T25, T24, T23,
104    T22, T21, T20, T19, T18, T17, T16, T15, T14, T13,
105    T12, T11, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1
106}