1use std::collections::{BTreeMap, BTreeSet};
17
18use crate::{MsgpackTagged, TagRegistry, Tagged};
19
20const LEAF: Tagged = Tagged::empty_product();
21
22impl<T: MsgpackTagged> MsgpackTagged for Vec<T> {
23 const TAGGED: Tagged = LEAF;
24 fn register_into(reg: &mut TagRegistry) {
25 T::register_into(reg);
26 }
27}
28
29impl<T: MsgpackTagged, const N: usize> MsgpackTagged for [T; N] {
30 const TAGGED: Tagged = LEAF;
31 fn register_into(reg: &mut TagRegistry) {
32 T::register_into(reg);
33 }
34}
35
36impl<T: MsgpackTagged> MsgpackTagged for Option<T> {
37 const TAGGED: Tagged = LEAF;
38 fn register_into(reg: &mut TagRegistry) {
39 T::register_into(reg);
40 }
41}
42
43impl<T: MsgpackTagged> MsgpackTagged for Box<T> {
44 const TAGGED: Tagged = LEAF;
45 fn register_into(reg: &mut TagRegistry) {
46 T::register_into(reg);
47 }
48}
49
50impl<K: MsgpackTagged, V: MsgpackTagged> MsgpackTagged for BTreeMap<K, V> {
51 const TAGGED: Tagged = LEAF;
52 fn register_into(reg: &mut TagRegistry) {
53 K::register_into(reg);
54 V::register_into(reg);
55 }
56}
57
58impl<T: MsgpackTagged> MsgpackTagged for BTreeSet<T> {
59 const TAGGED: Tagged = LEAF;
60 fn register_into(reg: &mut TagRegistry) {
61 T::register_into(reg);
62 }
63}
64
65macro_rules! impl_msgpack_tagged_for_tuple {
66 ($($t:ident),+ $(,)?) => {
67 impl<$($t: MsgpackTagged),+> MsgpackTagged for ($($t,)+) {
68 const TAGGED: Tagged = LEAF;
69 fn register_into(reg: &mut TagRegistry) {
70 $($t::register_into(reg);)+
71 }
72 }
73 };
74}
75
76impl_msgpack_tagged_for_tuple!(T0);
77impl_msgpack_tagged_for_tuple!(T0, T1);
78impl_msgpack_tagged_for_tuple!(T0, T1, T2);
79impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3);
80impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4);
81impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5);
82impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5, T6);
83impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5, T6, T7);
84impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
85impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
86impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
87impl_msgpack_tagged_for_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
88
89#[cfg(test)]
90mod tests {
91 use crate::Product;
92
93 use super::*;
94
95 struct Foo;
98 impl MsgpackTagged for Foo {
99 const TAGGED: Tagged = Tagged::Product(Product {
100 fields: &[(0, "x")],
101 reserved: &[],
102 allow_unknown_tags: false,
103 tag_order_matches_source: true,
104 });
105 fn register_into(reg: &mut TagRegistry) {
106 reg.try_insert::<Foo>("Foo");
107 }
108 }
109
110 struct Bar;
112 impl MsgpackTagged for Bar {
113 const TAGGED: Tagged = Tagged::Product(Product {
114 fields: &[(0, "y")],
115 reserved: &[],
116 allow_unknown_tags: false,
117 tag_order_matches_source: true,
118 });
119 fn register_into(reg: &mut TagRegistry) {
120 reg.try_insert::<Bar>("Bar");
121 }
122 }
123
124 #[test]
127 fn each_container_satisfies_the_trait_bound() {
128 fn assert_impl<T: MsgpackTagged>() {}
129 assert_impl::<Vec<u32>>();
130 assert_impl::<[u32; 4]>();
131 assert_impl::<Option<u32>>();
132 assert_impl::<Box<u32>>();
133 assert_impl::<BTreeMap<String, u32>>();
134 assert_impl::<BTreeSet<u32>>();
135 assert_impl::<(u32,)>();
136 assert_impl::<(u32, u32)>();
137 assert_impl::<(u32, u32, u32)>();
138 assert_impl::<(u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32)>();
139 }
140
141 #[test]
142 fn vec_recurses_into_inner() {
143 let mut reg = TagRegistry::new();
144 <Vec<Foo>>::register_into(&mut reg);
145 assert_eq!(reg.len(), 1);
146 assert!(reg.get("Foo").is_some());
147 }
148
149 #[test]
150 fn option_recurses_into_inner() {
151 let mut reg = TagRegistry::new();
152 <Option<Foo>>::register_into(&mut reg);
153 assert!(reg.get("Foo").is_some());
154 }
155
156 #[test]
157 fn array_recurses_into_inner() {
158 let mut reg = TagRegistry::new();
159 <[Foo; 7]>::register_into(&mut reg);
160 assert!(reg.get("Foo").is_some());
161 }
162
163 #[test]
164 fn box_recurses_into_inner() {
165 let mut reg = TagRegistry::new();
166 <Box<Foo>>::register_into(&mut reg);
167 assert!(reg.get("Foo").is_some());
168 }
169
170 #[test]
171 fn btreemap_recurses_into_key_and_value() {
172 let mut reg = TagRegistry::new();
173 <BTreeMap<Foo, Bar>>::register_into(&mut reg);
174 assert_eq!(reg.len(), 2);
175 assert!(reg.get("Foo").is_some());
176 assert!(reg.get("Bar").is_some());
177 }
178
179 #[test]
180 fn btreeset_recurses_into_inner() {
181 let mut reg = TagRegistry::new();
182 <BTreeSet<Foo>>::register_into(&mut reg);
183 assert!(reg.get("Foo").is_some());
184 }
185
186 #[test]
187 fn tuple_recurses_into_each_element() {
188 let mut reg = TagRegistry::new();
189 <(Foo, Bar)>::register_into(&mut reg);
190 assert!(reg.get("Foo").is_some());
191 assert!(reg.get("Bar").is_some());
192 }
193
194 #[test]
197 fn nested_containers_recurse_through() {
198 let mut reg = TagRegistry::new();
199 <Vec<Option<Foo>>>::register_into(&mut reg);
200 assert_eq!(reg.len(), 1);
201 assert!(reg.get("Foo").is_some());
202 }
203
204 #[test]
207 fn container_of_primitive_doesnt_populate_registry() {
208 let mut reg = TagRegistry::new();
209 <Vec<u32>>::register_into(&mut reg);
210 <Option<bool>>::register_into(&mut reg);
211 <BTreeMap<String, u64>>::register_into(&mut reg);
212 <(u32, u64, bool)>::register_into(&mut reg);
213 assert!(reg.is_empty());
214 }
215}