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