LCOV - code coverage report
Current view: top level - proxy/src - url.rs (source / functions) Coverage Total Hit
Test: 050dd70dd490b28fffe527eae9fb8a1222b5c59c.info Lines: 83.3 % 36 30
Test Date: 2024-06-25 21:28:46 Functions: 71.4 % 7 5

            Line data    Source code
       1              : use anyhow::bail;
       2              : 
       3              : /// A [url](url::Url) type with additional guarantees.
       4              : #[repr(transparent)]
       5              : #[derive(Debug, Clone, PartialEq, Eq)]
       6              : pub struct ApiUrl(url::Url);
       7              : 
       8              : impl ApiUrl {
       9              :     /// Consume the wrapper and return inner [url](url::Url).
      10            6 :     pub fn into_inner(self) -> url::Url {
      11            6 :         self.0
      12            6 :     }
      13              : 
      14              :     /// See [`url::Url::path_segments_mut`].
      15            6 :     pub fn path_segments_mut(&mut self) -> url::PathSegmentsMut {
      16            6 :         // We've already verified that it works during construction.
      17            6 :         self.0.path_segments_mut().expect("bad API url")
      18            6 :     }
      19              : }
      20              : 
      21              : /// This instance imposes additional requirements on the url.
      22              : impl std::str::FromStr for ApiUrl {
      23              :     type Err = anyhow::Error;
      24              : 
      25            8 :     fn from_str(s: &str) -> anyhow::Result<Self> {
      26            8 :         let mut url: url::Url = s.parse()?;
      27              : 
      28              :         // Make sure that we can build upon this URL.
      29            8 :         if url.path_segments_mut().is_err() {
      30            2 :             bail!("bad API url provided");
      31            6 :         }
      32            6 : 
      33            6 :         Ok(Self(url))
      34            8 :     }
      35              : }
      36              : 
      37              : /// This instance is safe because it doesn't allow us to modify the object.
      38              : impl std::ops::Deref for ApiUrl {
      39              :     type Target = url::Url;
      40              : 
      41            0 :     fn deref(&self) -> &Self::Target {
      42            0 :         &self.0
      43            0 :     }
      44              : }
      45              : 
      46              : impl std::fmt::Display for ApiUrl {
      47            0 :     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
      48            0 :         self.0.fmt(f)
      49            0 :     }
      50              : }
      51              : 
      52              : #[cfg(test)]
      53              : mod tests {
      54              :     use super::*;
      55              : 
      56              :     #[test]
      57            2 :     fn bad_url() {
      58            2 :         let url = "test:foobar";
      59            2 :         url.parse::<url::Url>().expect("unexpected parsing failure");
      60            2 :         let _ = url.parse::<ApiUrl>().expect_err("should not parse");
      61            2 :     }
      62              : 
      63              :     #[test]
      64            2 :     fn good_url() {
      65            2 :         let url = "test://foobar";
      66            2 :         let mut a = url.parse::<url::Url>().expect("unexpected parsing failure");
      67            2 :         let mut b = url.parse::<ApiUrl>().expect("unexpected parsing failure");
      68            2 : 
      69            2 :         a.path_segments_mut().unwrap().push("method");
      70            2 :         b.path_segments_mut().push("method");
      71            2 : 
      72            2 :         assert_eq!(a, b.into_inner());
      73            2 :     }
      74              : }
        

Generated by: LCOV version 2.1-beta