1use crate::context::PropertyHandlerContext;
4use crate::declaration::{DeclarationBlock, DeclarationList};
5use crate::error::{ParserError, PrinterError};
6use crate::printer::Printer;
7use crate::properties::{Property, PropertyId};
8use crate::stylesheet::{ParserOptions, PrinterOptions};
9use crate::targets::{Browsers, Targets};
10use crate::vendor_prefix::VendorPrefix;
11use cssparser::*;
12
13#[cfg(feature = "into_owned")]
14pub use static_self::IntoOwned;
15
16pub trait Parse<'i>: Sized {
18 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>>;
20
21 fn parse_string(input: &'i str) -> Result<Self, ParseError<'i, ParserError<'i>>> {
25 let mut input = ParserInput::new(input);
26 let mut parser = Parser::new(&mut input);
27 let result = Self::parse(&mut parser)?;
28 parser.expect_exhausted()?;
29 Ok(result)
30 }
31}
32
33pub(crate) use lightningcss_derive::Parse;
34
35impl<'i, T: Parse<'i>> Parse<'i> for Option<T> {
36 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
37 Ok(input.try_parse(T::parse).ok())
38 }
39}
40
41impl<'i, T: Parse<'i>> Parse<'i> for Box<T> {
42 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
43 Ok(Box::new(T::parse(input)?))
44 }
45}
46
47pub trait ParseWithOptions<'i>: Sized {
49 fn parse_with_options<'t>(
51 input: &mut Parser<'i, 't>,
52 options: &ParserOptions<'_, 'i>,
53 ) -> Result<Self, ParseError<'i, ParserError<'i>>>;
54
55 fn parse_string_with_options(
57 input: &'i str,
58 options: ParserOptions<'_, 'i>,
59 ) -> Result<Self, ParseError<'i, ParserError<'i>>> {
60 let mut input = ParserInput::new(input);
61 let mut parser = Parser::new(&mut input);
62 Self::parse_with_options(&mut parser, &options)
63 }
64}
65
66impl<'i, T: Parse<'i>> ParseWithOptions<'i> for T {
67 #[inline]
68 fn parse_with_options<'t>(
69 input: &mut Parser<'i, 't>,
70 _options: &ParserOptions,
71 ) -> Result<Self, ParseError<'i, ParserError<'i>>> {
72 T::parse(input)
73 }
74}
75
76pub trait ToCss {
78 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
80 where
81 W: std::fmt::Write;
82
83 #[inline]
87 fn to_css_string(&self, options: PrinterOptions) -> Result<String, PrinterError> {
88 let mut s = String::new();
89 let mut printer = Printer::new(&mut s, options);
90 self.to_css(&mut printer)?;
91 Ok(s)
92 }
93}
94
95pub(crate) use lightningcss_derive::ToCss;
96
97impl<'a, T> ToCss for &'a T
98where
99 T: ToCss + ?Sized,
100{
101 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
102 where
103 W: std::fmt::Write,
104 {
105 (*self).to_css(dest)
106 }
107}
108
109impl<T: ToCss> ToCss for Box<T> {
110 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
111 where
112 W: std::fmt::Write,
113 {
114 (**self).to_css(dest)
115 }
116}
117
118impl<T: ToCss> ToCss for Option<T> {
119 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
120 where
121 W: std::fmt::Write,
122 {
123 if let Some(v) = self {
124 v.to_css(dest)?;
125 }
126 Ok(())
127 }
128}
129
130pub(crate) trait PropertyHandler<'i>: Sized {
131 fn handle_property(
132 &mut self,
133 property: &Property<'i>,
134 dest: &mut DeclarationList<'i>,
135 context: &mut PropertyHandlerContext<'i, '_>,
136 ) -> bool;
137 fn finalize(&mut self, dest: &mut DeclarationList<'i>, context: &mut PropertyHandlerContext<'i, '_>);
138}
139
140pub(crate) mod private {
141 pub trait TryAdd<T> {
142 fn try_add(&self, other: &T) -> Option<T>;
143 }
144
145 pub trait AddInternal {
146 fn add(self, other: Self) -> Self;
147 }
148}
149
150pub(crate) trait FromStandard<T>: Sized {
151 fn from_standard(val: &T) -> Option<Self>;
152}
153
154pub(crate) trait FallbackValues: Sized {
155 fn get_fallbacks(&mut self, targets: Targets) -> Vec<Self>;
156}
157
158pub(crate) trait Shorthand<'i>: Sized {
160 fn from_longhands(decls: &DeclarationBlock<'i>, vendor_prefix: VendorPrefix) -> Option<(Self, bool)>;
162
163 fn longhands(vendor_prefix: VendorPrefix) -> Vec<PropertyId<'static>>;
165
166 fn longhand(&self, property_id: &PropertyId) -> Option<Property<'i>>;
168
169 fn set_longhand(&mut self, property: &Property<'i>) -> Result<(), ()>;
171}
172
173pub trait Op {
175 fn op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Self;
177 fn op_to<T, F: FnOnce(f32, f32) -> T>(&self, rhs: &Self, op: F) -> T;
179}
180
181macro_rules! impl_op {
182 ($t: ty, $trait: ident $(:: $x: ident)*, $op: ident) => {
183 impl $trait$(::$x)* for $t {
184 type Output = $t;
185
186 fn $op(self, rhs: Self) -> Self::Output {
187 self.op(&rhs, $trait$(::$x)*::$op)
188 }
189 }
190 };
191}
192
193pub(crate) use impl_op;
194use smallvec::SmallVec;
195
196pub trait TryOp: Sized {
198 fn try_op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Option<Self>;
200 fn try_op_to<T, F: FnOnce(f32, f32) -> T>(&self, rhs: &Self, op: F) -> Option<T>;
202}
203
204impl<T: Op> TryOp for T {
205 fn try_op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Option<Self> {
206 Some(self.op(rhs, op))
207 }
208
209 fn try_op_to<U, F: FnOnce(f32, f32) -> U>(&self, rhs: &Self, op: F) -> Option<U> {
210 Some(self.op_to(rhs, op))
211 }
212}
213
214pub trait Map {
216 fn map<F: FnOnce(f32) -> f32>(&self, op: F) -> Self;
218}
219
220pub trait TryMap: Sized {
222 fn try_map<F: FnOnce(f32) -> f32>(&self, op: F) -> Option<Self>;
224}
225
226impl<T: Map> TryMap for T {
227 fn try_map<F: FnOnce(f32) -> f32>(&self, op: F) -> Option<Self> {
228 Some(self.map(op))
229 }
230}
231
232pub trait Sign {
234 fn sign(&self) -> f32;
236
237 fn is_sign_positive(&self) -> bool {
239 f32::is_sign_positive(self.sign())
240 }
241
242 fn is_sign_negative(&self) -> bool {
244 f32::is_sign_negative(self.sign())
245 }
246}
247
248pub trait TrySign {
250 fn try_sign(&self) -> Option<f32>;
252
253 fn is_sign_positive(&self) -> bool {
255 self.try_sign().map_or(false, |s| f32::is_sign_positive(s))
256 }
257
258 fn is_sign_negative(&self) -> bool {
260 self.try_sign().map_or(false, |s| f32::is_sign_negative(s))
261 }
262}
263
264impl<T: Sign> TrySign for T {
265 fn try_sign(&self) -> Option<f32> {
266 Some(self.sign())
267 }
268}
269
270pub trait Zero {
272 fn zero() -> Self;
274
275 fn is_zero(&self) -> bool;
277}
278
279pub trait IsCompatible {
281 fn is_compatible(&self, browsers: Browsers) -> bool;
283}
284
285impl<T: IsCompatible> IsCompatible for SmallVec<[T; 1]> {
286 fn is_compatible(&self, browsers: Browsers) -> bool {
287 self.iter().all(|v| v.is_compatible(browsers))
288 }
289}
290
291impl<T: IsCompatible> IsCompatible for Vec<T> {
292 fn is_compatible(&self, browsers: Browsers) -> bool {
293 self.iter().all(|v| v.is_compatible(browsers))
294 }
295}
296
297pub trait AtRuleParser<'i>: Sized {
309 type Prelude;
311
312 type AtRule;
314
315 type Error: 'i;
317
318 fn parse_prelude<'t>(
334 &mut self,
335 name: CowRcStr<'i>,
336 input: &mut Parser<'i, 't>,
337 options: &ParserOptions<'_, 'i>,
338 ) -> Result<Self::Prelude, ParseError<'i, Self::Error>> {
339 let _ = name;
340 let _ = input;
341 let _ = options;
342 Err(input.new_error(BasicParseErrorKind::AtRuleInvalid(name)))
343 }
344
345 fn rule_without_block(
354 &mut self,
355 prelude: Self::Prelude,
356 start: &ParserState,
357 options: &ParserOptions<'_, 'i>,
358 is_nested: bool,
359 ) -> Result<Self::AtRule, ()> {
360 let _ = prelude;
361 let _ = start;
362 let _ = options;
363 let _ = is_nested;
364 Err(())
365 }
366
367 fn parse_block<'t>(
378 &mut self,
379 prelude: Self::Prelude,
380 start: &ParserState,
381 input: &mut Parser<'i, 't>,
382 options: &ParserOptions<'_, 'i>,
383 is_nested: bool,
384 ) -> Result<Self::AtRule, ParseError<'i, Self::Error>> {
385 let _ = prelude;
386 let _ = start;
387 let _ = input;
388 let _ = options;
389 let _ = is_nested;
390 Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid))
391 }
392}