embedded_layout/
object_chain.rs1mod private {
9 pub trait Sealed {}
10
11 impl<V> Sealed for super::Chain<V> {}
12 impl<V, C: super::ChainElement> Sealed for super::Link<V, C> {}
13}
14
15pub trait ChainElement: Sized + private::Sealed {
17 fn len(&self) -> usize;
19}
20
21pub struct Link<V, C: ChainElement> {
23 pub object: V,
25
26 pub parent: C,
28}
29
30impl<V, C: ChainElement> Link<V, C> {
31 #[inline]
33 pub fn append<T>(self, item: T) -> Link<T, Self> {
34 Link {
35 object: item,
36 parent: self,
37 }
38 }
39}
40
41impl<V, C> Clone for Link<V, C>
42where
43 V: Clone,
44 C: ChainElement + Clone,
45{
46 fn clone(&self) -> Self {
47 Self {
48 object: self.object.clone(),
49 parent: self.parent.clone(),
50 }
51 }
52}
53
54impl<V, VC> ChainElement for Link<V, VC>
55where
56 VC: ChainElement,
57{
58 #[inline]
59 fn len(&self) -> usize {
60 self.parent.len() + 1
61 }
62}
63
64pub struct Chain<V> {
66 pub object: V,
68}
69
70impl<V> Chain<V> {
71 #[inline]
73 pub fn append<T>(self, item: T) -> Link<T, Self> {
74 Link {
75 object: item,
76 parent: self,
77 }
78 }
79}
80
81impl<V> Chain<V> {
82 #[inline]
84 pub const fn new(object: V) -> Self {
85 Self { object }
86 }
87}
88
89impl<V> Clone for Chain<V>
90where
91 V: Clone,
92{
93 fn clone(&self) -> Self {
94 Self {
95 object: self.object.clone(),
96 }
97 }
98}
99
100impl<V> ChainElement for Chain<V> {
101 #[inline]
102 fn len(&self) -> usize {
103 1
104 }
105}
106
107#[doc(hidden)]
109#[macro_export(local_inner_macros)]
110macro_rules! chain_impl {
111 ($x:ty) => {
112 Chain<$x>
113 };
114 ($x:ty,) => {
115 Chain<$x>
116 };
117 ($x:ty, $($rest:tt)+) => {
118 Link<$x, chain_impl! { $($rest)+ }>
119 };
120}
121
122#[doc(hidden)]
124#[macro_export(local_inner_macros)]
125macro_rules! reverse {
126 ([] $($reversed:tt)+) => {
127 chain_impl! { $($reversed)+ }
128 };
129 ([$first:ty] $($reversed:tt)*) => {
130 reverse! { [ ] $first, $($reversed)* }
131 };
132 ([$first:ty, $($rest:ty),*] $($reversed:tt)*) => {
133 reverse! { [ $($rest),* ] $first, $($reversed)* }
134 };
135}
136
137#[macro_export(local_inner_macros)]
162macro_rules! chain {
163 ( $($types:ty),+ ) => {
164 reverse!{ [ $($types),+ ] }
165 };
166}
167
168#[cfg(test)]
169mod test {
170 #![allow(dead_code)]
171 use super::*;
172 use core::marker::PhantomData;
173
174 struct CompileTest {
175 chain1: chain! {
176 u8
177 },
178 generic_in_chain: chain! {
179 Generic<'static, u32>
180 },
181 chain: chain! {
182 u8, u16, u32
183 },
184 }
185
186 struct Generic<'a, T> {
187 field: PhantomData<&'a T>,
188 }
189
190 #[test]
191 pub fn test() {
192 fn f(_obj_chain: &chain! {u8, u16, u32}) {}
193
194 let test = CompileTest {
195 chain1: Chain::new(0),
196 generic_in_chain: Chain::new(Generic { field: PhantomData }),
197 chain: Chain::new(0u8).append(1u16).append(2u32),
198 };
199
200 f(&test.chain);
201 }
202
203 #[test]
204 pub fn test_count() {
205 assert_eq!(1, Chain::new(0).len());
206 assert_eq!(3, Chain::new(0u8).append(1u16).append(2u32).len());
207 }
208}
209
210#[cfg(test)]
211#[allow(dead_code)]
212mod test_macro {
213 use crate::prelude::*;
214 use embedded_graphics::primitives::{Rectangle, Triangle};
215
216 type Views = chain! {
217 Rectangle,
218 Rectangle,
219 Triangle
220 };
221}