1use 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#[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 #[inline]
80 pub const fn new(x: T) -> Self {
81 Length(x, PhantomData)
82 }
83}
84
85impl<T: Clone, U> Length<T, U> {
86 pub fn get(self) -> T {
88 self.0
89 }
90
91 #[inline]
93 pub fn cast_unit<V>(self) -> Length<T, V> {
94 Length::new(self.0)
95 }
96
97 #[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 #[inline]
126 pub fn min(self, other: Self) -> Self {
127 min(self, other)
128 }
129
130 #[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 #[inline]
140 pub fn cast<NewT: NumCast>(self) -> Length<NewT, U> {
141 self.try_cast().unwrap()
142 }
143
144 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
169impl<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
178impl<T: AddAssign, U> AddAssign for Length<T, U> {
180 fn add_assign(&mut self, other: Self) {
181 self.0 += other.0;
182 }
183}
184
185impl<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
194impl<T: SubAssign, U> SubAssign for Length<T, U> {
196 fn sub_assign(&mut self, other: Self) {
197 self.0 -= other.0;
198 }
199}
200
201impl<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
212impl<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
222impl<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
232impl<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
240impl<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
250impl<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
258impl<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
268impl<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
278impl<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 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 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}