1use crate::internal::{GenResult, SerializeFn, WriteContext};
3use crate::lib::std::io::Write;
4
5pub fn pair<F, G, W: Write>(first: F, second: G) -> impl SerializeFn<W>
21where
22 F: SerializeFn<W>,
23 G: SerializeFn<W>,
24{
25 move |out: WriteContext<W>| first(out).and_then(&second)
26}
27
28pub trait Tuple<W> {
30 fn serialize(&self, w: WriteContext<W>) -> GenResult<W>;
31}
32
33impl<W: Write, A: SerializeFn<W>> Tuple<W> for (A,) {
34 fn serialize(&self, w: WriteContext<W>) -> GenResult<W> {
35 self.0(w)
36 }
37}
38
39macro_rules! tuple_trait(
43 ($name1:ident, $name2: ident, $($name:ident),*) => (
44 tuple_trait!(__impl $name1, $name2; $($name),*);
45 );
46 (__impl $($name:ident),+; $name1:ident, $($name2:ident),*) => (
47 tuple_trait_impl!($($name),+);
48 tuple_trait!(__impl $($name),+ , $name1; $($name2),*);
49 );
50 (__impl $($name:ident),+; $name1:ident) => (
51 tuple_trait_impl!($($name),+);
52 tuple_trait_impl!($($name),+, $name1);
53 );
54);
55
56macro_rules! tuple_trait_impl(
60 ($($name:ident),+) => (
61 impl<W: Write, $($name: SerializeFn<W>),+> Tuple<W> for ( $($name),+ ) {
62 fn serialize(&self, w: WriteContext<W>) -> GenResult<W> {
63 tuple_trait_inner!(0, self, w, $($name)+)
64 }
65 }
66 );
67);
68
69macro_rules! tuple_trait_inner(
79 ($it:tt, $self:expr, $w:ident, $head:ident $($id:ident)+) => ({
80 let w = $self.$it($w)?;
81
82 succ!($it, tuple_trait_inner!($self, w, $($id)+))
83 });
84 ($it:tt, $self:expr, $w:ident, $head:ident) => ({
85 let w = $self.$it($w)?;
86
87 Ok(w)
88 });
89);
90
91#[doc(hidden)]
96macro_rules! succ (
97 (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
98 (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
99 (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
100 (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
101 (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
102 (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
103 (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
104 (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
105 (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
106 (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
107 (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
108 (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
109 (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
110 (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
111 (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
112 (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
113 (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
114 (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
115 (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
116 (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
117);
118
119tuple_trait!(
120 FnA, FnB, FnC, FnD, FnE, FnF, FnG, FnH, FnI, FnJ, FnK, FnL, FnM, FnN, FnO, FnP, FnQ, FnR, FnS,
121 FnT, FnU
122);
123
124pub fn tuple<W: Write, List: Tuple<W>>(l: List) -> impl SerializeFn<W> {
149 move |w: WriteContext<W>| l.serialize(w)
150}
151
152#[cfg(test)]
153mod test {
154 use super::*;
155 use crate::combinator::string;
156 use crate::internal::gen_simple;
157
158 #[test]
159 fn test_pair_with_cursor() {
160 let mut buf = [0u8; 8];
161
162 {
163 use crate::lib::std::io::Cursor;
164
165 let cursor = Cursor::new(&mut buf[..]);
166 let serializer = pair(string("1234"), string("5678"));
167
168 let cursor = gen_simple(serializer, cursor).unwrap();
169 assert_eq!(cursor.position(), 8);
170 }
171
172 assert_eq!(&buf[..], b"12345678");
173 }
174
175 #[test]
176 fn test_tuple() {
177 let mut buf = [0u8; 12];
178
179 {
180 use crate::lib::std::io::Cursor;
181
182 let cursor = Cursor::new(&mut buf[..]);
183 let serializer = tuple((string("1234"), string("5678"), tuple((string("0123"),))));
184
185 let cursor = gen_simple(serializer, cursor).unwrap();
186 assert_eq!(cursor.position(), 12);
187 }
188
189 assert_eq!(&buf[..], b"123456780123");
190 }
191}