style/values/generics/
counters.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Generic types for counters-related CSS values.
6
7use 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/// A name / value pair for counters.
16#[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    /// The name of the counter.
29    pub name: CustomIdent,
30    /// The value of the counter / increment / etc.
31    pub value: Integer,
32    /// If true, then this represents `reversed(name)`.
33    /// NOTE: It can only be true on `counter-reset` values.
34    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/// A generic value for the `counter-increment` property.
62#[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)]
76pub struct GenericCounterIncrement<I>(#[css(field_bound)] pub GenericCounters<I>);
77pub use self::GenericCounterIncrement as CounterIncrement;
78
79impl<I> CounterIncrement<I> {
80    /// Returns a new value for `counter-increment`.
81    #[inline]
82    pub fn new(counters: Vec<CounterPair<I>>) -> Self {
83        CounterIncrement(Counters(counters.into()))
84    }
85}
86
87impl<I> Deref for CounterIncrement<I> {
88    type Target = [CounterPair<I>];
89
90    #[inline]
91    fn deref(&self) -> &Self::Target {
92        &(self.0).0
93    }
94}
95
96/// A generic value for the `counter-set` property.
97#[derive(
98    Clone,
99    Debug,
100    Default,
101    MallocSizeOf,
102    PartialEq,
103    SpecifiedValueInfo,
104    ToComputedValue,
105    ToCss,
106    ToResolvedValue,
107    ToShmem,
108    ToTyped,
109)]
110#[repr(transparent)]
111pub struct GenericCounterSet<I>(#[css(field_bound)] pub GenericCounters<I>);
112pub use self::GenericCounterSet as CounterSet;
113
114impl<I> CounterSet<I> {
115    /// Returns a new value for `counter-set`.
116    #[inline]
117    pub fn new(counters: Vec<CounterPair<I>>) -> Self {
118        CounterSet(Counters(counters.into()))
119    }
120}
121
122impl<I> Deref for CounterSet<I> {
123    type Target = [CounterPair<I>];
124
125    #[inline]
126    fn deref(&self) -> &Self::Target {
127        &(self.0).0
128    }
129}
130
131/// A generic value for the `counter-reset` property.
132#[derive(
133    Clone,
134    Debug,
135    Default,
136    MallocSizeOf,
137    PartialEq,
138    SpecifiedValueInfo,
139    ToComputedValue,
140    ToCss,
141    ToResolvedValue,
142    ToShmem,
143    ToTyped,
144)]
145#[repr(transparent)]
146pub struct GenericCounterReset<I>(#[css(field_bound)] pub GenericCounters<I>);
147pub use self::GenericCounterReset as CounterReset;
148
149impl<I> CounterReset<I> {
150    /// Returns a new value for `counter-reset`.
151    #[inline]
152    pub fn new(counters: Vec<CounterPair<I>>) -> Self {
153        CounterReset(Counters(counters.into()))
154    }
155}
156
157impl<I> Deref for CounterReset<I> {
158    type Target = [CounterPair<I>];
159
160    #[inline]
161    fn deref(&self) -> &Self::Target {
162        &(self.0).0
163    }
164}
165
166/// A generic value for lists of counters.
167///
168/// Keyword `none` is represented by an empty vector.
169#[derive(
170    Clone,
171    Debug,
172    Default,
173    MallocSizeOf,
174    PartialEq,
175    SpecifiedValueInfo,
176    ToComputedValue,
177    ToCss,
178    ToResolvedValue,
179    ToShmem,
180)]
181#[repr(transparent)]
182pub struct GenericCounters<I>(
183    #[css(field_bound)]
184    #[css(iterable, if_empty = "none")]
185    crate::OwnedSlice<GenericCounterPair<I>>,
186);
187pub use self::GenericCounters as Counters;
188
189
190#[inline]
191fn is_decimal(counter_type: &CounterStyle) -> bool {
192    *counter_type == CounterStyle::decimal()
193}
194
195/// The non-normal, non-none values of the content property.
196#[derive(
197    Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
198)]
199#[repr(C)]
200pub struct GenericContentItems<Image> {
201    /// The actual content items. Note that, past the alt marker, only some subset (strings,
202    /// attr(), counter())
203    pub items: thin_vec::ThinVec<GenericContentItem<Image>>,
204    /// The index at which alt text starts, always non-zero. If equal to items.len(), no alt text
205    /// exists.
206    pub alt_start: usize,
207}
208
209impl<Image> ToCss for GenericContentItems<Image>
210where
211    Image: ToCss,
212{
213    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
214    where
215        W: Write,
216    {
217        for (i, item) in self.items.iter().enumerate() {
218            if i == self.alt_start {
219                dest.write_str(" /")?;
220            }
221            if i != 0 {
222                dest.write_str(" ")?;
223            }
224            item.to_css(dest)?;
225        }
226        Ok(())
227    }
228}
229
230/// The specified value for the `content` property.
231///
232/// https://drafts.csswg.org/css-content/#propdef-content
233#[derive(
234    Clone,
235    Debug,
236    Eq,
237    MallocSizeOf,
238    PartialEq,
239    SpecifiedValueInfo,
240    ToComputedValue,
241    ToCss,
242    ToShmem,
243    ToTyped,
244)]
245#[repr(u8)]
246pub enum GenericContent<Image> {
247    /// `normal` reserved keyword.
248    Normal,
249    /// `none` reserved keyword.
250    None,
251    /// Content items.
252    Items(GenericContentItems<Image>),
253}
254
255pub use self::GenericContent as Content;
256
257impl<Image> Content<Image> {
258    /// Whether `self` represents list of items.
259    #[inline]
260    pub fn is_items(&self) -> bool {
261        matches!(*self, Self::Items(..))
262    }
263
264    /// Set `content` property to `normal`.
265    #[inline]
266    pub fn normal() -> Self {
267        Content::Normal
268    }
269}
270
271/// Items for the `content` property.
272#[derive(
273    Clone,
274    Debug,
275    Eq,
276    MallocSizeOf,
277    PartialEq,
278    ToComputedValue,
279    SpecifiedValueInfo,
280    ToCss,
281    ToResolvedValue,
282    ToShmem,
283)]
284#[repr(u8)]
285pub enum GenericContentItem<I> {
286    /// Literal string content.
287    String(crate::OwnedStr),
288    /// `counter(name, style)`.
289    #[css(comma, function)]
290    Counter(CustomIdent, #[css(skip_if = "is_decimal")] CounterStyle),
291    /// `counters(name, separator, style)`.
292    #[css(comma, function)]
293    Counters(
294        CustomIdent,
295        crate::OwnedStr,
296        #[css(skip_if = "is_decimal")] CounterStyle,
297    ),
298    /// `open-quote`.
299    OpenQuote,
300    /// `close-quote`.
301    CloseQuote,
302    /// `no-open-quote`.
303    NoOpenQuote,
304    /// `no-close-quote`.
305    NoCloseQuote,
306    /// `-moz-alt-content`.
307    #[cfg(feature = "gecko")]
308    MozAltContent,
309    /// `-moz-label-content`.
310    /// This is needed to make `accesskey` work for XUL labels. It's basically
311    /// attr(value) otherwise.
312    #[cfg(feature = "gecko")]
313    MozLabelContent,
314    /// `attr([namespace? `|`]? ident)`
315    Attr(Attr),
316    /// image-set(url) | url(url)
317    Image(I),
318}
319
320pub use self::GenericContentItem as ContentItem;