style/values/generics/
mod.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Generic types that share their serialization implementations
6//! for both specified and computed values.
7
8use crate::derives::*;
9use crate::Zero;
10use std::ops::Add;
11
12pub mod animation;
13pub mod background;
14pub mod basic_shape;
15pub mod border;
16#[path = "box.rs"]
17pub mod box_;
18pub mod calc;
19pub mod color;
20pub mod column;
21pub mod counters;
22pub mod easing;
23pub mod effects;
24pub mod flex;
25pub mod font;
26pub mod grid;
27pub mod image;
28pub mod length;
29pub mod motion;
30pub mod page;
31pub mod position;
32pub mod ratio;
33pub mod rect;
34pub mod size;
35pub mod svg;
36pub mod text;
37pub mod transform;
38pub mod ui;
39pub mod url;
40
41/// A wrapper of Non-negative values.
42#[derive(
43    Animate,
44    Clone,
45    ComputeSquaredDistance,
46    Copy,
47    Debug,
48    Deserialize,
49    Hash,
50    MallocSizeOf,
51    PartialEq,
52    PartialOrd,
53    SpecifiedValueInfo,
54    Serialize,
55    ToAnimatedZero,
56    ToComputedValue,
57    ToCss,
58    ToResolvedValue,
59    ToShmem,
60    ToTyped,
61)]
62#[repr(transparent)]
63#[typed_value(derive_fields)]
64pub struct NonNegative<T>(pub T);
65
66/// A trait to clamp a negative value to another.
67pub trait ClampToNonNegative {
68    /// Clamps the value to be non-negative after an animation.
69    fn clamp_to_non_negative(self) -> Self;
70}
71
72impl ClampToNonNegative for f32 {
73    fn clamp_to_non_negative(self) -> Self {
74        self.max(0.)
75    }
76}
77
78impl<T: Add<Output = T>> Add<NonNegative<T>> for NonNegative<T> {
79    type Output = Self;
80
81    fn add(self, other: Self) -> Self {
82        NonNegative(self.0 + other.0)
83    }
84}
85
86impl<T: Zero> Zero for NonNegative<T> {
87    fn is_zero(&self) -> bool {
88        self.0.is_zero()
89    }
90
91    fn zero() -> Self {
92        NonNegative(T::zero())
93    }
94}
95
96/// A wrapper of greater-than-or-equal-to-one values.
97#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
98#[derive(
99    Animate,
100    Clone,
101    ComputeSquaredDistance,
102    Copy,
103    Debug,
104    MallocSizeOf,
105    PartialEq,
106    PartialOrd,
107    SpecifiedValueInfo,
108    ToAnimatedZero,
109    ToComputedValue,
110    ToCss,
111    ToResolvedValue,
112    ToShmem,
113)]
114#[repr(transparent)]
115pub struct GreaterThanOrEqualToOne<T>(pub T);
116
117/// A wrapper of values between zero and one.
118#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
119#[derive(
120    Animate,
121    Clone,
122    ComputeSquaredDistance,
123    Copy,
124    Debug,
125    Hash,
126    MallocSizeOf,
127    PartialEq,
128    PartialOrd,
129    SpecifiedValueInfo,
130    ToAnimatedZero,
131    ToComputedValue,
132    ToCss,
133    ToResolvedValue,
134    ToShmem,
135)]
136#[repr(transparent)]
137pub struct ZeroToOne<T>(pub T);
138
139/// A clip rect for clip and image-region
140#[allow(missing_docs)]
141#[derive(
142    Clone,
143    ComputeSquaredDistance,
144    Copy,
145    Debug,
146    MallocSizeOf,
147    PartialEq,
148    SpecifiedValueInfo,
149    ToAnimatedValue,
150    ToAnimatedZero,
151    ToComputedValue,
152    ToCss,
153    ToResolvedValue,
154    ToShmem,
155)]
156#[css(function = "rect", comma)]
157#[repr(C)]
158pub struct GenericClipRect<LengthOrAuto> {
159    pub top: LengthOrAuto,
160    pub right: LengthOrAuto,
161    pub bottom: LengthOrAuto,
162    pub left: LengthOrAuto,
163}
164
165pub use self::GenericClipRect as ClipRect;
166
167/// Either a clip-rect or `auto`.
168#[allow(missing_docs)]
169#[derive(
170    Animate,
171    Clone,
172    ComputeSquaredDistance,
173    Copy,
174    Debug,
175    MallocSizeOf,
176    Parse,
177    PartialEq,
178    SpecifiedValueInfo,
179    ToAnimatedValue,
180    ToAnimatedZero,
181    ToComputedValue,
182    ToCss,
183    ToResolvedValue,
184    ToShmem,
185    ToTyped,
186)]
187#[repr(C, u8)]
188pub enum GenericClipRectOrAuto<R> {
189    Auto,
190    Rect(R),
191}
192
193pub use self::GenericClipRectOrAuto as ClipRectOrAuto;
194
195impl<L> ClipRectOrAuto<L> {
196    /// Returns the `auto` value.
197    #[inline]
198    pub fn auto() -> Self {
199        ClipRectOrAuto::Auto
200    }
201
202    /// Returns whether this value is the `auto` value.
203    #[inline]
204    pub fn is_auto(&self) -> bool {
205        matches!(*self, ClipRectOrAuto::Auto)
206    }
207}
208
209pub use page::PageSize;
210
211pub use text::NumberOrAuto;
212
213/// An optional value, much like `Option<T>`, but with a defined struct layout
214/// to be able to use it from C++ as well.
215///
216/// Note that this is relatively inefficient, struct-layout-wise, as you have
217/// one byte for the tag, but padding to the alignment of T. If you have
218/// multiple optional values and care about struct compactness, you might be
219/// better off "coalescing" the combinations into a parent enum. But that
220/// shouldn't matter for most use cases.
221#[allow(missing_docs)]
222#[derive(
223    Animate,
224    Clone,
225    ComputeSquaredDistance,
226    Copy,
227    Debug,
228    MallocSizeOf,
229    Parse,
230    PartialEq,
231    SpecifiedValueInfo,
232    ToAnimatedValue,
233    ToAnimatedZero,
234    ToComputedValue,
235    ToCss,
236    ToResolvedValue,
237    ToShmem,
238    Serialize,
239    Deserialize,
240)]
241#[repr(C, u8)]
242pub enum Optional<T> {
243    #[css(skip)]
244    None,
245    Some(T),
246}
247
248impl<T> Optional<T> {
249    /// Returns whether this value is present.
250    pub fn is_some(&self) -> bool {
251        matches!(*self, Self::Some(..))
252    }
253
254    /// Returns whether this value is not present.
255    pub fn is_none(&self) -> bool {
256        matches!(*self, Self::None)
257    }
258
259    /// Turns this Optional<> into a regular rust Option<>.
260    pub fn into_rust(self) -> Option<T> {
261        match self {
262            Self::Some(v) => Some(v),
263            Self::None => None,
264        }
265    }
266
267    /// Return a reference to the containing value, if any, as a plain rust
268    /// Option<>.
269    pub fn as_ref(&self) -> Option<&T> {
270        match *self {
271            Self::Some(ref v) => Some(v),
272            Self::None => None,
273        }
274    }
275
276    /// Return a mutable reference to the containing value, if any, as a plain
277    /// rust Option<>.
278    pub fn as_mut(&mut self) -> Option<&mut T> {
279        match *self {
280            Self::Some(ref mut v) => Some(v),
281            Self::None => None,
282        }
283    }
284
285    /// See Option::map.
286    pub fn map<U>(self, map: impl FnOnce(T) -> U) -> Optional<U> {
287        match self {
288            Self::Some(v) => Optional::Some(map(v)),
289            Self::None => Optional::None,
290        }
291    }
292}
293
294impl<T> From<Option<T>> for Optional<T> {
295    fn from(rust: Option<T>) -> Self {
296        match rust {
297            Some(t) => Self::Some(t),
298            None => Self::None,
299        }
300    }
301}