1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
//! Traits for parsing and serializing CSS.

use crate::context::PropertyHandlerContext;
use crate::declaration::{DeclarationBlock, DeclarationList};
use crate::error::{ParserError, PrinterError};
use crate::printer::Printer;
use crate::properties::{Property, PropertyId};
use crate::stylesheet::{ParserOptions, PrinterOptions};
use crate::targets::Browsers;
use crate::vendor_prefix::VendorPrefix;
use cssparser::*;

/// Trait for things that can be parsed from CSS syntax.
pub trait Parse<'i>: Sized {
  /// Parse a value of this type using an existing parser.
  fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>>;

  /// Parse a value from a string.
  ///
  /// (This is a convenience wrapper for `parse` and probably should not be overridden.)
  fn parse_string(input: &'i str) -> Result<Self, ParseError<'i, ParserError<'i>>> {
    let mut input = ParserInput::new(input);
    let mut parser = Parser::new(&mut input);
    let result = Self::parse(&mut parser)?;
    parser.expect_exhausted()?;
    Ok(result)
  }
}

/// Trait for things that can be parsed from CSS syntax and require ParserOptions.
pub trait ParseWithOptions<'i>: Sized {
  /// Parse a value of this type with the given options.
  fn parse_with_options<'t>(
    input: &mut Parser<'i, 't>,
    options: &ParserOptions<'_, 'i>,
  ) -> Result<Self, ParseError<'i, ParserError<'i>>>;

  /// Parse a value from a string with the given options.
  fn parse_string_with_options(
    input: &'i str,
    options: ParserOptions<'_, 'i>,
  ) -> Result<Self, ParseError<'i, ParserError<'i>>> {
    let mut input = ParserInput::new(input);
    let mut parser = Parser::new(&mut input);
    Self::parse_with_options(&mut parser, &options)
  }
}

impl<'i, T: Parse<'i>> ParseWithOptions<'i> for T {
  #[inline]
  fn parse_with_options<'t>(
    input: &mut Parser<'i, 't>,
    _options: &ParserOptions,
  ) -> Result<Self, ParseError<'i, ParserError<'i>>> {
    T::parse(input)
  }
}

/// Trait for things the can serialize themselves in CSS syntax.
pub trait ToCss {
  /// Serialize `self` in CSS syntax, writing to `dest`.
  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
  where
    W: std::fmt::Write;

  /// Serialize `self` in CSS syntax and return a string.
  ///
  /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
  #[inline]
  fn to_css_string(&self, options: PrinterOptions) -> Result<String, PrinterError> {
    let mut s = String::new();
    let mut printer = Printer::new(&mut s, options);
    self.to_css(&mut printer)?;
    Ok(s)
  }
}

impl<'a, T> ToCss for &'a T
where
  T: ToCss + ?Sized,
{
  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
  where
    W: std::fmt::Write,
  {
    (*self).to_css(dest)
  }
}

pub(crate) trait PropertyHandler<'i>: Sized {
  fn handle_property(
    &mut self,
    property: &Property<'i>,
    dest: &mut DeclarationList<'i>,
    context: &mut PropertyHandlerContext<'i, '_>,
  ) -> bool;
  fn finalize(&mut self, dest: &mut DeclarationList<'i>, context: &mut PropertyHandlerContext<'i, '_>);
}

pub(crate) mod private {
  pub trait TryAdd<T> {
    fn try_add(&self, other: &T) -> Option<T>;
  }

  pub trait AddInternal {
    fn add(self, other: Self) -> Self;
  }
}

pub(crate) trait FromStandard<T>: Sized {
  fn from_standard(val: &T) -> Option<Self>;
}

pub(crate) trait FallbackValues: Sized {
  fn get_fallbacks(&mut self, targets: Browsers) -> Vec<Self>;
}

