use super::Client;
use super::sign_v4::HTTPVerb;
use super::utils::{get_request_header, parse_xml_response};
use crate::oss::Error;
use bon::Builder;
use serde::{Deserialize, Serialize};
use serde_with::{DisplayFromStr, serde_as};
use std::collections::HashMap;
use url::Url;
#[serde_as]
#[serde_with::skip_serializing_none]
#[derive(Builder, Serialize)]
#[serde(rename_all = "kebab-case")]
pub struct ListBuckets<'a> {
#[builder(start_fn)]
#[serde(skip_serializing)]
pub(crate) client: &'a Client,
#[serde(skip_serializing)]
pub(crate) x_oss_resource_group_id: Option<&'a str>,
pub(crate) prefix: Option<&'a str>,
pub(crate) marker: Option<&'a str>,
#[serde_as(as = "Option<DisplayFromStr>")]
pub(crate) max_keys: Option<u16>,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct ListAllMyBucketsResult {
pub prefix: Option<String>,
pub marker: Option<String>,
pub max_keys: Option<u32>,
pub is_truncated: Option<bool>,
pub next_marker: Option<String>,
pub owner: Owner,
#[serde(deserialize_with = "unwrap_buckets")]
pub buckets: Vec<Bucket>,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Buckets {
#[serde(default)]
bucket: Vec<Bucket>,
}
fn unwrap_buckets<'de, D>(deserializer: D) -> Result<Vec<Bucket>, D::Error>
where
D: serde::Deserializer<'de>,
{
let helper = Buckets::deserialize(deserializer)?;
Ok(helper.bucket)
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct Owner {
#[serde(rename = "ID")]
pub id: String,
pub display_name: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct Bucket {
pub name: String,
pub creation_date: String,
pub location: String,
pub extranet_endpoint: String,
pub intranet_endpoint: String,
pub region: String,
pub storage_class: String,
pub resource_group_id: Option<String>,
}
impl ListBuckets<'_> {
pub async fn send(&self) -> Result<ListAllMyBucketsResult, Error> {
let query_map: HashMap<String, String> =
serde_json::from_value(serde_json::to_value(self).unwrap()).unwrap();
let client = self.client;
let request_url =
Url::parse_with_params(&format!("https://{}", client.endpoint), query_map).unwrap();
let mut request_header_map = HashMap::new();
if let Some(s) = self.x_oss_resource_group_id {
request_header_map.insert("x-oss-resource-group-id".to_owned(), s.to_owned());
}
let creds = client.credentials_provider.load().await?;
if let Some(token) = &creds.sts_security_token {
request_header_map.insert("x-oss-security-token".to_string(), token.clone());
}
let header_map = get_request_header(
&creds.access_key_id,
&creds.access_key_secret,
request_header_map,
&request_url,
HTTPVerb::Get,
&client.region,
None,
);
let resp = client
.http_client
.get(request_url)
.headers(header_map)
.send()
.await?;
let res = parse_xml_response(resp).await?;
Ok(res)
}
}
impl Client {
pub fn list_buckets(&self) -> ListBucketsBuilder<'_> {
ListBuckets::builder(self)
}
}