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#[derive(
97    Animate,
98    Clone,
99    ComputeSquaredDistance,
100    Copy,
101    Debug,
102    Deserialize,
103    MallocSizeOf,
104    PartialEq,
105    PartialOrd,
106    Serialize,
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#[derive(
119    Animate,
120    Clone,
121    ComputeSquaredDistance,
122    Copy,
123    Debug,
124    Deserialize,
125    Hash,
126    MallocSizeOf,
127    PartialEq,
128    PartialOrd,
129    Serialize,
130    SpecifiedValueInfo,
131    ToAnimatedZero,
132    ToComputedValue,
133    ToCss,
134    ToResolvedValue,
135    ToShmem,
136)]
137#[repr(transparent)]
138pub struct ZeroToOne<T>(pub T);
139
140/// A clip rect for clip and image-region
141#[allow(missing_docs)]
142#[derive(
143    Clone,
144    ComputeSquaredDistance,
145    Copy,
146    Debug,
147    MallocSizeOf,
148    PartialEq,
149    SpecifiedValueInfo,
150    ToAnimatedValue,
151    ToAnimatedZero,
152    ToComputedValue,
153    ToCss,
154    ToResolvedValue,
155    ToShmem,
156)]
157#[css(function = "rect", comma)]
158#[repr(C)]
159pub struct GenericClipRect<LengthOrAuto> {
160    pub top: LengthOrAuto,
161    pub right: LengthOrAuto,
162    pub bottom: LengthOrAuto,
163    pub left: LengthOrAuto,
164}
165
166pub use self::GenericClipRect as ClipRect;
167
168/// Either a clip-rect or `auto`.
169#[allow(missing_docs)]
170#[derive(
171    Animate,
172    Clone,
173    ComputeSquaredDistance,
174    Copy,
175    Debug,
176    MallocSizeOf,
177    Parse,
178    PartialEq,
179    SpecifiedValueInfo,
180    ToAnimatedValue,
181    ToAnimatedZero,
182    ToComputedValue,
183    ToCss,
184    ToResolvedValue,
185    ToShmem,
186    ToTyped,
187)]
188#[repr(C, u8)]
189#[typed(todo_derive_fields)]
190pub enum GenericClipRectOrAuto<R> {
191    Auto,
192    Rect(R),
193}
194
195pub use self::GenericClipRectOrAuto as ClipRectOrAuto;
196
197impl<L> ClipRectOrAuto<L> {
198    /// Returns the `auto` value.
199    #[inline]
200    pub fn auto() -> Self {
201        ClipRectOrAuto::Auto
202    }
203
204    /// Returns whether this value is the `auto` value.
205    #[inline]
206    pub fn is_auto(&self) -> bool {
207        matches!(*self, ClipRectOrAuto::Auto)
208    }
209}
210
211pub use page::PageSize;
212
213pub use text::NumberOrAuto;
214
215/// An optional value, much like `Option<T>`, but with a defined struct layout
216/// to be able to use it from C++ as well.
217///
218/// Note that this is relatively inefficient, struct-layout-wise, as you have
219/// one byte for the tag, but padding to the alignment of T. If you have
220/// multiple optional values and care about struct compactness, you might be
221/// better off "coalescing" the combinations into a parent enum. But that
222/// shouldn't matter for most use cases.
223#[allow(missing_docs)]
224#[derive(
225    Animate,
226    Clone,
227    ComputeSquaredDistance,
228    Copy,
229    Debug,
230    MallocSizeOf,
231    Parse,
232    PartialEq,
233    SpecifiedValueInfo,
234    ToAnimatedValue,
235    ToAnimatedZero,
236    ToComputedValue,
237    ToCss,
238    ToResolvedValue,
239    ToShmem,
240    Serialize,
241    Deserialize,
242)]
243#[repr(C, u8)]
244pub enum Optional<T> {
245    #[css(skip)]
246    None,
247    Some(T),
248}
249
250impl<T> Optional<T> {
251    /// Returns whether this value is present.
252    pub fn is_some(&self) -> bool {
253        matches!(*self, Self::Some(..))
254    }
255
256    /// Returns whether this value is not present.
257    pub fn is_none(&self) -> bool {
258        matches!(*self, Self::None)
259    }
260
261    /// Turns this Optional<> into a regular rust Option<>.
262    pub fn into_rust(self) -> Option<T> {
263        match self {
264            Self::Some(v) => Some(v),
265            Self::None => None,
266        }
267    }
268
269    /// Return a reference to the containing value, if any, as a plain rust
270    /// Option<>.
271    pub fn as_ref(&self) -> Option<&T> {
272        match *self {
273            Self::Some(ref v) => Some(v),
274            Self::None => None,
275        }
276    }
277
278    /// Return a mutable reference to the containing value, if any, as a plain
279    /// rust Option<>.
280    pub fn as_mut(&mut self) -> Option<&mut T> {
281        match *self {
282            Self::Some(ref mut v) => Some(v),
283            Self::None => None,
284        }
285    }
286
287    /// See Option::map.
288    pub fn map<U>(self, map: impl FnOnce(T) -> U) -> Optional<U> {
289        match self {
290            Self::Some(v) => Optional::Some(map(v)),
291            Self::None => Optional::None,
292        }
293    }
294}
295
296impl<T> From<Option<T>> for Optional<T> {
297    fn from(rust: Option<T>) -> Self {
298        match rust {
299            Some(t) => Self::Some(t),
300            None => Self::None,
301        }
302    }
303}