use serde::Deserialize;
use ve_tos_generic::{AclHeader, RequestInfo};
use crate::common::{Meta, Owner, RequestInfo};
use crate::constant::{HEADER_AZ_REDUNDANCY, HEADER_BUCKET_REGION, HEADER_LOCATION, HEADER_PROJECT_NAME, HEADER_STORAGE_CLASS};
use crate::enumeration::HttpMethodType::{HttpMethodDelete, HttpMethodGet, HttpMethodHead};
use crate::internal::{get_header_value_str, InputDescriptor, map_insert, set_acl_header};
use super::enumeration::{ACLType, AzRedundancyType, HttpMethodType::HttpMethodPut, StorageClassType};
use super::error::TosError;
use super::http::{HttpRequest, HttpResponse};
use super::internal::{get_header_value, InputTranslator, OutputParser, parse_json};
pub trait BucketAPI {
fn create_bucket(&self, input: &CreateBucketInput) -> Result<CreateBucketOutput, TosError>;
fn head_bucket(&self, input: &HeadBucketInput) -> Result<HeadBucketOutput, TosError>;
fn delete_bucket(&self, input: &DeleteBucketInput) -> Result<DeleteBucketOutput, TosError>;
fn list_buckets(&self, input: &ListBucketsInput) -> Result<ListBucketsOutput, TosError>;
}
#[derive(Debug, Clone, PartialEq, Default, AclHeader)]
#[enable_grant_write]
pub struct CreateBucketInput {
pub(crate) bucket: String,
pub(crate) acl: Option<ACLType>,
pub(crate) grant_full_control: String,
pub(crate) grant_read: String,
pub(crate) grant_read_acp: String,
pub(crate) grant_write: String,
pub(crate) grant_write_acp: String,
pub(crate) storage_class: Option<StorageClassType>,
pub(crate) az_redundancy: Option<AzRedundancyType>,
}
impl CreateBucketInput {
pub fn new(bucket: impl Into<String>) -> Self {
let mut input = Self::default();
input.bucket = bucket.into();
input
}
pub fn bucket(&self) -> &str {
&self.bucket
}
pub fn storage_class(&self) -> &Option<StorageClassType> {
&self.storage_class
}
pub fn az_redundancy(&self) -> &Option<AzRedundancyType> {
&self.az_redundancy
}
pub fn set_bucket(&mut self, bucket: impl Into<String>) {
self.bucket = bucket.into();
}
pub fn set_storage_class(&mut self, storage_class: impl Into<StorageClassType>) {
self.storage_class = Some(storage_class.into());
}
pub fn set_az_redundancy(&mut self, az_redundancy: impl Into<AzRedundancyType>) {
self.az_redundancy = Some(az_redundancy.into());
}
}
impl InputDescriptor for CreateBucketInput {
fn operation(&self) -> &str {
"CreateBucket"
}
fn bucket(&self) -> Result<&str, TosError> {
Ok(&self.bucket)
}
}
impl<B> InputTranslator<B> for CreateBucketInput {
fn trans(&self) -> Result<HttpRequest<B>, TosError> {
let mut request = self.trans_bucket()?;
request.method = HttpMethodPut;
let header = &mut request.header;
set_acl_header(header, self);
if let Some(x) = &self.storage_class {
header.insert(HEADER_STORAGE_CLASS, x.as_str().to_string());
}
if let Some(x) = &self.az_redundancy {
header.insert(HEADER_AZ_REDUNDANCY, x.as_str().to_string());
}
Ok(request)
}
}
#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
pub struct CreateBucketOutput {
pub(crate) request_info: RequestInfo,
pub(crate) location: String,
}
impl CreateBucketOutput {
pub fn location(&self) -> &str {
&self.location
}
}
impl OutputParser for CreateBucketOutput {
fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
let location = get_header_value(response.headers(), HEADER_LOCATION);
Ok(Self { request_info, location })
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct HeadBucketInput {
pub(crate) bucket: String,
}
impl HeadBucketInput {
pub fn new(bucket: impl Into<String>) -> Self {
let mut input = Self::default();
input.bucket = bucket.into();
input
}
pub fn bucket(&self) -> &str {
&self.bucket
}
pub fn set_bucket(&mut self, bucket: impl Into<String>) {
self.bucket = bucket.into();
}
}
impl InputDescriptor for HeadBucketInput {
fn operation(&self) -> &str {
"HeadBucket"
}
fn bucket(&self) -> Result<&str, TosError> {
Ok(&self.bucket)
}
}
impl<B> InputTranslator<B> for HeadBucketInput {
fn trans(&self) -> Result<HttpRequest<B>, TosError> {
let mut request = self.trans_bucket()?;
request.method = HttpMethodHead;
Ok(request)
}
}
#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
pub struct HeadBucketOutput {
pub(crate) request_info: RequestInfo,
pub(crate) region: String,
pub(crate) storage_class: Option<StorageClassType>,
pub(crate) az_redundancy: Option<AzRedundancyType>,
pub(crate) project_name: String,
}
impl HeadBucketOutput {
pub fn region(&self) -> &str {
&self.region
}
pub fn storage_class(&self) -> &Option<StorageClassType> {
&self.storage_class
}
pub fn az_redundancy(&self) -> &Option<AzRedundancyType> {
&self.az_redundancy
}
pub fn project_name(&self) -> &str {
&self.project_name
}
}
impl OutputParser for HeadBucketOutput {
fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
let region = get_header_value(response.headers(), HEADER_BUCKET_REGION);
let storage_class = StorageClassType::from(get_header_value_str(response.headers(), HEADER_STORAGE_CLASS));
let az_redundancy = AzRedundancyType::from(get_header_value_str(response.headers(), HEADER_AZ_REDUNDANCY));
let project_name = get_header_value(response.headers(), HEADER_PROJECT_NAME);
Ok(Self { request_info, region, storage_class, az_redundancy, project_name })
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DeleteBucketInput {
pub(crate) bucket: String,
}
impl DeleteBucketInput {
pub fn new(bucket: impl Into<String>) -> Self {
let mut input = Self::default();
input.bucket = bucket.into();
input
}
pub fn bucket(&self) -> &str {
&self.bucket
}
pub fn set_bucket(&mut self, bucket: impl Into<String>) {
self.bucket = bucket.into();
}
}
impl InputDescriptor for DeleteBucketInput {
fn operation(&self) -> &str {
"DeleteBucket"
}
fn bucket(&self) -> Result<&str, TosError> {
Ok(&self.bucket)
}
}
impl<B> InputTranslator<B> for DeleteBucketInput {
fn trans(&self) -> Result<HttpRequest<B>, TosError> {
let mut request = self.trans_bucket()?;
request.method = HttpMethodDelete;
Ok(request)
}
}
#[derive(Debug, Clone, PartialEq, Default, RequestInfo)]
pub struct DeleteBucketOutput {
pub(crate) request_info: RequestInfo,
}
impl OutputParser for DeleteBucketOutput {
fn parse_by_ref<B>(_: &HttpRequest<B>, _: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
Ok(Self { request_info })
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct ListBucketsInput {
pub(crate) project_name: String,
}
impl ListBucketsInput {
pub fn new() -> Self {
Self::default()
}
pub fn project_name(&self) -> &str {
&self.project_name
}
pub fn set_project_name(&mut self, project_name: impl Into<String>) {
self.project_name = project_name.into();
}
}
impl InputDescriptor for ListBucketsInput {
fn operation(&self) -> &str {
"ListBuckets"
}
fn bucket(&self) -> Result<&str, TosError> {
Err(TosError::client_error("unsupported"))
}
}
impl<B> InputTranslator<B> for ListBucketsInput {
fn trans(&self) -> Result<HttpRequest<B>, TosError> {
let mut request = HttpRequest::default();
request.operation = self.operation();
request.method = HttpMethodGet;
map_insert(&mut request.header, HEADER_PROJECT_NAME, &self.project_name);
Ok(request)
}
}
#[derive(Debug, Clone, PartialEq, Default, RequestInfo, Deserialize)]
pub struct ListBucketsOutput {
#[serde(skip)]
pub(crate) request_info: RequestInfo,
#[serde(default)]
#[serde(rename = "Buckets")]
pub(crate) buckets: Vec<ListedBucket>,
#[serde(default)]
#[serde(rename = "Owner")]
pub(crate) owner: Owner,
}
#[derive(Debug, Clone, PartialEq, Default, Deserialize)]
pub struct ListedBucket {
#[serde(default)]
#[serde(rename = "CreationDate")]
pub(crate) creation_date: String,
#[serde(default)]
#[serde(rename = "Name")]
pub(crate) name: String,
#[serde(default)]
#[serde(rename = "Location")]
pub(crate) location: String,
#[serde(default)]
#[serde(rename = "ExtranetEndpoint")]
pub(crate) extranet_endpoint: String,
#[serde(default)]
#[serde(rename = "IntranetEndpoint")]
pub(crate) intranet_endpoint: String,
#[serde(default)]
#[serde(rename = "ProjectName")]
pub(crate) project_name: String,
}
impl ListBucketsOutput {
pub fn buckets(&self) -> &Vec<ListedBucket> {
&self.buckets
}
pub fn owner(&self) -> &Owner {
&self.owner
}
}
impl OutputParser for ListBucketsOutput {
fn parse_by_ref<B>(_: &HttpRequest<B>, response: &mut HttpResponse, request_info: RequestInfo, _: Meta) -> Result<Self, TosError> {
let mut result = parse_json::<Self>(response)?;
result.request_info = request_info;
Ok(result)
}
}
impl ListedBucket {
pub fn creation_date(&self) -> &str {
&self.creation_date
}
pub fn name(&self) -> &str {
&self.name
}
pub fn location(&self) -> &str {
&self.location
}
pub fn extranet_endpoint(&self) -> &str {
&self.extranet_endpoint
}
pub fn intranet_endpoint(&self) -> &str {
&self.intranet_endpoint
}
pub fn project_name(&self) -> &str {
&self.project_name
}
}