1use crate::counter_style::CounterStyle;
8use crate::derives::*;
9use crate::values::specified::Attr;
10use crate::values::CustomIdent;
11use std::fmt::{self, Write};
12use std::ops::Deref;
13use style_traits::{CssWriter, ToCss};
14
15#[derive(
17 Clone,
18 Debug,
19 MallocSizeOf,
20 PartialEq,
21 SpecifiedValueInfo,
22 ToComputedValue,
23 ToResolvedValue,
24 ToShmem,
25)]
26#[repr(C)]
27pub struct GenericCounterPair<Integer> {
28 pub name: CustomIdent,
30 pub value: Integer,
32 pub is_reversed: bool,
35}
36pub use self::GenericCounterPair as CounterPair;
37
38impl<Integer> ToCss for CounterPair<Integer>
39where
40 Integer: ToCss + PartialEq<i32>,
41{
42 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
43 where
44 W: Write,
45 {
46 if self.is_reversed {
47 dest.write_str("reversed(")?;
48 }
49 self.name.to_css(dest)?;
50 if self.is_reversed {
51 dest.write_char(')')?;
52 if self.value == i32::min_value() {
53 return Ok(());
54 }
55 }
56 dest.write_char(' ')?;
57 self.value.to_css(dest)
58 }
59}
60
61#[derive(
63 Clone,
64 Debug,
65 Default,
66 MallocSizeOf,
67 PartialEq,
68 SpecifiedValueInfo,
69 ToComputedValue,
70 ToCss,
71 ToResolvedValue,
72 ToShmem,
73 ToTyped,
74)]
75#[repr(transparent)]
76#[typed(todo_derive_fields)]
77pub struct GenericCounterIncrement<I>(#[css(field_bound)] pub GenericCounters<I>);
78pub use self::GenericCounterIncrement as CounterIncrement;
79
80impl<I> CounterIncrement<I> {
81 #[inline]
83 pub fn new(counters: Vec<CounterPair<I>>) -> Self {
84 CounterIncrement(Counters(counters.into()))
85 }
86}
87
88impl<I> Deref for CounterIncrement<I> {
89 type Target = [CounterPair<I>];
90
91 #[inline]
92 fn deref(&self) -> &Self::Target {
93 &(self.0).0
94 }
95}
96
97#[derive(
99 Clone,
100 Debug,
101 Default,
102 MallocSizeOf,
103 PartialEq,
104 SpecifiedValueInfo,
105 ToComputedValue,
106 ToCss,
107 ToResolvedValue,
108 ToShmem,
109 ToTyped,
110)]
111#[repr(transparent)]
112#[typed(todo_derive_fields)]
113pub struct GenericCounterSet<I>(#[css(field_bound)] pub GenericCounters<I>);
114pub use self::GenericCounterSet as CounterSet;
115
116impl<I> CounterSet<I> {
117 #[inline]
119 pub fn new(counters: Vec<CounterPair<I>>) -> Self {
120 CounterSet(Counters(counters.into()))
121 }
122}
123
124impl<I> Deref for CounterSet<I> {
125 type Target = [CounterPair<I>];
126
127 #[inline]
128 fn deref(&self) -> &Self::Target {
129 &(self.0).0
130 }
131}
132
133#[derive(
135 Clone,
136 Debug,
137 Default,
138 MallocSizeOf,
139 PartialEq,
140 SpecifiedValueInfo,
141 ToComputedValue,
142 ToCss,
143 ToResolvedValue,
144 ToShmem,
145 ToTyped,
146)]
147#[repr(transparent)]
148#[typed(todo_derive_fields)]
149pub struct GenericCounterReset<I>(#[css(field_bound)] pub GenericCounters<I>);
150pub use self::GenericCounterReset as CounterReset;
151
152impl<I> CounterReset<I> {
153 #[inline]
155 pub fn new(counters: Vec<CounterPair<I>>) -> Self {
156 CounterReset(Counters(counters.into()))
157 }
158}
159
160impl<I> Deref for CounterReset<I> {
161 type Target = [CounterPair<I>];
162
163 #[inline]
164 fn deref(&self) -> &Self::Target {
165 &(self.0).0
166 }
167}
168
169#[derive(
173 Clone,
174 Debug,
175 Default,
176 MallocSizeOf,
177 PartialEq,
178 SpecifiedValueInfo,
179 ToComputedValue,
180 ToCss,
181 ToResolvedValue,
182 ToShmem,
183)]
184#[repr(transparent)]
185pub struct GenericCounters<I>(
186 #[css(field_bound)]
187 #[css(iterable, if_empty = "none")]
188 crate::OwnedSlice<GenericCounterPair<I>>,
189);
190pub use self::GenericCounters as Counters;
191
192#[inline]
193fn is_decimal(counter_type: &CounterStyle) -> bool {
194 *counter_type == CounterStyle::decimal()
195}
196
197#[derive(
199 Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
200)]
201#[repr(C)]
202pub struct GenericContentItems<Image> {
203 pub items: thin_vec::ThinVec<GenericContentItem<Image>>,
206 pub alt_start: usize,
209}
210
211impl<Image> ToCss for GenericContentItems<Image>
212where
213 Image: ToCss,
214{
215 fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
216 where
217 W: Write,
218 {
219 for (i, item) in self.items.iter().enumerate() {
220 if i == self.alt_start {
221 dest.write_str(" /")?;
222 }
223 if i != 0 {
224 dest.write_str(" ")?;
225 }
226 item.to_css(dest)?;
227 }
228 Ok(())
229 }
230}
231
232#[derive(
236 Clone,
237 Debug,
238 Eq,
239 MallocSizeOf,
240 PartialEq,
241 SpecifiedValueInfo,
242 ToComputedValue,
243 ToCss,
244 ToShmem,
245 ToTyped,
246)]
247#[repr(u8)]
248#[typed(todo_derive_fields)]
249pub enum GenericContent<Image> {
250 Normal,
252 None,
254 Items(GenericContentItems<Image>),
256}
257
258pub use self::GenericContent as Content;
259
260impl<Image> Content<Image> {
261 #[inline]
263 pub fn is_items(&self) -> bool {
264 matches!(*self, Self::Items(..))
265 }
266
267 #[inline]
269 pub fn normal() -> Self {
270 Content::Normal
271 }
272}
273
274#[derive(
276 Clone,
277 Debug,
278 Eq,
279 MallocSizeOf,
280 PartialEq,
281 ToComputedValue,
282 SpecifiedValueInfo,
283 ToCss,
284 ToResolvedValue,
285 ToShmem,
286)]
287#[repr(u8)]
288pub enum GenericContentItem<I> {
289 String(crate::OwnedStr),
291 #[css(comma, function)]
293 Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyle),
294 #[css(comma, function)]
296 Counters(
297 CustomIdent,
298 crate::OwnedStr,
299 #[css(skip_if = "is_decimal")] CounterStyle,
300 ),
301 OpenQuote,
303 CloseQuote,
305 NoOpenQuote,
307 NoCloseQuote,
309 #[cfg(feature = "gecko")]
311 MozAltContent,
312 #[cfg(feature = "gecko")]
316 MozLabelContent,
317 Attr(Attr),
319 Image(I),
321}
322
323pub use self::GenericContentItem as ContentItem;