LCOV - differential code coverage report
Current view: top level - libs/utils/src - serde_percent.rs (source / functions) Coverage Total Hit UBC CBC
Current: f6946e90941b557c917ac98cd5a7e9506d180f3e.info Lines: 98.4 % 64 63 1 63
Current Date: 2023-10-19 02:04:12 Functions: 50.0 % 56 28 28 28
Baseline: c8637f37369098875162f194f92736355783b050.info
Baseline Date: 2023-10-18 20:25:20

           TLA  Line data    Source code
       1                 : //! A serde::Deserialize type for percentages.
       2                 : //!
       3                 : //! See [`Percent`] for details.
       4                 : 
       5                 : use serde::{Deserialize, Serialize};
       6                 : 
       7                 : /// If the value is not an integer between 0 and 100,
       8                 : /// deserialization fails with a descriptive error.
       9 CBC          11 : #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
      10                 : #[serde(transparent)]
      11                 : pub struct Percent(#[serde(deserialize_with = "deserialize_pct_0_to_100")] u8);
      12                 : 
      13                 : impl Percent {
      14               2 :     pub const fn new(pct: u8) -> Option<Self> {
      15               2 :         if pct <= 100 {
      16               2 :             Some(Percent(pct))
      17                 :         } else {
      18 UBC           0 :             None
      19                 :         }
      20 CBC           2 :     }
      21                 : 
      22              53 :     pub fn get(&self) -> u8 {
      23              53 :         self.0
      24              53 :     }
      25                 : }
      26                 : 
      27              11 : fn deserialize_pct_0_to_100<'de, D>(deserializer: D) -> Result<u8, D::Error>
      28              11 : where
      29              11 :     D: serde::de::Deserializer<'de>,
      30              11 : {
      31              11 :     let v: u8 = serde::de::Deserialize::deserialize(deserializer)?;
      32               7 :     if v > 100 {
      33               1 :         return Err(serde::de::Error::custom(
      34               1 :             "must be an integer between 0 and 100",
      35               1 :         ));
      36               6 :     }
      37               6 :     Ok(v)
      38              11 : }
      39                 : 
      40                 : #[cfg(test)]
      41                 : mod tests {
      42                 :     use super::Percent;
      43                 : 
      44              26 :     #[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq, Eq)]
      45                 :     struct Foo {
      46                 :         bar: Percent,
      47                 :     }
      48                 : 
      49               1 :     #[test]
      50               1 :     fn basics() {
      51               1 :         let input = r#"{ "bar": 50 }"#;
      52               1 :         let foo: Foo = serde_json::from_str(input).unwrap();
      53               1 :         assert_eq!(foo.bar.get(), 50);
      54               1 :     }
      55               1 :     #[test]
      56               1 :     fn null_handling() {
      57               1 :         let input = r#"{ "bar": null }"#;
      58               1 :         let res: Result<Foo, _> = serde_json::from_str(input);
      59               1 :         assert!(res.is_err());
      60               1 :     }
      61               1 :     #[test]
      62               1 :     fn zero() {
      63               1 :         let input = r#"{ "bar": 0 }"#;
      64               1 :         let foo: Foo = serde_json::from_str(input).unwrap();
      65               1 :         assert_eq!(foo.bar.get(), 0);
      66               1 :     }
      67               1 :     #[test]
      68               1 :     fn out_of_range_above() {
      69               1 :         let input = r#"{ "bar": 101 }"#;
      70               1 :         let res: Result<Foo, _> = serde_json::from_str(input);
      71               1 :         assert!(res.is_err());
      72               1 :     }
      73               1 :     #[test]
      74               1 :     fn out_of_range_below() {
      75               1 :         let input = r#"{ "bar": -1 }"#;
      76               1 :         let res: Result<Foo, _> = serde_json::from_str(input);
      77               1 :         assert!(res.is_err());
      78               1 :     }
      79               1 :     #[test]
      80               1 :     fn float() {
      81               1 :         let input = r#"{ "bar": 50.5 }"#;
      82               1 :         let res: Result<Foo, _> = serde_json::from_str(input);
      83               1 :         assert!(res.is_err());
      84               1 :     }
      85               1 :     #[test]
      86               1 :     fn string() {
      87               1 :         let input = r#"{ "bar": "50 %" }"#;
      88               1 :         let res: Result<Foo, _> = serde_json::from_str(input);
      89               1 :         assert!(res.is_err());
      90               1 :     }
      91                 : }
        

Generated by: LCOV version 2.1-beta