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