use crate::s3::error::Error;
use crate::s3::types::{FromS3Response, S3Request};
use crate::s3::utils::{get_text, take_bucket, take_object};
use async_trait::async_trait;
use bytes::{Buf, Bytes};
use http::HeaderMap;
use std::mem;
use xmltree::Element;
#[derive(Clone, Debug)]
pub struct UploadPartCopyResponse {
pub headers: HeaderMap,
pub region: String,
pub bucket: String,
pub object: String,
pub etag: String,
pub version_id: Option<String>,
}
#[async_trait]
impl FromS3Response for UploadPartCopyResponse {
async fn from_s3response(
req: S3Request,
resp: Result<reqwest::Response, Error>,
) -> Result<Self, Error> {
let mut resp = resp?;
let headers: HeaderMap = mem::take(resp.headers_mut());
let etag: String = {
let body: Bytes = resp.bytes().await?;
let root = Element::parse(body.reader())?;
get_text(&root, "ETag")?.trim_matches('"').to_string()
};
let version_id: Option<String> = headers
.get("x-amz-version-id")
.and_then(|v| v.to_str().ok().map(String::from));
Ok(Self {
headers,
region: req.inner_region,
bucket: take_bucket(req.bucket)?,
object: take_object(req.object)?,
etag,
version_id,
})
}
}
#[derive(Clone, Debug)]
pub struct CopyObjectInternalResponse {
pub headers: HeaderMap,
pub region: String,
pub bucket: String,
pub object: String,
pub etag: String,
pub version_id: Option<String>,
}
#[async_trait]
impl FromS3Response for CopyObjectInternalResponse {
async fn from_s3response(
req: S3Request,
resp: Result<reqwest::Response, Error>,
) -> Result<Self, Error> {
let bucket = req
.bucket
.ok_or_else(|| Error::InvalidBucketName("no bucket specified".into()))?;
let object = req
.object
.ok_or_else(|| Error::InvalidObjectName("no object specified".into()))?;
let mut resp = resp?;
let headers: HeaderMap = mem::take(resp.headers_mut());
let etag: String = {
let body: Bytes = resp.bytes().await?;
let root = Element::parse(body.reader())?;
get_text(&root, "ETag")?.trim_matches('"').to_string()
};
let version_id: Option<String> = headers
.get("x-amz-version-id")
.and_then(|v| v.to_str().ok().map(String::from));
Ok(CopyObjectInternalResponse {
headers,
region: req.inner_region,
bucket,
object,
etag,
version_id,
})
}
}
#[derive(Clone, Debug)]
pub struct CopyObjectResponse {
pub headers: HeaderMap,
pub region: String,
pub bucket: String,
pub object: String,
pub etag: String,
pub version_id: Option<String>,
}
#[derive(Debug, Clone)]
pub struct ComposeObjectResponse {
pub headers: HeaderMap,
pub bucket: String,
pub object: String,
pub region: String,
pub etag: String,
pub version_id: Option<String>,
}