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::Zero;
9use crate::derives::*;
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    Hash,
231    MallocSizeOf,
232    Parse,
233    PartialEq,
234    SpecifiedValueInfo,
235    ToAnimatedValue,
236    ToAnimatedZero,
237    ToComputedValue,
238    ToCss,
239    ToResolvedValue,
240    ToShmem,
241    Serialize,
242    Deserialize,
243)]
244#[repr(C, u8)]
245pub enum Optional<T> {
246    #[css(skip)]
247    None,
248    Some(T),
249}
250
251impl<T> Optional<T> {
252    /// Returns whether this value is present.
253    pub fn is_some(&self) -> bool {
254        matches!(*self, Self::Some(..))
255    }
256
257    /// Returns whether this value is not present.
258    pub fn is_none(&self) -> bool {
259        matches!(*self, Self::None)
260    }
261
262    /// Turns this Optional<> into a regular rust Option<>.
263    pub fn into_rust(self) -> Option<T> {
264        match self {
265            Self::Some(v) => Some(v),
266            Self::None => None,
267        }
268    }
269
270    /// Return a reference to the containing value, if any, as a plain rust
271    /// Option<>.
272    pub fn as_ref(&self) -> Option<&T> {
273        match *self {
274            Self::Some(ref v) => Some(v),
275            Self::None => None,
276        }
277    }
278
279    /// Return a mutable reference to the containing value, if any, as a plain
280    /// rust Option<>.
281    pub fn as_mut(&mut self) -> Option<&mut T> {
282        match *self {
283            Self::Some(ref mut v) => Some(v),
284            Self::None => None,
285        }
286    }
287
288    /// See Option::map.
289    pub fn map<U>(self, map: impl FnOnce(T) -> U) -> Optional<U> {
290        match self {
291            Self::Some(v) => Optional::Some(map(v)),
292            Self::None => Optional::None,
293        }
294    }
295}
296
297impl<T> From<Option<T>> for Optional<T> {
298    fn from(rust: Option<T>) -> Self {
299        match rust {
300            Some(t) => Self::Some(t),
301            None => Self::None,
302        }
303    }
304}