Skip to main content

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)]
63pub struct NonNegative<T>(pub T);
64
65/// A trait to clamp a negative value to another.
66pub trait ClampToNonNegative {
67    /// Clamps the value to be non-negative after an animation.
68    fn clamp_to_non_negative(self) -> Self;
69}
70
71impl ClampToNonNegative for f32 {
72    fn clamp_to_non_negative(self) -> Self {
73        self.max(0.)
74    }
75}
76
77impl<T: Add<Output = T>> Add<NonNegative<T>> for NonNegative<T> {
78    type Output = Self;
79
80    fn add(self, other: Self) -> Self {
81        NonNegative(self.0 + other.0)
82    }
83}
84
85impl<T: Zero> Zero for NonNegative<T> {
86    fn is_zero(&self) -> bool {
87        self.0.is_zero()
88    }
89
90    fn zero() -> Self {
91        NonNegative(T::zero())
92    }
93}
94
95/// A wrapper of greater-than-or-equal-to-one values.
96#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
97#[derive(
98    Animate,
99    Clone,
100    ComputeSquaredDistance,
101    Copy,
102    Debug,
103    MallocSizeOf,
104    PartialEq,
105    PartialOrd,
106    SpecifiedValueInfo,
107    ToAnimatedZero,
108    ToComputedValue,
109    ToCss,
110    ToResolvedValue,
111    ToShmem,
112)]
113#[repr(transparent)]
114pub struct GreaterThanOrEqualToOne<T>(pub T);
115
116/// A wrapper of values between zero and one.
117#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
118#[derive(
119    Animate,
120    Clone,
121    ComputeSquaredDistance,
122    Copy,
123    Debug,
124    Hash,
125    MallocSizeOf,
126    PartialEq,
127    PartialOrd,
128    SpecifiedValueInfo,
129    ToAnimatedZero,
130    ToComputedValue,
131    ToCss,
132    ToResolvedValue,
133    ToShmem,
134)]
135#[repr(transparent)]
136pub struct ZeroToOne<T>(pub T);
137
138/// A clip rect for clip and image-region
139#[allow(missing_docs)]
140#[derive(
141    Clone,
142    ComputeSquaredDistance,
143    Copy,
144    Debug,
145    MallocSizeOf,
146    PartialEq,
147    SpecifiedValueInfo,
148    ToAnimatedValue,
149    ToAnimatedZero,
150    ToComputedValue,
151    ToCss,
152    ToResolvedValue,
153    ToShmem,
154)]
155#[css(function = "rect", comma)]
156#[repr(C)]
157pub struct GenericClipRect<LengthOrAuto> {
158    pub top: LengthOrAuto,
159    pub right: LengthOrAuto,
160    pub bottom: LengthOrAuto,
161    pub left: LengthOrAuto,
162}
163
164pub use self::GenericClipRect as ClipRect;
165
166/// Either a clip-rect or `auto`.
167#[allow(missing_docs)]
168#[derive(
169    Animate,
170    Clone,
171    ComputeSquaredDistance,
172    Copy,
173    Debug,
174    MallocSizeOf,
175    Parse,
176    PartialEq,
177    SpecifiedValueInfo,
178    ToAnimatedValue,
179    ToAnimatedZero,
180    ToComputedValue,
181    ToCss,
182    ToResolvedValue,
183    ToShmem,
184    ToTyped,
185)]
186#[repr(C, u8)]
187#[typed(todo_derive_fields)]
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}