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