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 {}