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