/// Trait for shorthand properties.
pub(crate) trait Shorthand<'i>: Sized {
  /// Returns a shorthand from the longhand properties defined in the given declaration block.
  fn from_longhands(decls: &DeclarationBlock<'i>, vendor_prefix: VendorPrefix) -> Option<(Self, bool)>;

  /// Returns a list of longhand property ids for this shorthand.
  fn longhands(vendor_prefix: VendorPrefix) -> Vec<PropertyId<'static>>;

  /// Returns a longhand property for this shorthand.
  fn longhand(&self, property_id: &PropertyId) -> Option<Property<'i>>;

  /// Updates this shorthand from a longhand property.
  fn set_longhand(&mut self, property: &Property<'i>) -> Result<(), ()>;
}

/// A trait for values that support binary operations.
pub trait Op {
  /// Returns the result of the operation in the same type.
  fn op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Self;
  /// Returns the result of the operation in a different type.
  fn op_to<T, F: FnOnce(f32, f32) -> T>(&self, rhs: &Self, op: F) -> T;
}

macro_rules! impl_op {
  ($t: ty, $trait: ident $(:: $x: ident)*, $op: ident) => {
    impl $trait$(::$x)* for $t {
      type Output = $t;

      fn $op(self, rhs: Self) -> Self::Output {
        self.op(&rhs, $trait$(::$x)*::$op)
      }
    }
  };
}

pub(crate) use impl_op;

/// A trait for values that potentially support a binary operation (e.g. if they have the same unit).
pub trait TryOp: Sized {
  /// Returns the result of the operation in the same type, if possible.
  fn try_op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Option<Self>;
  /// Returns the result of the operation in a different type, if possible.
  fn try_op_to<T, F: FnOnce(f32, f32) -> T>(&self, rhs: &Self, op: F) -> Option<T>;
}

impl<T: Op> TryOp for T {
  fn try_op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Option<Self> {
    Some(self.op(rhs, op))
  }

  fn try_op_to<U, F: FnOnce(f32, f32) -> U>(&self, rhs: &Self, op: F) -> Option<U> {
    Some(self.op_to(rhs, op))
  }
}

/// A trait for values that can be mapped by applying a function.
pub trait Map {
  /// Returns the result of the operation.
  fn map<F: FnOnce(f32) -> f32>(&self, op: F) -> Self;
}

/// A trait for values that can potentially be mapped.
pub trait TryMap: Sized {
  /// Returns the result of the operation, if possible.
  fn try_map<F: FnOnce(f32) -> f32>(&self, op: F) -> Option<Self>;
}

impl<T: Map> TryMap for T {
  fn try_map<F: FnOnce(f32) -> f32>(&self, op: F) -> Option<Self> {
    Some(self.map(op))
  }
}

/// A trait for values that can return a sign.
pub trait Sign {
  /// Returns the sign of the value.
  fn sign(&self) -> f32;

  /// Returns whether the value is positive.
  fn is_sign_positive(&self) -> bool {
    f32::is_sign_positive(self.sign())
  }

  /// Returns whether the value is negative.
  fn is_sign_negative(&self) -> bool {
    f32::is_sign_negative(self.sign())
  }
}

/// A trait for values that can potentially return a sign.
pub trait TrySign {
  /// Returns the sign of the value, if possible.
  fn try_sign(&self) -> Option<f32>;

  /// Returns whether the value is positive. If not possible, returns false.
  fn is_sign_positive(&self) -> bool {
    self.try_sign().map_or(false, |s| f32::is_sign_positive(s))
  }

  /// Returns whether the value is negative. If not possible, returns false.
  fn is_sign_negative(&self) -> bool {
    self.try_sign().map_or(false, |s| f32::is_sign_negative(s))
  }
}

impl<T: Sign> TrySign for T {
  fn try_sign(&self) -> Option<f32> {
    Some(self.sign())
  }
}

/// A trait for values that can be zero.
pub trait Zero {
  /// Returns the zero value.
  fn zero() -> Self;

  /// Returns whether the value is zero.
  fn is_zero(&self) -> bool;
}

/// A trait to provide parsing of custom at-rules.
///
/// For example, there could be different implementations for top-level at-rules
/// (`@media`, `@font-face`, …)
/// and for page-margin rules inside `@page`.
///
/// Default implementations that reject all at-rules are provided,
/// so that `impl AtRuleParser<(), ()> for ... {}` can be used
/// for using `DeclarationListParser` to parse a declarations list with only qualified rules.
///
/// Note: this trait is copied from cssparser and modified to provide parser options.
pub trait AtRuleParser<'i>: Sized {
  /// The intermediate representation of prelude of an at-rule.
  type Prelude;

  /// The finished representation of an at-rule.
  type AtRule;

  /// The error type that is included in the ParseError value that can be returned.
  type Error: 'i;

  /// Parse the prelude of an at-rule with the given `name`.
  ///
  /// Return the representation of the prelude and the type of at-rule,
  /// or `Err(())` to ignore the entire at-rule as invalid.
  ///
  /// The prelude is the part after the at-keyword
  /// and before the `;` semicolon or `{ /* ... */ }` block.
  ///
  /// At-rule name matching should be case-insensitive in the ASCII range.
  /// This can be done with `std::ascii::Ascii::eq_ignore_ascii_case`,
  /// or with the `match_ignore_ascii_case!` macro.
  ///
  /// The given `input` is a "delimited" parser
  /// that ends wherever the prelude should end.
  /// (Before the next semicolon, the next `{`, or the end of the current block.)
  fn parse_prelude<'t>(
    &mut self,
    name: CowRcStr<'i>,
    input: &mut Parser<'i, 't>,
    options: &ParserOptions<'_, 'i>,
  ) -> Result<Self::Prelude, ParseError<'i, Self::Error>> {
    let _ = name;
    let _ = input;
    let _ = options;
    Err(input.new_error(BasicParseErrorKind::AtRuleInvalid(name)))
  }

  /// End an at-rule which doesn't have block. Return the finished
  /// representation of the at-rule.
  ///
  /// The location passed in is source location of the start of the prelude.
  ///
  /// This is only called when either the `;` semicolon indeed follows the prelude,
  /// or parser is at the end of the input.
  fn rule_without_block(
    &mut self,
    prelude: Self::Prelude,
    start: &ParserState,
    options: &ParserOptions<'_, 'i>,
  ) -> Result<Self::AtRule, ()> {
    let _ = prelude;
    let _ = start;
    let _ = options;
    Err(())
  }

  /// Parse the content of a `{ /* ... */ }` block for the body of the at-rule.
  ///
  /// The location passed in is source location of the start of the prelude.
  ///
  /// Return the finished representation of the at-rule
  /// as returned by `RuleListParser::next` or `DeclarationListParser::next`,
  /// or `Err(())` to ignore the entire at-rule as invalid.
  ///
  /// This is only called when a block was found following the prelude.
  fn parse_block<'t>(
    &mut self,
    prelude: Self::Prelude,
    start: &ParserState,
    input: &mut Parser<'i, 't>,
    options: &ParserOptions<'_, 'i>,
  ) -> Result<Self::AtRule, ParseError<'i, Self::Error>> {
    let _ = prelude;
    let _ = start;
    let _ = input;
    let _ = options;
    Err(input.new_error(BasicParseErrorKind::AtRuleBodyInvalid))
  }
}