euclid/
length.rs

1// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9//! A one-dimensional length, tagged with its units.
10
11use crate::approxeq::ApproxEq;
12use crate::approxord::{max, min};
13use crate::num::Zero;
14use crate::scale::Scale;
15
16use crate::num::One;
17#[cfg(feature = "bytemuck")]
18use bytemuck::{Pod, Zeroable};
19use core::cmp::Ordering;
20use core::fmt;
21use core::hash::{Hash, Hasher};
22use core::iter::Sum;
23use core::marker::PhantomData;
24use core::ops::{Add, Div, Mul, Neg, Sub};
25use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
26#[cfg(feature = "malloc_size_of")]
27use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
28use num_traits::{NumCast, Saturating};
29#[cfg(feature = "serde")]
30use serde::{Deserialize, Deserializer, Serialize, Serializer};
31
32/// A one-dimensional distance, with value represented by `T` and unit of measurement `Unit`.
33///
34/// `T` can be any numeric type, for example a primitive type like `u64` or `f32`.
35///
36/// `Unit` is not used in the representation of a `Length` value. It is used only at compile time
37/// to ensure that a `Length` stored with one unit is converted explicitly before being used in an
38/// expression that requires a different unit.  It may be a type without values, such as an empty
39/// enum.
40///
41/// You can multiply a `Length` by a [`Scale`] to convert it from one unit to
42/// another. See the [`Scale`] docs for an example.
43#[repr(C)]
44pub struct Length<T, Unit>(pub T, #[doc(hidden)] pub PhantomData<Unit>);
45
46impl<T: Clone, U> Clone for Length<T, U> {
47    fn clone(&self) -> Self {
48        Length(self.0.clone(), PhantomData)
49    }
50}
51
52impl<T: Copy, U> Copy for Length<T, U> {}
53
54#[cfg(feature = "serde")]
55impl<'de, T, U> Deserialize<'de> for Length<T, U>
56where
57    T: Deserialize<'de>,
58{
59    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60    where
61        D: Deserializer<'de>,
62    {
63        Ok(Length(Deserialize::deserialize(deserializer)?, PhantomData))
64    }
65}
66
67#[cfg(feature = "serde")]
68impl<T, U> Serialize for Length<T, U>
69where
70    T: Serialize,
71{
72    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73    where
74        S: Serializer,
75    {
76        self.0.serialize(serializer)
77    }
78}
79
80#[cfg(feature = "arbitrary")]
81impl<'a, T, U> arbitrary::Arbitrary<'a> for Length<T, U>
82where
83    T: arbitrary::Arbitrary<'a>,
84{
85    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
86        Ok(Length(arbitrary::Arbitrary::arbitrary(u)?, PhantomData))
87    }
88}
89
90#[cfg(feature = "bytemuck")]
91unsafe impl<T: Zeroable, U> Zeroable for Length<T, U> {}
92
93#[cfg(feature = "bytemuck")]
94unsafe impl<T: Pod, U: 'static> Pod for Length<T, U> {}
95
96#[cfg(feature = "malloc_size_of")]
97impl<T: MallocSizeOf, U> MallocSizeOf for Length<T, U> {
98    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
99        self.0.size_of(ops)
100    }
101}
102
103impl<T, U> Length<T, U> {
104    /// Associate a value with a unit of measure.
105    #[inline]
106    pub const fn new(x: T) -> Self {
107        Length(x, PhantomData)
108    }
109}
110
111impl<T: Clone, U> Length<T, U> {
112    /// Unpack the underlying value from the wrapper.
113    pub fn get(self) -> T {
114        self.0
115    }
116
117    /// Cast the unit
118    #[inline]
119    pub fn cast_unit<V>(self) -> Length<T, V> {
120        Length::new(self.0)
121    }
122
123    /// Linearly interpolate between this length and another length.
124    ///
125    /// # Example
126    ///
127    /// ```rust
128    /// use euclid::default::Length;
129    ///
130    /// let from = Length::new(0.0);
131    /// let to = Length::new(8.0);
132    ///
133    /// assert_eq!(from.lerp(to, -1.0), Length::new(-8.0));
134    /// assert_eq!(from.lerp(to,  0.0), Length::new( 0.0));
135    /// assert_eq!(from.lerp(to,  0.5), Length::new( 4.0));
136    /// assert_eq!(from.lerp(to,  1.0), Length::new( 8.0));
137    /// assert_eq!(from.lerp(to,  2.0), Length::new(16.0));
138    /// ```
139    #[inline]
140    pub fn lerp(self, other: Self, t: T) -> Self
141    where
142        T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
143    {
144        let one_t = T::one() - t.clone();
145        Length::new(one_t * self.0.clone() + t * other.0)
146    }
147}
148
149impl<T: PartialOrd, U> Length<T, U> {
150    /// Returns minimum between this length and another length.
151    #[inline]
152    pub fn min(self, other: Self) -> Self {
153        min(self, other)
154    }
155
156    /// Returns maximum between this length and another length.
157    #[inline]
158    pub fn max(self, other: Self) -> Self {
159        max(self, other)
160    }
161}
162
163impl<T: NumCast + Clone, U> Length<T, U> {
164    /// Cast from one numeric representation to another, preserving the units.
165    #[inline]
166    pub fn cast<NewT: NumCast>(self) -> Length<NewT, U> {
167        self.try_cast().unwrap()
168    }
169
170    /// Fallible cast from one numeric representation to another, preserving the units.
171    pub fn try_cast<NewT: NumCast>(self) -> Option<Length<NewT, U>> {
172        NumCast::from(self.0).map(Length::new)
173    }
174}
175
176impl<T: fmt::Debug, U> fmt::Debug for Length<T, U> {
177    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178        self.0.fmt(f)
179    }
180}
181
182impl<T: Default, U> Default for Length<T, U> {
183    #[inline]
184    fn default() -> Self {
185        Length::new(Default::default())
186    }
187}
188
189impl<T: Hash, U> Hash for Length<T, U> {
190    fn hash<H: Hasher>(&self, h: &mut H) {
191        self.0.hash(h);
192    }
193}
194
195// length + length
196impl<T: Add, U> Add for Length<T, U> {
197    type Output = Length<T::Output, U>;
198
199    fn add(self, other: Self) -> Self::Output {
200        Length::new(self.0 + other.0)
201    }
202}
203
204// length + &length
205impl<T: Add + Copy, U> Add<&Self> for Length<T, U> {
206    type Output = Length<T::Output, U>;
207
208    fn add(self, other: &Self) -> Self::Output {
209        Length::new(self.0 + other.0)
210    }
211}
212
213// length_iter.copied().sum()
214impl<T: Add<Output = T> + Zero, U> Sum for Length<T, U> {
215    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
216        iter.fold(Self::zero(), Add::add)
217    }
218}
219
220// length_iter.sum()
221impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Length<T, U> {
222    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
223        iter.fold(Self::zero(), Add::add)
224    }
225}
226
227// length += length
228impl<T: AddAssign, U> AddAssign for Length<T, U> {
229    fn add_assign(&mut self, other: Self) {
230        self.0 += other.0;
231    }
232}
233
234// length - length
235impl<T: Sub, U> Sub for Length<T, U> {
236    type Output = Length<T::Output, U>;
237
238    fn sub(self, other: Length<T, U>) -> Self::Output {
239        Length::new(self.0 - other.0)
240    }
241}
242
243// length -= length
244impl<T: SubAssign, U> SubAssign for Length<T, U> {
245    fn sub_assign(&mut self, other: Self) {
246        self.0 -= other.0;
247    }
248}
249
250// Saturating length + length and length - length.
251impl<T: Saturating, U> Saturating for Length<T, U> {
252    fn saturating_add(self, other: Self) -> Self {
253        Length::new(self.0.saturating_add(other.0))
254    }
255
256    fn saturating_sub(self, other: Self) -> Self {
257        Length::new(self.0.saturating_sub(other.0))
258    }
259}
260
261// length / length
262impl<Src, Dst, T: Div> Div<Length<T, Src>> for Length<T, Dst> {
263    type Output = Scale<T::Output, Src, Dst>;
264
265    #[inline]
266    fn div(self, other: Length<T, Src>) -> Self::Output {
267        Scale::new(self.0 / other.0)
268    }
269}
270
271// length * scalar
272impl<T: Mul, U> Mul<T> for Length<T, U> {
273    type Output = Length<T::Output, U>;
274
275    #[inline]
276    fn mul(self, scale: T) -> Self::Output {
277        Length::new(self.0 * scale)
278    }
279}
280
281// length *= scalar
282impl<T: Copy + Mul<T, Output = T>, U> MulAssign<T> for Length<T, U> {
283    #[inline]
284    fn mul_assign(&mut self, scale: T) {
285        *self = *self * scale;
286    }
287}
288
289// length / scalar
290impl<T: Div, U> Div<T> for Length<T, U> {
291    type Output = Length<T::Output, U>;
292
293    #[inline]
294    fn div(self, scale: T) -> Self::Output {
295        Length::new(self.0 / scale)
296    }
297}
298
299// length /= scalar
300impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Length<T, U> {
301    #[inline]
302    fn div_assign(&mut self, scale: T) {
303        *self = *self / scale;
304    }
305}
306
307// length * scaleFactor
308impl<Src, Dst, T: Mul> Mul<Scale<T, Src, Dst>> for Length<T, Src> {
309    type Output = Length<T::Output, Dst>;
310
311    #[inline]
312    fn mul(self, scale: Scale<T, Src, Dst>) -> Self::Output {
313        Length::new(self.0 * scale.0)
314    }
315}
316
317// length / scaleFactor
318impl<Src, Dst, T: Div> Div<Scale<T, Src, Dst>> for Length<T, Dst> {
319    type Output = Length<T::Output, Src>;
320
321    #[inline]
322    fn div(self, scale: Scale<T, Src, Dst>) -> Self::Output {
323        Length::new(self.0 / scale.0)
324    }
325}
326
327// -length
328impl<U, T: Neg> Neg for Length<T, U> {
329    type Output = Length<T::Output, U>;
330
331    #[inline]
332    fn neg(self) -> Self::Output {
333        Length::new(-self.0)
334    }
335}
336
337impl<T: PartialEq, U> PartialEq for Length<T, U> {
338    fn eq(&self, other: &Self) -> bool {
339        self.0.eq(&other.0)
340    }
341}
342
343impl<T: PartialOrd, U> PartialOrd for Length<T, U> {
344    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
345        self.0.partial_cmp(&other.0)
346    }
347}
348
349impl<T: Eq, U> Eq for Length<T, U> {}
350
351impl<T: Ord, U> Ord for Length<T, U> {
352    fn cmp(&self, other: &Self) -> Ordering {
353        self.0.cmp(&other.0)
354    }
355}
356
357impl<T: Zero, U> Zero for Length<T, U> {
358    #[inline]
359    fn zero() -> Self {
360        Length::new(Zero::zero())
361    }
362}
363
364impl<U, T: ApproxEq<T>> ApproxEq<T> for Length<T, U> {
365    #[inline]
366    fn approx_epsilon() -> T {
367        T::approx_epsilon()
368    }
369
370    #[inline]
371    fn approx_eq_eps(&self, other: &Length<T, U>, approx_epsilon: &T) -> bool {
372        self.0.approx_eq_eps(&other.0, approx_epsilon)
373    }
374}
375
376#[cfg(test)]
377mod tests {
378    use super::Length;
379    use crate::num::Zero;
380
381    use crate::scale::Scale;
382    use core::f32::INFINITY;
383    use num_traits::Saturating;
384
385    enum Inch {}
386    enum Mm {}
387    enum Cm {}
388    enum Second {}
389
390    #[cfg(feature = "serde")]
391    mod serde {
392        use super::*;
393
394        extern crate serde_test;
395        use self::serde_test::assert_tokens;
396        use self::serde_test::Token;
397
398        #[test]
399        fn test_length_serde() {
400            let one_cm: Length<f32, Mm> = Length::new(10.0);
401
402            assert_tokens(&one_cm, &[Token::F32(10.0)]);
403        }
404    }
405
406    #[test]
407    fn test_clone() {
408        // A cloned Length is a separate length with the state matching the
409        // original Length at the point it was cloned.
410        let mut variable_length: Length<f32, Inch> = Length::new(12.0);
411
412        let one_foot = variable_length.clone();
413        variable_length.0 = 24.0;
414
415        assert_eq!(one_foot.get(), 12.0);
416        assert_eq!(variable_length.get(), 24.0);
417    }
418
419    #[test]
420    fn test_add() {
421        let length1: Length<u8, Mm> = Length::new(250);
422        let length2: Length<u8, Mm> = Length::new(5);
423
424        assert_eq!((length1 + length2).get(), 255);
425        assert_eq!((length1 + &length2).get(), 255);
426    }
427
428    #[test]
429    fn test_sum() {
430        type L = Length<f32, Mm>;
431        let lengths = [L::new(1.0), L::new(2.0), L::new(3.0)];
432
433        assert_eq!(lengths.iter().sum::<L>(), L::new(6.0));
434    }
435
436    #[test]
437    fn test_addassign() {
438        let one_cm: Length<f32, Mm> = Length::new(10.0);
439        let mut measurement: Length<f32, Mm> = Length::new(5.0);
440
441        measurement += one_cm;
442
443        assert_eq!(measurement.get(), 15.0);
444    }
445
446    #[test]
447    fn test_sub() {
448        let length1: Length<u8, Mm> = Length::new(250);
449        let length2: Length<u8, Mm> = Length::new(5);
450
451        let result = length1 - length2;
452
453        assert_eq!(result.get(), 245);
454    }
455
456    #[test]
457    fn test_subassign() {
458        let one_cm: Length<f32, Mm> = Length::new(10.0);
459        let mut measurement: Length<f32, Mm> = Length::new(5.0);
460
461        measurement -= one_cm;
462
463        assert_eq!(measurement.get(), -5.0);
464    }
465
466    #[test]
467    fn test_saturating_add() {
468        let length1: Length<u8, Mm> = Length::new(250);
469        let length2: Length<u8, Mm> = Length::new(6);
470
471        let result = length1.saturating_add(length2);
472
473        assert_eq!(result.get(), 255);
474    }
475
476    #[test]
477    fn test_saturating_sub() {
478        let length1: Length<u8, Mm> = Length::new(5);
479        let length2: Length<u8, Mm> = Length::new(10);
480
481        let result = length1.saturating_sub(length2);
482
483        assert_eq!(result.get(), 0);
484    }
485
486    #[test]
487    fn test_division_by_length() {
488        // Division results in a Scale from denominator units
489        // to numerator units.
490        let length: Length<f32, Cm> = Length::new(5.0);
491        let duration: Length<f32, Second> = Length::new(10.0);
492
493        let result = length / duration;
494
495        let expected: Scale<f32, Second, Cm> = Scale::new(0.5);
496        assert_eq!(result, expected);
497    }
498
499    #[test]
500    fn test_multiplication() {
501        let length_mm: Length<f32, Mm> = Length::new(10.0);
502        let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
503
504        let result = length_mm * cm_per_mm;
505
506        let expected: Length<f32, Cm> = Length::new(1.0);
507        assert_eq!(result, expected);
508    }
509
510    #[test]
511    fn test_multiplication_with_scalar() {
512        let length_mm: Length<f32, Mm> = Length::new(10.0);
513
514        let result = length_mm * 2.0;
515
516        let expected: Length<f32, Mm> = Length::new(20.0);
517        assert_eq!(result, expected);
518    }
519
520    #[test]
521    fn test_multiplication_assignment() {
522        let mut length: Length<f32, Mm> = Length::new(10.0);
523
524        length *= 2.0;
525
526        let expected: Length<f32, Mm> = Length::new(20.0);
527        assert_eq!(length, expected);
528    }
529
530    #[test]
531    fn test_division_by_scalefactor() {
532        let length: Length<f32, Cm> = Length::new(5.0);
533        let cm_per_second: Scale<f32, Second, Cm> = Scale::new(10.0);
534
535        let result = length / cm_per_second;
536
537        let expected: Length<f32, Second> = Length::new(0.5);
538        assert_eq!(result, expected);
539    }
540
541    #[test]
542    fn test_division_by_scalar() {
543        let length: Length<f32, Cm> = Length::new(5.0);
544
545        let result = length / 2.0;
546
547        let expected: Length<f32, Cm> = Length::new(2.5);
548        assert_eq!(result, expected);
549    }
550
551    #[test]
552    fn test_division_assignment() {
553        let mut length: Length<f32, Mm> = Length::new(10.0);
554
555        length /= 2.0;
556
557        let expected: Length<f32, Mm> = Length::new(5.0);
558        assert_eq!(length, expected);
559    }
560
561    #[test]
562    fn test_negation() {
563        let length: Length<f32, Cm> = Length::new(5.0);
564
565        let result = -length;
566
567        let expected: Length<f32, Cm> = Length::new(-5.0);
568        assert_eq!(result, expected);
569    }
570
571    #[test]
572    fn test_cast() {
573        let length_as_i32: Length<i32, Cm> = Length::new(5);
574
575        let result: Length<f32, Cm> = length_as_i32.cast();
576
577        let length_as_f32: Length<f32, Cm> = Length::new(5.0);
578        assert_eq!(result, length_as_f32);
579    }
580
581    #[test]
582    fn test_equality() {
583        let length_5_point_0: Length<f32, Cm> = Length::new(5.0);
584        let length_5_point_1: Length<f32, Cm> = Length::new(5.1);
585        let length_0_point_1: Length<f32, Cm> = Length::new(0.1);
586
587        assert!(length_5_point_0 == length_5_point_1 - length_0_point_1);
588        assert!(length_5_point_0 != length_5_point_1);
589    }
590
591    #[test]
592    fn test_order() {
593        let length_5_point_0: Length<f32, Cm> = Length::new(5.0);
594        let length_5_point_1: Length<f32, Cm> = Length::new(5.1);
595        let length_0_point_1: Length<f32, Cm> = Length::new(0.1);
596
597        assert!(length_5_point_0 < length_5_point_1);
598        assert!(length_5_point_0 <= length_5_point_1);
599        assert!(length_5_point_0 <= length_5_point_1 - length_0_point_1);
600        assert!(length_5_point_1 > length_5_point_0);
601        assert!(length_5_point_1 >= length_5_point_0);
602        assert!(length_5_point_0 >= length_5_point_1 - length_0_point_1);
603    }
604
605    #[test]
606    fn test_zero_add() {
607        type LengthCm = Length<f32, Cm>;
608        let length: LengthCm = Length::new(5.0);
609
610        let result = length - LengthCm::zero();
611
612        assert_eq!(result, length);
613    }
614
615    #[test]
616    fn test_zero_division() {
617        type LengthCm = Length<f32, Cm>;
618        let length: LengthCm = Length::new(5.0);
619        let length_zero: LengthCm = Length::zero();
620
621        let result = length / length_zero;
622
623        let expected: Scale<f32, Cm, Cm> = Scale::new(INFINITY);
624        assert_eq!(result, expected);
625    }
626}