qiniu-http-client 0.2.4

Qiniu HTTP Client for Rust
Documentation
use super::{
    super::{Endpoint, EndpointParseError},
    Region,
};
use serde::Deserialize;
use std::{convert::TryFrom, fmt::Debug, time::Duration};

#[derive(Debug, Clone, Deserialize)]
pub(super) struct ResponseBody {
    #[serde(alias = "regions")]
    hosts: Vec<RegionResponseBody>,
}

impl ResponseBody {
    pub(super) fn into_hosts(self) -> Vec<RegionResponseBody> {
        self.hosts
    }
}

#[derive(Debug, Clone, Deserialize)]
pub(super) struct RegionResponseBody {
    #[serde(alias = "id")]
    region: Box<str>,
    #[serde(default = "default_ttl")]
    ttl: u64,
    io: DomainsResponseBody,
    up: DomainsResponseBody,
    uc: DomainsResponseBody,
    rs: DomainsResponseBody,
    rsf: DomainsResponseBody,
    api: DomainsResponseBody,
    s3: DomainsResponseBody,
}

impl RegionResponseBody {
    pub(super) fn lifetime(&self) -> Duration {
        Duration::from_secs(self.ttl)
    }
}

fn default_ttl() -> u64 {
    86400
}

#[derive(Debug, Clone, Deserialize)]
struct DomainsResponseBody {
    #[serde(rename = "domains")]
    preferred: Box<[Box<str>]>,

    #[serde(rename = "old")]
    alternative: Option<Box<[Box<str>]>>,

    #[serde(rename = "region_alias")]
    s3_region_id: Option<Box<str>>,
}

impl TryFrom<RegionResponseBody> for Region {
    type Error = EndpointParseError;
    fn try_from(body: RegionResponseBody) -> Result<Self, Self::Error> {
        let RegionResponseBody {
            region,
            io,
            up,
            uc,
            rs,
            rsf,
            api,
            s3,
            ..
        } = body;
        let mut builder = Self::builder(region);

        macro_rules! push_to_builder {
            ($service_name:expr, $add_to_preferred_endpoint:ident, $add_to_alternative_endpoint:ident) => {
                for preferred_domain in $service_name.preferred.iter() {
                    let endpoint: Endpoint = preferred_domain.as_ref().parse()?;
                    builder.$add_to_preferred_endpoint(endpoint);
                }
                if let Some(alternative_domains) = &$service_name.alternative {
                    for alternative_domain in alternative_domains.iter() {
                        let endpoint: Endpoint = alternative_domain.as_ref().parse()?;
                        builder.$add_to_alternative_endpoint(endpoint);
                    }
                }
            };
        }
        push_to_builder!(io, add_io_preferred_endpoint, add_io_alternative_endpoint);
        push_to_builder!(up, add_up_preferred_endpoint, add_up_alternative_endpoint);
        push_to_builder!(uc, add_uc_preferred_endpoint, add_uc_alternative_endpoint);
        push_to_builder!(rs, add_rs_preferred_endpoint, add_rs_alternative_endpoint);
        push_to_builder!(rsf, add_rsf_preferred_endpoint, add_rsf_alternative_endpoint);
        push_to_builder!(api, add_api_preferred_endpoint, add_api_alternative_endpoint);
        push_to_builder!(s3, add_s3_preferred_endpoint, add_s3_alternative_endpoint);
        if let Some(s3_region_id) = s3.s3_region_id {
            builder.s3_region_id(s3_region_id);
        }

        Ok(builder.build())
    }
}