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