eio_okta_api/traits/
service.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
use std::ops::Deref;

use http::uri::{Authority, Scheme};
use iri_string::types::{UriAbsoluteStr, UriAbsoluteString};

#[derive(Debug, thiserror::Error)]
pub enum Error {
  #[error("http: {0}")]
  Http(#[from] http::Error),
  #[error("endpoint: {0}")]
  Endpoint(#[from] super::endpoint::Error),
  #[error("validate: {0}")]
  Validate(#[from] iri_string::validate::Error),
}

pub trait Service: Sized {
  fn scheme(&self) -> &Scheme {
    &Scheme::HTTPS
  }

  fn authority(&self) -> &Authority;

  fn uri(&self) -> Result<ServiceURI, Error> {
    ServiceURI::new(self)
  }
}

#[derive(Debug, Clone)]
pub struct ServiceURI(UriAbsoluteString);

impl Deref for ServiceURI {
  type Target = UriAbsoluteStr;
  fn deref(&self) -> &Self::Target {
    self.0.deref()
  }
}

impl ServiceURI {
  fn new<T>(service: &T) -> Result<Self, Error>
  where
    T: Service,
  {
    let mut uri = iri_string::build::Builder::new();

    uri.scheme(service.scheme().as_str());
    uri.host(service.authority().host());
    if let Some(port) = service.authority().port_u16() {
      uri.port(port)
    }
    uri.path("");
    uri.unset_fragment();
    uri.unset_query();
    uri.unset_userinfo();
    uri.normalize();

    Ok(Self(uri.build::<UriAbsoluteStr>()?.into()))
  }
}