parcel_css/
traits.rs

1//! Traits for parsing and serializing CSS.
2
3use 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;
10use crate::vendor_prefix::VendorPrefix;
11use cssparser::*;
12
13/// Trait for things that can be parsed from CSS syntax.
14pub trait Parse<'i>: Sized {
15  /// Parse a value of this type using an existing parser.
16  fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>>;
17
18  /// Parse a value from a string.
19  ///
20  /// (This is a convenience wrapper for `parse` and probably should not be overridden.)
21  fn parse_string(input: &'i str) -> Result<Self, ParseError<'i, ParserError<'i>>> {
22    let mut input = ParserInput::new(input);
23    let mut parser = Parser::new(&mut input);
24    let result = Self::parse(&mut parser)?;
25    parser.expect_exhausted()?;
26    Ok(result)
27  }
28}
29
30pub(crate) trait ParseWithOptions<'i>: Sized {
31  fn parse_with_options<'t>(
32    input: &mut Parser<'i, 't>,
33    options: &ParserOptions,
34  ) -> Result<Self, ParseError<'i, ParserError<'i>>>;
35}
36
37impl<'i, T: Parse<'i>> ParseWithOptions<'i> for T {
38  #[inline]
39  fn parse_with_options<'t>(
40    input: &mut Parser<'i, 't>,
41    _options: &ParserOptions,
42  ) -> Result<Self, ParseError<'i, ParserError<'i>>> {
43    T::parse(input)
44  }
45}
46
47/// Trait for things the can serialize themselves in CSS syntax.
48pub trait ToCss {
49  /// Serialize `self` in CSS syntax, writing to `dest`.
50  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
51  where
52    W: std::fmt::Write;
53
54  /// Serialize `self` in CSS syntax and return a string.
55  ///
56  /// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
57  #[inline]
58  fn to_css_string(&self, options: PrinterOptions) -> Result<String, PrinterError> {
59    let mut s = String::new();
60    let mut printer = Printer::new(&mut s, options);
61    self.to_css(&mut printer)?;
62    Ok(s)
63  }
64}
65
66impl<'a, T> ToCss for &'a T
67where
68  T: ToCss + ?Sized,
69{
70  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
71  where
72    W: std::fmt::Write,
73  {
74    (*self).to_css(dest)
75  }
76}
77
78pub(crate) trait PropertyHandler<'i>: Sized {
79  fn handle_property(
80    &mut self,
81    property: &Property<'i>,
82    dest: &mut DeclarationList<'i>,
83    context: &mut PropertyHandlerContext<'i, '_>,
84  ) -> bool;
85  fn finalize(&mut self, dest: &mut DeclarationList<'i>, context: &mut PropertyHandlerContext<'i, '_>);
86}
87
88pub(crate) mod private {
89  pub trait TryAdd<T> {
90    fn try_add(&self, other: &T) -> Option<T>;
91  }
92
93  pub trait AddInternal {
94    fn add(self, other: Self) -> Self;
95  }
96}
97
98pub(crate) trait FromStandard<T>: Sized {
99  fn from_standard(val: &T) -> Option<Self>;
100}
101
102pub(crate) trait FallbackValues: Sized {
103  fn get_fallbacks(&mut self, targets: Browsers) -> Vec<Self>;
104}
105
106/// Trait for shorthand properties.
107pub(crate) trait Shorthand<'i>: Sized {
108  /// Returns a shorthand from the longhand properties defined in the given declaration block.
109  fn from_longhands(decls: &DeclarationBlock<'i>, vendor_prefix: VendorPrefix) -> Option<(Self, bool)>;
110
111  /// Returns a list of longhand property ids for this shorthand.
112  fn longhands(vendor_prefix: VendorPrefix) -> Vec<PropertyId<'static>>;
113
114  /// Returns a longhand property for this shorthand.
115  fn longhand(&self, property_id: &PropertyId) -> Option<Property<'i>>;
116
117  /// Updates this shorthand from a longhand property.
118  fn set_longhand(&mut self, property: &Property<'i>) -> Result<(), ()>;
119}
120
121/// A trait for values that support binary operations.
122pub trait Op {
123  /// Returns the result of the operation in the same type.
124  fn op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Self;
125  /// Returns the result of the operation in a different type.
126  fn op_to<T, F: FnOnce(f32, f32) -> T>(&self, rhs: &Self, op: F) -> T;
127}
128
129macro_rules! impl_op {
130  ($t: ty, $trait: ident $(:: $x: ident)*, $op: ident) => {
131    impl $trait$(::$x)* for $t {
132      type Output = $t;
133
134      fn $op(self, rhs: Self) -> Self::Output {
135        self.op(&rhs, $trait$(::$x)*::$op)
136      }
137    }
138  };
139}
140
141pub(crate) use impl_op;
142
143/// A trait for values that potentially support a binary operation (e.g. if they have the same unit).
144pub trait TryOp: Sized {
145  /// Returns the result of the operation in the same type, if possible.
146  fn try_op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Option<Self>;
147  /// Returns the result of the operation in a different type, if possible.
148  fn try_op_to<T, F: FnOnce(f32, f32) -> T>(&self, rhs: &Self, op: F) -> Option<T>;
149}
150
151impl<T: Op> TryOp for T {
152  fn try_op<F: FnOnce(f32, f32) -> f32>(&self, rhs: &Self, op: F) -> Option<Self> {
153    Some(self.op(rhs, op))
154  }
155
156  fn try_op_to<U, F: FnOnce(f32, f32) -> U>(&self, rhs: &Self, op: F) -> Option<U> {
157    Some(self.op_to(rhs, op))
158  }
159}
160
161/// A trait for values that can be mapped by applying a function.
162pub trait Map {
163  /// Returns the result of the operation.
164  fn map<F: FnOnce(f32) -> f32>(&self, op: F) -> Self;
165}
166
167/// A trait for values that can potentially be mapped.
168pub trait TryMap: Sized {
169  /// Returns the result of the operation, if possible.
170  fn try_map<F: FnOnce(f32) -> f32>(&self, op: F) -> Option<Self>;
171}
172
173impl<T: Map> TryMap for T {
174  fn try_map<F: FnOnce(f32) -> f32>(&self, op: F) -> Option<Self> {
175    Some(self.map(op))
176  }
177}
178
179/// A trait for values that can return a sign.
180pub trait Sign {
181  /// Returns the sign of the value.
182  fn sign(&self) -> f32;
183
184  /// Returns whether the value is positive.
185  fn is_sign_positive(&self) -> bool {
186    f32::is_sign_positive(self.sign())
187  }
188
189  /// Returns whether the value is negative.
190  fn is_sign_negative(&self) -> bool {
191    f32::is_sign_negative(self.sign())
192  }
193}
194
195/// A trait for values that can potentially return a sign.
196pub trait TrySign {
197  /// Returns the sign of the value, if possible.
198  fn try_sign(&self) -> Option<f32>;
199
200  /// Returns whether the value is positive. If not possible, returns false.
201  fn is_sign_positive(&self) -> bool {
202    self.try_sign().map_or(false, |s| f32::is_sign_positive(s))
203  }
204
205  /// Returns whether the value is negative. If not possible, returns false.
206  fn is_sign_negative(&self) -> bool {
207    self.try_sign().map_or(false, |s| f32::is_sign_negative(s))
208  }
209}
210
211impl<T: Sign> TrySign for T {
212  fn try_sign(&self) -> Option<f32> {
213    Some(self.sign())
214  }
215}
216
217/// A trait for values that can be zero.
218pub trait Zero {
219  /// Returns the zero value.
220  fn zero() -> Self;
221
222  /// Returns whether the value is zero.
223  fn is_zero(&self) -> bool;
224}