style/values/specified/
list.rs1use crate::counter_style::{CounterStyle, CounterStyleParsingFlags};
8use crate::derives::*;
9use crate::parser::{Parse, ParserContext};
10use cssparser::{Parser, Token};
11use style_traits::{ParseError, StyleParseErrorKind};
12
13#[derive(
15 Clone,
16 Debug,
17 Eq,
18 MallocSizeOf,
19 PartialEq,
20 SpecifiedValueInfo,
21 ToComputedValue,
22 ToCss,
23 ToResolvedValue,
24 ToShmem,
25 ToTyped,
26)]
27#[repr(transparent)]
28pub struct ListStyleType(pub CounterStyle);
29
30impl ListStyleType {
31 #[inline]
33 pub fn disc() -> Self {
34 Self(CounterStyle::disc())
35 }
36
37 #[inline]
39 pub fn none() -> Self {
40 Self(CounterStyle::None)
41 }
42
43 #[cfg(feature = "gecko")]
48 pub fn from_gecko_keyword(value: u32) -> Self {
49 use crate::gecko_bindings::structs;
50 use crate::values::CustomIdent;
51 let v8 = value as u8;
52 if v8 == structs::ListStyle_None {
53 return Self::none();
54 }
55
56 Self(CounterStyle::Name(CustomIdent(match v8 {
57 structs::ListStyle_Disc => atom!("disc"),
58 structs::ListStyle_Circle => atom!("circle"),
59 structs::ListStyle_Square => atom!("square"),
60 structs::ListStyle_Decimal => atom!("decimal"),
61 structs::ListStyle_LowerRoman => atom!("lower-roman"),
62 structs::ListStyle_UpperRoman => atom!("upper-roman"),
63 structs::ListStyle_LowerAlpha => atom!("lower-alpha"),
64 structs::ListStyle_UpperAlpha => atom!("upper-alpha"),
65 _ => unreachable!("Unknown counter style keyword value"),
66 })))
67 }
68
69 #[inline]
71 pub fn is_bullet(&self) -> bool {
72 self.0.is_bullet()
73 }
74}
75
76impl Parse for ListStyleType {
77 fn parse<'i, 't>(
78 context: &ParserContext,
79 input: &mut Parser<'i, 't>,
80 ) -> Result<Self, ParseError<'i>> {
81 let flags = CounterStyleParsingFlags::ALLOW_NONE | CounterStyleParsingFlags::ALLOW_STRING;
82 Ok(Self(CounterStyle::parse(context, input, flags)?))
83 }
84}
85
86#[derive(
88 Clone,
89 Debug,
90 MallocSizeOf,
91 PartialEq,
92 SpecifiedValueInfo,
93 ToComputedValue,
94 ToCss,
95 ToResolvedValue,
96 ToShmem,
97)]
98#[repr(C)]
99pub struct QuotePair {
100 pub opening: crate::OwnedStr,
102
103 pub closing: crate::OwnedStr,
105}
106
107#[derive(
109 Clone,
110 Debug,
111 Default,
112 MallocSizeOf,
113 PartialEq,
114 SpecifiedValueInfo,
115 ToComputedValue,
116 ToCss,
117 ToResolvedValue,
118 ToShmem,
119)]
120#[repr(transparent)]
121pub struct QuoteList(
122 #[css(iterable, if_empty = "none")]
123 #[ignore_malloc_size_of = "Arc"]
124 pub crate::ArcSlice<QuotePair>,
125);
126
127#[derive(
130 Clone,
131 Debug,
132 MallocSizeOf,
133 PartialEq,
134 SpecifiedValueInfo,
135 ToComputedValue,
136 ToCss,
137 ToResolvedValue,
138 ToShmem,
139 ToTyped,
140)]
141#[repr(C)]
142pub enum Quotes {
143 QuoteList(QuoteList),
145 Auto,
147}
148
149impl Parse for Quotes {
150 fn parse<'i, 't>(
151 _: &ParserContext,
152 input: &mut Parser<'i, 't>,
153 ) -> Result<Quotes, ParseError<'i>> {
154 if input
155 .try_parse(|input| input.expect_ident_matching("auto"))
156 .is_ok()
157 {
158 return Ok(Quotes::Auto);
159 }
160
161 if input
162 .try_parse(|input| input.expect_ident_matching("none"))
163 .is_ok()
164 {
165 return Ok(Quotes::QuoteList(QuoteList::default()));
166 }
167
168 let mut quotes = Vec::new();
169 loop {
170 let location = input.current_source_location();
171 let opening = match input.next() {
172 Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into(),
173 Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
174 Err(_) => break,
175 };
176
177 let closing = input.expect_string()?.as_ref().to_owned().into();
178 quotes.push(QuotePair { opening, closing });
179 }
180
181 if !quotes.is_empty() {
182 Ok(Quotes::QuoteList(QuoteList(crate::ArcSlice::from_iter(
183 quotes.into_iter(),
184 ))))
185 } else {
186 Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
187 }
188 }
189}