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