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