rational_extensions

Extends num_rational::Ratio<T>.
git clone https://git.philomathiclife.com/repos/rational_extensions
Log | Files | Refs | README

serde.rs (2103B)


      1 /// Unit tests.
      2 #[cfg(test)]
      3 mod tests;
      4 use crate::{Ratio, try_from_str};
      5 use core::{
      6     fmt::{self, Formatter},
      7     marker::PhantomData,
      8     ops::Mul,
      9     str::FromStr,
     10 };
     11 use num_integer::Integer;
     12 use num_traits::Pow;
     13 use serde::de::{self, Deserialize, Deserializer, Unexpected, Visitor};
     14 /// Wrapper around a `num_rational::Ratio` that
     15 /// deserializes a JSON string representing a rational number in
     16 /// fractional or decimal notation to a Ratio&lt;T&gt;.
     17 #[derive(Clone, Copy, Debug)]
     18 pub struct Rational<T>(pub Ratio<T>);
     19 impl<'de, T> Deserialize<'de> for Rational<T>
     20 where
     21     T: Clone
     22         + From<u8>
     23         + FromStr
     24         + Integer
     25         + for<'a> Mul<&'a T, Output = T>
     26         + Pow<usize, Output = T>,
     27 {
     28     #[inline]
     29     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     30     where
     31         D: Deserializer<'de>,
     32     {
     33         /// Visitor used to deserialize a JSON string into a Rational.
     34         struct RationalVisitor<T> {
     35             /// Does not own nor drop a `T`.
     36             _x: PhantomData<fn() -> T>,
     37         }
     38         impl<T> Visitor<'_> for RationalVisitor<T>
     39         where
     40             T: Clone
     41                 + From<u8>
     42                 + FromStr
     43                 + Integer
     44                 + for<'a> Mul<&'a T, Output = T>
     45                 + Pow<usize, Output = T>,
     46         {
     47             type Value = Rational<T>;
     48             fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
     49                 formatter.write_str("struct Rational")
     50             }
     51             fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
     52             where
     53                 E: de::Error,
     54             {
     55                 try_from_str(v).map_or_else(
     56                     |_| {
     57                         Err(E::invalid_value(
     58                             Unexpected::Str(v),
     59                             &"a rational number in fraction or decimal notation",
     60                         ))
     61                     },
     62                     |val| Ok(Rational(val)),
     63                 )
     64             }
     65         }
     66         deserializer.deserialize_str(RationalVisitor { _x: PhantomData })
     67     }
     68 }