photoncloud-monorepo/lightningstor/crates/lightningstor-server/src/s3/xml.rs

177 lines
4.9 KiB
Rust

//! S3 XML response formatting
use quick_xml::se::to_string as xml_to_string;
use serde::Serialize;
/// S3 error response
#[derive(Debug, Serialize)]
#[serde(rename = "Error")]
pub struct ErrorResponse {
#[serde(rename = "Code")]
pub code: String,
#[serde(rename = "Message")]
pub message: String,
#[serde(rename = "Resource")]
pub resource: String,
#[serde(rename = "RequestId")]
pub request_id: String,
}
impl ErrorResponse {
pub fn to_xml(&self) -> String {
format!(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n{}",
xml_to_string(self).unwrap_or_default()
)
}
}
/// ListAllMyBucketsResult for ListBuckets
#[derive(Debug, Serialize)]
#[serde(rename = "ListAllMyBucketsResult")]
pub struct ListAllMyBucketsResult {
#[serde(rename = "Owner")]
pub owner: Owner,
#[serde(rename = "Buckets")]
pub buckets: Buckets,
}
#[derive(Debug, Serialize)]
pub struct Owner {
#[serde(rename = "ID")]
pub id: String,
#[serde(rename = "DisplayName")]
pub display_name: String,
}
#[derive(Debug, Serialize)]
pub struct Buckets {
#[serde(rename = "Bucket", default)]
pub bucket: Vec<BucketEntry>,
}
#[derive(Debug, Serialize)]
pub struct BucketEntry {
#[serde(rename = "Name")]
pub name: String,
#[serde(rename = "CreationDate")]
pub creation_date: String,
}
/// ListBucketResult for ListObjects (v1)
#[derive(Debug, Serialize)]
#[serde(rename = "ListBucketResult")]
pub struct ListBucketResult {
#[serde(rename = "Name")]
pub name: String,
#[serde(rename = "Prefix")]
pub prefix: String,
#[serde(rename = "Marker")]
#[serde(skip_serializing_if = "Option::is_none")]
pub marker: Option<String>,
#[serde(rename = "Delimiter")]
#[serde(skip_serializing_if = "Option::is_none")]
pub delimiter: Option<String>,
#[serde(rename = "MaxKeys")]
pub max_keys: u32,
#[serde(rename = "IsTruncated")]
pub is_truncated: bool,
#[serde(rename = "NextMarker")]
#[serde(skip_serializing_if = "Option::is_none")]
pub next_marker: Option<String>,
#[serde(rename = "Contents", default)]
pub contents: Vec<ObjectEntry>,
#[serde(rename = "CommonPrefixes", default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub common_prefixes: Vec<CommonPrefix>,
}
/// ListBucketResult for ListObjectsV2 (v2)
#[derive(Debug, Serialize)]
#[serde(rename = "ListBucketResult")]
pub struct ListBucketResultV2 {
#[serde(rename = "Name")]
pub name: String,
#[serde(rename = "Prefix")]
pub prefix: String,
#[serde(rename = "Delimiter")]
#[serde(skip_serializing_if = "Option::is_none")]
pub delimiter: Option<String>,
#[serde(rename = "MaxKeys")]
pub max_keys: u32,
#[serde(rename = "KeyCount")]
pub key_count: u32,
#[serde(rename = "IsTruncated")]
pub is_truncated: bool,
#[serde(rename = "ContinuationToken")]
#[serde(skip_serializing_if = "Option::is_none")]
pub continuation_token: Option<String>,
#[serde(rename = "NextContinuationToken")]
#[serde(skip_serializing_if = "Option::is_none")]
pub next_continuation_token: Option<String>,
#[serde(rename = "StartAfter")]
#[serde(skip_serializing_if = "Option::is_none")]
pub start_after: Option<String>,
#[serde(rename = "Contents", default)]
pub contents: Vec<ObjectEntry>,
#[serde(rename = "CommonPrefixes", default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub common_prefixes: Vec<CommonPrefix>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ObjectEntry {
#[serde(rename = "Key")]
pub key: String,
#[serde(rename = "LastModified")]
pub last_modified: String,
#[serde(rename = "ETag")]
pub etag: String,
#[serde(rename = "Size")]
pub size: u64,
#[serde(rename = "StorageClass")]
pub storage_class: String,
}
#[derive(Debug, Serialize)]
pub struct CommonPrefix {
#[serde(rename = "Prefix")]
pub prefix: String,
}
/// InitiateMultipartUploadResult
#[derive(Debug, Serialize)]
#[serde(rename = "InitiateMultipartUploadResult")]
#[allow(dead_code)]
pub struct InitiateMultipartUploadResult {
#[serde(rename = "Bucket")]
pub bucket: String,
#[serde(rename = "Key")]
pub key: String,
#[serde(rename = "UploadId")]
pub upload_id: String,
}
/// CompleteMultipartUploadResult
#[derive(Debug, Serialize)]
#[serde(rename = "CompleteMultipartUploadResult")]
#[allow(dead_code)]
pub struct CompleteMultipartUploadResult {
#[serde(rename = "Location")]
pub location: String,
#[serde(rename = "Bucket")]
pub bucket: String,
#[serde(rename = "Key")]
pub key: String,
#[serde(rename = "ETag")]
pub etag: String,
}
/// Convert to XML with declaration
pub fn to_xml<T: Serialize>(value: &T) -> Result<String, quick_xml::DeError> {
let xml = xml_to_string(value)?;
Ok(format!(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n{}",
xml
))
}