use std::future::Future;
use http::Method;
use serde::{Deserialize, Serialize};
use crate::body::NoneBody;
use crate::error::Result;
use crate::response::BodyResponseProcessor;
use crate::{Client, Ops, Prepared, Request};
#[derive(Debug, Clone, Default, Serialize)]
pub struct DescribeRegionsParams {
#[serde(rename = "regions", skip_serializing_if = "Option::is_none")]
pub region: Option<String>,
}
impl DescribeRegionsParams {
pub fn all() -> Self {
Self::default()
}
pub fn region(region: impl Into<String>) -> Self {
Self {
region: Some(region.into()),
}
}
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "PascalCase")]
pub struct RegionInfo {
pub region: String,
pub internet_endpoint: String,
pub internal_endpoint: String,
pub accelerate_endpoint: String,
}
#[derive(Debug, Clone, Default, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct RegionInfoList {
#[serde(default, rename = "RegionInfo")]
pub regions: Vec<RegionInfo>,
}
pub struct DescribeRegions {
pub params: DescribeRegionsParams,
}
impl Ops for DescribeRegions {
type Response = BodyResponseProcessor<RegionInfoList>;
type Body = NoneBody;
type Query = DescribeRegionsParams;
const USE_BUCKET: bool = false;
fn prepare(self) -> Result<Prepared<DescribeRegionsParams>> {
Ok(Prepared {
method: Method::GET,
query: Some(self.params),
..Default::default()
})
}
}
pub trait DescribeRegionsOps {
fn describe_regions(&self) -> impl Future<Output = Result<RegionInfoList>>;
fn describe_region(&self, region: impl Into<String>) -> impl Future<Output = Result<RegionInfoList>>;
}
impl DescribeRegionsOps for Client {
async fn describe_regions(&self) -> Result<RegionInfoList> {
let ops = DescribeRegions {
params: DescribeRegionsParams::all(),
};
self.request(ops).await
}
async fn describe_region(&self, region: impl Into<String>) -> Result<RegionInfoList> {
let ops = DescribeRegions {
params: DescribeRegionsParams::region(region),
};
self.request(ops).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn describe_regions_params_serialize_all() {
let q = crate::ser::to_string(&DescribeRegionsParams::all()).unwrap();
assert_eq!(q, "");
}
#[test]
fn describe_regions_params_serialize_single() {
let q = crate::ser::to_string(&DescribeRegionsParams::region("oss-cn-hangzhou")).unwrap();
assert_eq!(q, "regions=oss-cn-hangzhou");
}
#[test]
fn describe_regions_prepared_method() {
let prepared = DescribeRegions {
params: DescribeRegionsParams::all(),
}
.prepare()
.unwrap();
assert_eq!(prepared.method, Method::GET);
assert!(prepared.key.is_none());
}
#[test]
fn describe_regions_use_bucket_false() {
const _: () = assert!(!<DescribeRegions as Ops>::USE_BUCKET);
}
#[test]
fn region_info_list_parses_single_region() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<RegionInfoList>
<RegionInfo>
<Region>oss-cn-hangzhou</Region>
<InternetEndpoint>oss-cn-hangzhou.aliyuncs.com</InternetEndpoint>
<InternalEndpoint>oss-cn-hangzhou-internal.aliyuncs.com</InternalEndpoint>
<AccelerateEndpoint>oss-accelerate.aliyuncs.com</AccelerateEndpoint>
</RegionInfo>
</RegionInfoList>"#;
let parsed: RegionInfoList = quick_xml::de::from_str(xml).unwrap();
assert_eq!(parsed.regions.len(), 1);
assert_eq!(parsed.regions[0].region, "oss-cn-hangzhou");
assert_eq!(parsed.regions[0].internet_endpoint, "oss-cn-hangzhou.aliyuncs.com");
}
#[test]
fn region_info_list_parses_multiple_regions() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<RegionInfoList>
<RegionInfo>
<Region>oss-cn-hangzhou</Region>
<InternetEndpoint>oss-cn-hangzhou.aliyuncs.com</InternetEndpoint>
<InternalEndpoint>oss-cn-hangzhou-internal.aliyuncs.com</InternalEndpoint>
<AccelerateEndpoint>oss-accelerate.aliyuncs.com</AccelerateEndpoint>
</RegionInfo>
<RegionInfo>
<Region>oss-cn-shanghai</Region>
<InternetEndpoint>oss-cn-shanghai.aliyuncs.com</InternetEndpoint>
<InternalEndpoint>oss-cn-shanghai-internal.aliyuncs.com</InternalEndpoint>
<AccelerateEndpoint>oss-accelerate.aliyuncs.com</AccelerateEndpoint>
</RegionInfo>
</RegionInfoList>"#;
let parsed: RegionInfoList = quick_xml::de::from_str(xml).unwrap();
assert_eq!(parsed.regions.len(), 2);
assert_eq!(parsed.regions[1].region, "oss-cn-shanghai");
}
#[test]
fn region_info_list_parses_empty() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<RegionInfoList></RegionInfoList>"#;
let parsed: RegionInfoList = quick_xml::de::from_str(xml).unwrap();
assert_eq!(parsed.regions.len(), 0);
}
}