1use topcoat_core::context::Cx;
2
3use crate::{PartsWriter, Unescaped, ViewPart};
4
5pub trait AttributeValueViewParts {
28 fn attribute_present(&self) -> bool;
34
35 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>);
37}
38
39macro_rules! impl_primitive {
40 ($ty:ty, $method:ident) => {
41 impl AttributeValueViewParts for $ty {
42 #[inline]
43 fn attribute_present(&self) -> bool {
44 true
45 }
46
47 #[inline]
48 fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
49 parts.$method(self);
50 }
51 }
52 };
53 ($ty:ty, $method:ident, ref) => {
54 impl_primitive!($ty, $method);
55
56 impl AttributeValueViewParts for &$ty {
57 #[inline]
58 fn attribute_present(&self) -> bool {
59 (*self).attribute_present()
60 }
61
62 #[inline]
63 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>) {
64 (*self).into_view_parts(cx, parts);
65 }
66 }
67 };
68}
69
70impl_primitive!(char, push_char, ref);
71impl_primitive!(i8, push_i8, ref);
72impl_primitive!(i16, push_i16, ref);
73impl_primitive!(i32, push_i32, ref);
74impl_primitive!(i64, push_i64, ref);
75impl_primitive!(i128, push_i128, ref);
76impl_primitive!(isize, push_isize, ref);
77impl_primitive!(u8, push_u8, ref);
78impl_primitive!(u16, push_u16, ref);
79impl_primitive!(u32, push_u32, ref);
80impl_primitive!(u64, push_u64, ref);
81impl_primitive!(u128, push_u128, ref);
82impl_primitive!(usize, push_usize, ref);
83impl_primitive!(f32, push_f32, ref);
84impl_primitive!(f64, push_f64, ref);
85impl_primitive!(String, push_str);
86
87impl AttributeValueViewParts for &str {
88 #[inline]
89 fn attribute_present(&self) -> bool {
90 true
91 }
92
93 #[inline]
94 fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
95 parts.push_str(self.to_owned());
96 }
97}
98
99impl AttributeValueViewParts for Unescaped<String> {
100 #[inline]
101 fn attribute_present(&self) -> bool {
102 true
103 }
104
105 #[inline]
106 fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
107 parts.push_str_unescaped(self.0);
108 }
109}
110
111impl AttributeValueViewParts for Unescaped<&'static str> {
112 #[inline]
113 fn attribute_present(&self) -> bool {
114 true
115 }
116
117 #[inline]
118 fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
119 parts.push_str_unescaped(self.0);
120 }
121}
122
123impl AttributeValueViewParts for &String {
124 #[inline]
125 fn attribute_present(&self) -> bool {
126 self.as_str().attribute_present()
127 }
128
129 #[inline]
130 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>) {
131 self.as_str().into_view_parts(cx, parts);
132 }
133}
134
135impl AttributeValueViewParts for bool {
136 #[inline]
137 fn attribute_present(&self) -> bool {
138 *self
139 }
140
141 #[inline]
142 fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
143 parts.push_bool(self);
144 }
145}
146
147impl AttributeValueViewParts for &bool {
148 #[inline]
149 fn attribute_present(&self) -> bool {
150 (*self).attribute_present()
151 }
152
153 #[inline]
154 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>) {
155 (*self).into_view_parts(cx, parts);
156 }
157}
158
159impl<'b, T: ?Sized> AttributeValueViewParts for &&'b T
160where
161 &'b T: AttributeValueViewParts,
162{
163 #[inline]
164 fn attribute_present(&self) -> bool {
165 (**self).attribute_present()
166 }
167
168 #[inline]
169 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>) {
170 (*self).into_view_parts(cx, parts);
171 }
172}
173
174impl<T> AttributeValueViewParts for Option<T>
175where
176 T: AttributeValueViewParts,
177{
178 #[inline]
179 fn attribute_present(&self) -> bool {
180 self.as_ref()
181 .is_some_and(AttributeValueViewParts::attribute_present)
182 }
183
184 #[inline]
185 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>) {
186 if let Some(value) = self {
187 value.into_view_parts(cx, parts);
188 }
189 }
190}
191
192impl AttributeValueViewParts for ViewPart {
193 fn attribute_present(&self) -> bool {
194 match self {
195 Self::Empty | Self::Bool(false) => false,
196 Self::BoxSlice { inner, .. } if inner.is_empty() => false,
197 _ => true,
198 }
199 }
200
201 #[inline]
202 fn into_view_parts(self, _cx: &Cx, parts: &mut PartsWriter<'_>) {
203 parts.push_part(self);
204 }
205}
206
207macro_rules! impl_tuple {
208 ($($ty:ident),+) => {
209 impl<$($ty),+> AttributeValueViewParts for ($($ty,)+)
210 where
211 $($ty: AttributeValueViewParts,)+
212 {
213 #[inline]
214 #[allow(non_snake_case)]
215 fn attribute_present(&self) -> bool {
216 let ($($ty,)+) = self;
217 $($ty.attribute_present())||+
218 }
219
220 #[inline]
221 #[allow(non_snake_case)]
222 fn into_view_parts(self, cx: &Cx, parts: &mut PartsWriter<'_>) {
223 let ($($ty,)+) = self;
224 $($ty.into_view_parts(cx, parts);)+
225 }
226 }
227 };
228}
229
230impl_tuple!(T1);
231impl_tuple!(T1, T2);
232impl_tuple!(T1, T2, T3);
233impl_tuple!(T1, T2, T3, T4);
234impl_tuple!(T1, T2, T3, T4, T5);
235impl_tuple!(T1, T2, T3, T4, T5, T6);
236impl_tuple!(T1, T2, T3, T4, T5, T6, T7);
237impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
238impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
239impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
240impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
241impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);