embedded_time/rate.rs
1//! Rate-based types/units
2
3pub use crate::fraction::Fraction;
4use crate::{
5 duration,
6 fixed_point::{self, FixedPoint},
7 time_int::TimeInt,
8 ConversionError,
9};
10use core::{convert::TryFrom, mem::size_of, prelude::v1::*};
11#[doc(hidden)]
12pub use fixed_point::FixedPoint as _;
13use num::{CheckedDiv, CheckedMul};
14#[doc(inline)]
15pub use units::*;
16
17/// An unsigned, fixed-point rate type
18///
19/// Each implementation defines an _integer_ type and a _scaling factor_ [`Fraction`].
20///
21/// # Constructing a rate
22///
23/// ```rust
24/// use embedded_time::rate::*;
25///
26/// let _ = <Kilohertz>::new(5);
27/// let _ = Kilohertz(5_u32);
28/// let _ = 5_u32.kHz();
29/// ```
30///
31/// # Get the integer part
32///
33/// ```rust
34/// use embedded_time::rate::*;
35///
36/// assert_eq!(Hertz(45_u32).integer(), 45_u32);
37/// ```
38///
39/// # Formatting
40///
41/// Just forwards the underlying integer to [`core::fmt::Display::fmt()`]
42///
43/// ```rust
44/// use embedded_time::rate::*;
45///
46/// assert_eq!(format!("{}", Hertz(123_u32)), "123");
47/// ```
48///
49/// # Converting between `Rate`s
50///
51/// Many intra-rate conversions can be done using `From`/`Into`:
52///
53/// ```rust
54/// use embedded_time::rate::*;
55///
56/// let kilohertz = Kilohertz::<u32>::from(23_000_u32.Hz());
57/// assert_eq!(kilohertz.integer(), 23_u32);
58///
59/// let kilohertz: Kilohertz<u32> = 23_000_u32.Hz().into();
60/// assert_eq!(kilohertz.integer(), 23_u32);
61/// ```
62///
63/// Others require the use of `TryFrom`/`TryInto`:
64///
65/// ```rust
66/// use embedded_time::rate::*;
67/// use std::convert::{TryInto, TryFrom};
68///
69/// let hertz = Hertz::<u32>::try_from(23_u32.kHz()).unwrap();
70/// assert_eq!(hertz.integer(), 23_000_u32);
71///
72/// let hertz: Hertz<u32> = 23_u32.kHz().try_into().unwrap();
73/// assert_eq!(hertz.integer(), 23_000_u32);
74/// ```
75///
76/// # Converting from a [`Generic`] `Rate`
77///
78/// ## Examples
79///
80/// ```rust
81/// use embedded_time::rate::*;
82/// use core::convert::{TryFrom, TryInto};
83///
84/// // A generic rate of 20_000 events/second
85/// let generic_rate = Generic::new(10_u32, Fraction::new(2_000, 1));
86///
87/// let rate = KilobitsPerSecond::<u32>::try_from(generic_rate).unwrap();
88/// assert_eq!(rate, 20_u32.kbps());
89///
90/// let rate: KilobitsPerSecond<u32> = generic_rate.try_into().unwrap();
91/// assert_eq!(rate, 20_u32.kbps());
92/// ```
93///
94/// ## Errors
95///
96/// Failure will only occur if the provided value does not fit in the selected destination type.
97///
98/// ---
99///
100/// [`ConversionError::Unspecified`]
101///
102/// ```rust
103/// use embedded_time::{rate::*, ConversionError};
104/// use core::convert::TryFrom;
105///
106/// assert_eq!(
107/// Hertz::<u32>::try_from(Generic::new(u32::MAX, Fraction::new(10,1))),
108/// Err(ConversionError::Unspecified)
109/// );
110/// ```
111///
112/// ---
113///
114/// [`ConversionError::ConversionFailure`] : The _integer_ conversion to that of the
115/// destination type fails.
116///
117/// ```rust
118/// use embedded_time::{rate::*, ConversionError};
119/// # use core::convert::TryFrom;
120///
121/// assert_eq!(
122/// Hertz::<u32>::try_from(Generic::new(u32::MAX as u64 + 1, Fraction::new(1,1))),
123/// Err(ConversionError::ConversionFailure)
124/// );
125/// ```
126///
127/// # Converting to a [`Generic`] `Rate` with the same _scaling factor_
128///
129/// ```rust
130/// use embedded_time::rate::*;
131///
132/// let generic_rate = Generic::<u32>::from(5_u32.Hz());
133/// let generic_rate: Generic<u32> = 5_u32.Hz().into();
134///
135/// assert_eq!(generic_rate.integer(), 5_u32);
136/// ```
137///
138/// # Converting to a [`Generic`] `Rate` with a different _scaling factor_
139///
140/// See [`Rate::to_generic()`]
141///
142/// # Converting to a _named_ `Duration`
143///
144/// See [`Rate::to_duration()`]
145///
146/// # Creating a custom `Rate`
147///
148///
149///
150/// # Add/Sub
151///
152/// The result of the operation is the LHS type
153///
154/// ## Examples
155///
156/// ```rust
157/// use embedded_time::rate::*;
158///
159/// assert_eq!((Hertz(1_u32) + 1_u32.kHz()),
160/// Hertz(1_001_u32));
161///
162/// assert_eq!((Hertz(2_001_u32) - 1_u32.kHz()),
163/// Hertz(1_001_u32));
164/// ```
165///
166/// ## Panics
167///
168/// The same reason the integer operation would panic. Namely, if the result overflows the type.
169///
170/// ```rust,should_panic
171/// use embedded_time::rate::*;
172///
173/// let _ = Hertz(u32::MAX) + Hertz(1_u32);
174/// ```
175///
176/// # Mul/Div
177///
178/// Rates may also be multiplied and divided by integers. The result is of the LHS type. Both
179/// _panicky_ and _checked_ operations are available.
180///
181/// # Comparisons
182///
183/// ```rust
184/// use embedded_time::rate::*;
185///
186/// assert_eq!(Kilohertz(2_u32), Hertz(2_000_u32));
187/// assert_ne!(Kilohertz(2_u32), Hertz(2_001_u32));
188///
189/// assert!(Kilohertz(2_u32) < Hertz(2_001_u32));
190/// assert!(Kilohertz(2_u32) > Hertz(1_999_u32));
191/// ```
192///
193/// # Remainder
194///
195/// ```rust
196/// use embedded_time::rate::*;
197///
198/// assert_eq!(Hertz(2_037_u32) % Kilohertz(1_u32), Hertz(37_u32));
199/// ```
200pub trait Rate: Sized + Copy {
201 /// Construct a `Generic` `Rate` from a _named_ `Rate` (eg. [`Kilohertz`])
202 ///
203 /// # Examples
204 ///
205 /// ```rust
206 /// use embedded_time::rate::*;
207 ///
208 /// let kilobits = KilobitsPerSecond(20_u32);
209 ///
210 /// // convert into a generic rate with a different _scaling factor_
211 /// let generic = kilobits.to_generic::<u32>(Fraction::new(500, 1)).unwrap();
212 ///
213 /// assert_eq!(generic.integer(), 40_u32);
214 /// ```
215 ///
216 /// # Errors
217 ///
218 /// Failure will only occur if the provided value does not fit in the selected destination type.
219 ///
220 /// ---
221 ///
222 /// [`ConversionError::Unspecified`]
223 ///
224 /// ```rust
225 /// # use embedded_time::{rate::*, ConversionError};
226 ///
227 /// assert_eq!(
228 /// Hertz(u32::MAX).to_generic::<u32>(Fraction::new(1, 2)),
229 /// Err(ConversionError::Unspecified)
230 /// );
231 /// ```
232 ///
233 /// ---
234 ///
235 /// [`ConversionError::ConversionFailure`] : The integer conversion to that of the destination
236 /// type fails.
237 ///
238 /// ```rust
239 /// use embedded_time::{fraction::Fraction, rate::*, ConversionError};
240 ///
241 /// assert_eq!(
242 /// Hertz(u32::MAX as u64 + 1).to_generic::<u32>(Fraction::new(1, 1)),
243 /// Err(ConversionError::ConversionFailure)
244 /// );
245 /// ```
246 fn to_generic<DestInt: TimeInt>(
247 self,
248 scaling_factor: Fraction,
249 ) -> Result<Generic<DestInt>, ConversionError>
250 where
251 Self: FixedPoint,
252 DestInt: TryFrom<Self::T>,
253 {
254 Ok(Generic::<DestInt>::new(
255 self.into_ticks(scaling_factor)?,
256 scaling_factor,
257 ))
258 }
259
260 /// Convert to _named_ [`Duration`](duration::Duration)
261 ///
262 /// (the rate is equal to the reciprocal of the duration)
263 ///
264 /// # Examples
265 ///
266 /// ```rust
267 /// use embedded_time::{duration::*, rate::*};
268 ///
269 /// assert_eq!(
270 /// Kilohertz(500_u32).to_duration(),
271 /// Ok(Microseconds(2_u32))
272 /// );
273 /// ```
274 ///
275 /// # Errors
276 ///
277 /// Failure will only occur if the provided value does not fit in the selected destination type.
278 ///
279 /// ---
280 ///
281 /// [`ConversionError::Overflow`] : The conversion of the _scaling factor_ causes an overflow.
282 ///
283 /// ```rust
284 /// use embedded_time::{duration::*, rate::*, ConversionError};
285 ///
286 /// assert_eq!(
287 /// Megahertz(u32::MAX).to_duration::<Hours<u32>>(),
288 /// Err(ConversionError::Overflow)
289 /// );
290 /// ```
291 ///
292 /// ---
293 ///
294 /// [`ConversionError::DivByZero`] : The rate is `0`, therefore the reciprocal is undefined.
295 ///
296 /// ```rust
297 /// use embedded_time::{duration::*, rate::*, ConversionError};
298 ///
299 /// assert_eq!(
300 /// Hertz(0_u32).to_duration::<Seconds<u32>>(),
301 /// Err(ConversionError::DivByZero)
302 /// );
303 /// ```
304 fn to_duration<Duration: duration::Duration>(&self) -> Result<Duration, ConversionError>
305 where
306 Duration: FixedPoint,
307 Self: FixedPoint,
308 Duration::T: TryFrom<Self::T>,
309 {
310 let conversion_factor = Self::SCALING_FACTOR
311 .checked_mul(&Duration::SCALING_FACTOR)
312 .ok_or(ConversionError::Unspecified)?
313 .recip();
314
315 if size_of::<Self::T>() >= size_of::<Duration::T>() {
316 fixed_point::FixedPoint::from_ticks(
317 Self::T::from(*conversion_factor.numerator())
318 .checked_div(
319 &self
320 .integer()
321 .checked_mul(&Self::T::from(*conversion_factor.denominator()))
322 .ok_or(ConversionError::Overflow)?,
323 )
324 .ok_or(ConversionError::DivByZero)?,
325 Duration::SCALING_FACTOR,
326 )
327 } else {
328 fixed_point::FixedPoint::from_ticks(
329 Duration::T::from(*conversion_factor.numerator())
330 .checked_div(
331 &Duration::T::try_from(self.integer())
332 .map_err(|_| ConversionError::Overflow)?
333 .checked_mul(&Duration::T::from(*conversion_factor.denominator()))
334 .ok_or(ConversionError::Overflow)?,
335 )
336 .ok_or(ConversionError::DivByZero)?,
337 Duration::SCALING_FACTOR,
338 )
339 }
340 }
341}
342
343/// The `Generic` `Rate` type allows an arbitrary _scaling factor_ to be used without having to
344/// impl `FixedPoint`.
345///
346/// The purpose of this type is to allow a simple `Rate` object that can be defined at run-time.
347/// It does this by replacing the `const` _scaling factor_ with a struct field.
348#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
349pub struct Generic<T> {
350 integer: T,
351 scaling_factor: Fraction,
352}
353
354impl<T: TimeInt> Generic<T> {
355 /// Constructs a new fixed-point `Generic` `Rate` value
356 pub fn new(integer: T, scaling_factor: Fraction) -> Self {
357 Self {
358 integer,
359 scaling_factor,
360 }
361 }
362
363 /// Returns the _integer_ part
364 pub fn integer(&self) -> T {
365 self.integer
366 }
367
368 /// Returns the _scaling factor_ [`Fraction`] part
369 pub fn scaling_factor(&self) -> &Fraction {
370 &self.scaling_factor
371 }
372}
373
374impl<T: TimeInt> Rate for Generic<T> {}
375
376/// Rate-type units
377#[doc(hidden)]
378pub mod units {
379 use super::*;
380 use crate::{
381 fixed_point::{self, FixedPoint},
382 fraction::Fraction,
383 time_int::TimeInt,
384 ConversionError,
385 };
386 use core::{
387 cmp,
388 convert::TryFrom,
389 fmt::{self, Formatter},
390 ops,
391 };
392 #[doc(hidden)]
393 pub use Extensions as _;
394
395 macro_rules! impl_rate {
396 ( $name:ident, ($numer:expr, $denom:expr), $desc:literal ) => {
397 #[doc = $desc]
398 #[derive(Copy, Clone, Eq, Ord, Hash, Debug, Default)]
399 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
400 pub struct $name<T: TimeInt = u32>(pub T);
401
402 impl<T: TimeInt> $name<T> {
403 /// See [Constructing a rate](trait.Rate.html#constructing-a-rate)
404 pub fn new(value: T) -> Self {
405 Self(value)
406 }
407 }
408
409 impl<T: TimeInt> Rate for $name<T> {}
410
411 impl<T: TimeInt> FixedPoint for $name<T> {
412 type T = T;
413 const SCALING_FACTOR: Fraction = Fraction::new($numer, $denom);
414
415 /// See [Constructing a rate](trait.Rate.html#constructing-a-rate)
416 fn new(value: Self::T) -> Self {
417 Self(value)
418 }
419
420 /// See [Get the integer part](trait.Rate.html#get-the-integer-part)
421 fn integer(&self) -> Self::T {
422 self.0
423 }
424 }
425
426 impl<T: TimeInt> fmt::Display for $name<T> {
427 /// See [Formatting](trait.Rate.html#formatting)
428 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
429 fmt::Display::fmt(&self.0, f)
430 }
431 }
432
433 impl<T: TimeInt, Rhs: Rate> ops::Add<Rhs> for $name<T>
434 where
435 Rhs: FixedPoint,
436 Self: TryFrom<Rhs>,
437 {
438 type Output = Self;
439
440 /// See [Add/Sub](trait.Rate.html#addsub)
441 fn add(self, rhs: Rhs) -> Self::Output {
442 <Self as FixedPoint>::add(self, rhs)
443 }
444 }
445
446 impl<T: TimeInt, Rhs: Rate> ops::Sub<Rhs> for $name<T>
447 where
448 Self: TryFrom<Rhs>,
449 Rhs: FixedPoint,
450 {
451 type Output = Self;
452
453 /// See [Add/Sub](trait.Rate.html#addsub)
454 fn sub(self, rhs: Rhs) -> Self::Output {
455 <Self as FixedPoint>::sub(self, rhs)
456 }
457 }
458
459 impl<T: TimeInt> ops::Mul<T> for $name<T> {
460 type Output = Self;
461
462 /// See [Mul/Div](trait.Rate.html#muldiv)
463 fn mul(self, rhs: T) -> Self::Output {
464 <Self as FixedPoint>::mul(self, rhs)
465 }
466 }
467
468 impl<T: TimeInt> ops::Div<T> for $name<T> {
469 type Output = Self;
470
471 /// See [Mul/Div](trait.Rate.html#muldiv)
472 fn div(self, rhs: T) -> Self::Output {
473 <Self as FixedPoint>::div(self, rhs)
474 }
475 }
476
477 impl<T: TimeInt, Rhs: Rate> ops::Rem<Rhs> for $name<T>
478 where
479 Self: TryFrom<Rhs>,
480 Rhs: FixedPoint,
481 {
482 type Output = Self;
483
484 /// See [Remainder](trait.Rate.html#remainder)
485 fn rem(self, rhs: Rhs) -> Self::Output {
486 <Self as FixedPoint>::rem(self, rhs)
487 }
488 }
489
490 impl<SourceInt: TimeInt, DestInt: TimeInt> TryFrom<Generic<SourceInt>>
491 for $name<DestInt>
492 where
493 DestInt: TryFrom<SourceInt>,
494 {
495 type Error = ConversionError;
496
497 /// See [Converting from a `Generic`
498 /// `Rate`](trait.Rate.html#converting-from-a-generic-rate)
499 fn try_from(generic_rate: Generic<SourceInt>) -> Result<Self, Self::Error> {
500 fixed_point::FixedPoint::from_ticks(
501 generic_rate.integer,
502 generic_rate.scaling_factor,
503 )
504 }
505 }
506
507 impl<T: TimeInt> From<$name<T>> for Generic<T> {
508 /// See [Converting to a `Generic`
509 /// `Rate`](trait.Rate.html#converting-to-a-generic-rate)
510 fn from(rate: $name<T>) -> Self {
511 Self::new(rate.integer(), $name::<T>::SCALING_FACTOR)
512 }
513 }
514 };
515 }
516 impl_rate![Mebihertz, (1_048_576, 1), "Hertz × 1,048,576"];
517 impl_rate![Megahertz, (1_000_000, 1), "Hertz × 1,000,000"];
518 impl_rate![Kibihertz, (1_024, 1), "Hertz × 1,024"];
519 impl_rate![Kilohertz, (1_000, 1), "Hertz × 1,000"];
520 impl_rate![Hertz, (1, 1), "Hertz"];
521 impl_rate![Decihertz, (1, 10), "Hertz / 10"];
522 impl_rate![Centihertz, (1, 100), "Hertz / 100"];
523 impl_rate![Millihertz, (1, 1_000), "Hertz / 1000"];
524 impl_rate![Microhertz, (1, 1_000_000), "Hertz / 1,000,000"];
525 impl_rate![
526 MebibytesPerSecond,
527 (1_048_576 * 8, 1),
528 "Bytes/s × 1,048,576"
529 ];
530 impl_rate![
531 MegabytesPerSecond,
532 (1_000_000 * 8, 1),
533 "Bytes/s × 1,000,000"
534 ];
535 impl_rate![KibibytesPerSecond, (1_024 * 8, 1), "Bytes/s × 1,024"];
536 impl_rate![KilobytesPerSecond, (1_000 * 8, 1), "Bytes/s × 1,000"];
537 impl_rate![BytesPerSecond, (8, 1), "Bytes/s"];
538 impl_rate![MebibitsPerSecond, (1_048_576, 1), "Bits/s × 1,048,576"];
539 impl_rate![MegabitsPerSecond, (1_000_000, 1), "Bits/s × 1,000,000"];
540 impl_rate![KibibitsPerSecond, (1_024, 1), "Bits/s × 1,024"];
541 impl_rate![KilobitsPerSecond, (1_000, 1), "Bits/s × 1,000"];
542 impl_rate![BitsPerSecond, (1, 1), "Bits/s"];
543 impl_rate![Mebibaud, (1_048_576, 1), "Baud × 1,048,576"];
544 impl_rate![Megabaud, (1_000_000, 1), "Baud × 1,000,000"];
545 impl_rate![Kibibaud, (1_024, 1), "Baud × 1,024"];
546 impl_rate![Kilobaud, (1_000, 1), "Baud × 1,000"];
547 impl_rate![Baud, (1, 1), "Baud"];
548
549 macro_rules! impl_conversion {
550 ($name:ident) => {
551 impl From<$name<u32>> for $name<u64> {
552 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
553 fn from(source: $name<u32>) -> Self {
554 Self::new(u64::from(source.integer()))
555 }
556 }
557
558 impl TryFrom<$name<u64>> for $name<u32> {
559 type Error = ConversionError;
560
561 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
562 fn try_from(source: $name<u64>) -> Result<Self, Self::Error> {
563 fixed_point::FixedPoint::from_ticks(
564 source.integer(),
565 $name::<u64>::SCALING_FACTOR,
566 )
567 }
568 }
569
570 impl<T: TimeInt, RhsInt: TimeInt> cmp::PartialEq<$name<RhsInt>> for $name<T>
571 where
572 T: TryFrom<RhsInt>,
573 {
574 /// See [Comparisons](trait.Rate.html#comparisons)
575 fn eq(&self, rhs: &$name<RhsInt>) -> bool {
576 match T::try_from(rhs.integer()) {
577 Ok(rhs_value) => self.integer() == rhs_value,
578 Err(_) => false
579 }
580 }
581 }
582
583 impl<T: TimeInt, RhsInt: TimeInt> PartialOrd<$name<RhsInt>> for $name<T>
584 where
585 T: TryFrom<RhsInt>,
586 {
587 /// See [Comparisons](trait.Rate.html#comparisons)
588 fn partial_cmp(&self, rhs: &$name<RhsInt>) -> Option<core::cmp::Ordering> {
589 match T::try_from(rhs.integer()) {
590 Ok(rhs_integer) => Some(self.integer().cmp(&rhs_integer)),
591 Err(_) => Some(core::cmp::Ordering::Less),
592 }
593 }
594 }
595 };
596
597 (once, $big:ident, $small:ident) => {
598 impl<T: TimeInt> From<$small<T>> for $big<T>
599 {
600 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
601 fn from(small: $small<T>) -> Self {
602 if let Ok(v) = fixed_point::FixedPoint::from_ticks(small.integer(), $small::<T>::SCALING_FACTOR) {
603 v
604 } else {
605 panic!("From failed")
606 }
607 }
608 }
609
610 impl From<$small<u32>> for $big<u64>
611 {
612 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
613 fn from(small: $small<u32>) -> Self {
614 if let Ok(v) = fixed_point::FixedPoint::from_ticks(small.integer(), $small::<u32>::SCALING_FACTOR) {
615 v
616 } else {
617 panic!("From failed")
618 }
619 }
620 }
621
622 impl TryFrom<$small<u64>> for $big<u32>
623 {
624 type Error = ConversionError;
625
626 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
627 fn try_from(small: $small<u64>) -> Result<Self, Self::Error> {
628 fixed_point::FixedPoint::from_ticks(
629 small.integer(),
630 $small::<u64>::SCALING_FACTOR,
631 )
632 }
633 }
634
635
636 impl From<$big<u32>> for $small<u64>
637 {
638 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
639 fn from(big: $big<u32>) -> Self {
640 if let Ok(v) = fixed_point::FixedPoint::from_ticks(big.integer(), $big::<u32>::SCALING_FACTOR) {
641 v
642 } else {
643 panic!("From failed")
644 }
645 }
646 }
647
648 impl<T: TimeInt> TryFrom<$big<T>> for $small<T>
649 {
650 type Error = ConversionError;
651
652 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
653 fn try_from(big: $big<T>) -> Result<Self, Self::Error> {
654 fixed_point::FixedPoint::from_ticks(
655 big.integer(),
656 $big::<T>::SCALING_FACTOR,
657 )
658 }
659 }
660
661 impl TryFrom<$big<u64>> for $small<u32>
662 {
663 type Error = ConversionError;
664
665 /// See [Converting between `Rate`s](trait.Rate.html#converting-between-rates)
666 fn try_from(big: $big<u64>) -> Result<Self, Self::Error> {
667 fixed_point::FixedPoint::from_ticks(
668 big.integer(),
669 $big::<u64>::SCALING_FACTOR,
670 )
671 }
672 }
673
674 impl<T: TimeInt, RhsInt: TimeInt> cmp::PartialEq<$small<RhsInt>> for $big<T>
675 where
676 $small<RhsInt>: PartialEq<$big<T>>,
677 {
678 /// See [Comparisons](trait.Rate.html#comparisons)
679 fn eq(&self, rhs: &$small<RhsInt>) -> bool {
680 <$small::<RhsInt> as PartialEq<$big<T>>>::eq(rhs, self)
681 }
682 }
683
684 impl<T: TimeInt, RhsInt: TimeInt> cmp::PartialEq<$big<RhsInt>> for $small<T>
685 where
686 Self: TryFrom<$big<RhsInt>>,
687 {
688 /// See [Comparisons](trait.Rate.html#comparisons)
689 fn eq(&self, rhs: &$big<RhsInt>) -> bool {
690 match Self::try_from(*rhs) {
691 Ok(rhs) => *self == rhs,
692 Err(_) => false
693 }
694 }
695 }
696
697 impl<T: TimeInt, RhsInt: TimeInt> PartialOrd<$small<RhsInt>> for $big<T>
698 where
699 $small<RhsInt>: TryFrom<Self> + Ord,
700 {
701 /// See [Comparisons](trait.Rate.html#comparisons)
702 fn partial_cmp(&self, rhs: &$small<RhsInt>) -> Option<core::cmp::Ordering> {
703 match $small::<RhsInt>::try_from(*self) {
704 Ok(lhs) => Some(lhs.cmp(&rhs)),
705 Err(_) => Some(core::cmp::Ordering::Greater),
706 }
707
708 }
709 }
710
711 impl<T: TimeInt, RhsInt: TimeInt> PartialOrd<$big<RhsInt>> for $small<T>
712 where
713 Self: TryFrom<$big<RhsInt>>,
714 {
715 /// See [Comparisons](trait.Rate.html#comparisons)
716 fn partial_cmp(&self, rhs: &$big<RhsInt>) -> Option<core::cmp::Ordering> {
717 match Self::try_from(*rhs) {
718 Ok(rhs) => Some((*self).cmp(&rhs)),
719 Err(_) => Some(core::cmp::Ordering::Less),
720 }
721 }
722 }
723 };
724 ($big:ident; $($small:ident),+) => {
725 impl_conversion![$big];
726 $(
727 impl_conversion![once, $big, $small];
728 )+
729 };
730 // ($big:ident, $($small:ident),+) => {
731 // $(
732 // impl_from_smaller![once, $big, $small];
733 // )+
734 //
735 // impl_from_smaller![$($small),+];
736 // };
737
738 }
739
740 impl_conversion![Mebihertz; Kibihertz, Hertz];
741 impl_conversion![Kibihertz; Hertz];
742 impl_conversion![Megahertz; Kilohertz, Hertz];
743 impl_conversion![Kilohertz; Hertz];
744 impl_conversion![Hertz];
745 impl_conversion![Decihertz; Hertz];
746 impl_conversion![Centihertz; Hertz];
747 impl_conversion![Millihertz; Hertz];
748 impl_conversion![Microhertz; Hertz];
749
750 // The first arg implements From/TryFrom all following
751 impl_conversion![MebibytesPerSecond; MebibitsPerSecond, KibibytesPerSecond, KibibitsPerSecond, BytesPerSecond, BitsPerSecond];
752 impl_conversion![MebibitsPerSecond; KibibytesPerSecond, KibibitsPerSecond, BytesPerSecond, BitsPerSecond];
753 impl_conversion![KibibytesPerSecond; KibibitsPerSecond, BytesPerSecond, BitsPerSecond];
754 impl_conversion![KibibitsPerSecond; BytesPerSecond, BitsPerSecond];
755
756 impl_conversion![MegabytesPerSecond; MegabitsPerSecond, KilobytesPerSecond, KilobitsPerSecond, BytesPerSecond, BitsPerSecond];
757 impl_conversion![MegabitsPerSecond; KilobytesPerSecond, KilobitsPerSecond, BytesPerSecond, BitsPerSecond ];
758 impl_conversion![KilobytesPerSecond; KilobitsPerSecond, BytesPerSecond, BitsPerSecond ];
759 impl_conversion![KilobitsPerSecond; BytesPerSecond, BitsPerSecond];
760
761 impl_conversion![BytesPerSecond; BitsPerSecond];
762 impl_conversion![BitsPerSecond];
763
764 impl_conversion![Mebibaud; Kibibaud, Baud];
765 impl_conversion![Kibibaud; Baud];
766 impl_conversion![Megabaud; Kilobaud, Baud];
767 impl_conversion![Kilobaud; Baud];
768 impl_conversion![Baud];
769
770 /// Create rate-based extensions from primitive numeric types.
771 ///
772 /// ```rust
773 /// # use embedded_time::{rate::*};
774 /// assert_eq!(5.MiHz(), Mebihertz(5_u32));
775 /// assert_eq!(5.MHz(), Megahertz(5_u32));
776 /// assert_eq!(5.KiHz(), Kibihertz(5_u32));
777 /// assert_eq!(5.kHz(), Kilohertz(5_u32));
778 /// assert_eq!(5.Hz(), Hertz(5_u32));
779 /// assert_eq!(5.MiBps(), MebibytesPerSecond(5_u32));
780 /// assert_eq!(5.MBps(), MegabytesPerSecond(5_u32));
781 /// assert_eq!(5.KiBps(), KibibytesPerSecond(5_u32));
782 /// assert_eq!(5.kBps(), KilobytesPerSecond(5_u32));
783 /// assert_eq!(5.Bps(), BytesPerSecond(5_u32));
784 /// assert_eq!(5.Mibps(), MebibitsPerSecond(5_u32));
785 /// assert_eq!(5.Mbps(), MegabitsPerSecond(5_u32));
786 /// assert_eq!(5.Kibps(), KibibitsPerSecond(5_u32));
787 /// assert_eq!(5.kbps(), KilobitsPerSecond(5_u32));
788 /// assert_eq!(5.bps(), BitsPerSecond(5_u32));
789 /// assert_eq!(5.MiBd(), Mebibaud(5_u32));
790 /// assert_eq!(5.MBd(), Megabaud(5_u32));
791 /// assert_eq!(5.KiBd(), Kibibaud(5_u32));
792 /// assert_eq!(5.kBd(), Kilobaud(5_u32));
793 /// assert_eq!(5.Bd(), Baud(5_u32));
794 /// ```
795 #[allow(non_snake_case)]
796 pub trait Extensions: TimeInt {
797 /// mebihertz
798 fn MiHz(self) -> Mebihertz<Self> {
799 Mebihertz::new(self)
800 }
801
802 /// megahertz
803 fn MHz(self) -> Megahertz<Self> {
804 Megahertz::new(self)
805 }
806
807 /// kibihertz
808 fn KiHz(self) -> Kibihertz<Self> {
809 Kibihertz::new(self)
810 }
811
812 /// kilohertz
813 fn kHz(self) -> Kilohertz<Self> {
814 Kilohertz::new(self)
815 }
816
817 /// hertz
818 fn Hz(self) -> Hertz<Self> {
819 Hertz::new(self)
820 }
821
822 /// mebibytes per second
823 fn MiBps(self) -> MebibytesPerSecond<Self> {
824 MebibytesPerSecond::new(self)
825 }
826
827 /// megabytes per second
828 fn MBps(self) -> MegabytesPerSecond<Self> {
829 MegabytesPerSecond::new(self)
830 }
831
832 /// kibibytes per second
833 fn KiBps(self) -> KibibytesPerSecond<Self> {
834 KibibytesPerSecond::new(self)
835 }
836
837 /// kiloBytes per second
838 fn kBps(self) -> KilobytesPerSecond<Self> {
839 KilobytesPerSecond::new(self)
840 }
841
842 /// bytes per second
843 fn Bps(self) -> BytesPerSecond<Self> {
844 BytesPerSecond::new(self)
845 }
846
847 /// mebibits per second
848 fn Mibps(self) -> MebibitsPerSecond<Self> {
849 MebibitsPerSecond::new(self)
850 }
851
852 /// megabits per second
853 fn Mbps(self) -> MegabitsPerSecond<Self> {
854 MegabitsPerSecond::new(self)
855 }
856
857 /// kibibits per second
858 fn Kibps(self) -> KibibitsPerSecond<Self> {
859 KibibitsPerSecond::new(self)
860 }
861
862 /// kilobits per second
863 fn kbps(self) -> KilobitsPerSecond<Self> {
864 KilobitsPerSecond::new(self)
865 }
866
867 /// bits per second
868 fn bps(self) -> BitsPerSecond<Self> {
869 BitsPerSecond::new(self)
870 }
871
872 /// mebibaud
873 fn MiBd(self) -> Mebibaud<Self> {
874 Mebibaud::new(self)
875 }
876
877 /// megabaud
878 fn MBd(self) -> Megabaud<Self> {
879 Megabaud::new(self)
880 }
881
882 /// kibibaud
883 fn KiBd(self) -> Kibibaud<Self> {
884 Kibibaud::new(self)
885 }
886
887 /// kilobaud
888 fn kBd(self) -> Kilobaud<Self> {
889 Kilobaud::new(self)
890 }
891
892 /// baud
893 fn Bd(self) -> Baud<Self> {
894 Baud::new(self)
895 }
896 }
897
898 impl Extensions for u32 {}
899}
900
901#[cfg(test)]
902mod tests {}