style: cargo fmt --all

This commit is contained in:
2026-05-31 05:31:42 +02:00
parent 4b31a0f74b
commit c2ebca0da0
138 changed files with 2422 additions and 1164 deletions

View File

@@ -1,10 +1,10 @@
use std::sync::Arc;
use async_trait::async_trait;
use bytes::Bytes;
use futures::stream::StreamExt;
use object_store::{ObjectStore, path::Path, Error as OsError};
use domain::errors::DomainError;
use domain::ports::{DataStream, StorageReader, StorageWriter};
use futures::stream::StreamExt;
use object_store::{Error as OsError, ObjectStore, path::Path};
use std::sync::Arc;
pub struct ObjectStorageAdapter {
store: Arc<dyn ObjectStore>,
@@ -12,7 +12,10 @@ pub struct ObjectStorageAdapter {
}
impl ObjectStorageAdapter {
pub fn new(store: Arc<dyn ObjectStore>, prefix: impl Into<String>) -> Result<Self, DomainError> {
pub fn new(
store: Arc<dyn ObjectStore>,
prefix: impl Into<String>,
) -> Result<Self, DomainError> {
let prefix = prefix.into();
if !prefix.is_empty() {
validate_key(&prefix)?;
@@ -38,17 +41,19 @@ fn map_err(e: OsError, key: &str) -> DomainError {
fn validate_key(key: &str) -> Result<(), DomainError> {
if key.is_empty() {
return Err(DomainError::Validation("storage key must not be empty".into()));
return Err(DomainError::Validation(
"storage key must not be empty".into(),
));
}
if key.starts_with('/') {
return Err(DomainError::Validation(
format!("storage key must not start with '/': {key}"),
));
return Err(DomainError::Validation(format!(
"storage key must not start with '/': {key}"
)));
}
if key.split('/').any(|seg| seg == ".." || seg == ".") {
return Err(DomainError::Validation(
format!("storage key contains invalid path segment: {key}"),
));
return Err(DomainError::Validation(format!(
"storage key contains invalid path segment: {key}"
)));
}
Ok(())
}
@@ -79,7 +84,10 @@ impl StorageWriter for ObjectStorageAdapter {
}
}
}
upload.complete().await.map_err(|e| DomainError::Internal(e.to_string()))?;
upload
.complete()
.await
.map_err(|e| DomainError::Internal(e.to_string()))?;
Ok(())
}
@@ -99,11 +107,7 @@ impl StorageReader for ObjectStorageAdapter {
async fn get(&self, key: &str) -> Result<DataStream, DomainError> {
validate_key(key)?;
let path = self.path(key);
let result = self
.store
.get(&path)
.await
.map_err(|e| map_err(e, key))?;
let result = self.store.get(&path).await.map_err(|e| map_err(e, key))?;
let s = result
.into_stream()
.map(|r| r.map_err(|e| DomainError::Internal(e.to_string())));
@@ -128,10 +132,12 @@ impl StorageReader for ObjectStorageAdapter {
let key = meta.location.to_string();
let stripped = if !self.prefix.is_empty() {
key.strip_prefix(&format!("{}/", self.prefix))
.ok_or_else(|| DomainError::Internal(format!(
"listed key '{key}' does not start with expected prefix '{}'",
self.prefix
)))?
.ok_or_else(|| {
DomainError::Internal(format!(
"listed key '{key}' does not start with expected prefix '{}'",
self.prefix
))
})?
.to_string()
} else {
key
@@ -172,7 +178,10 @@ mod tests {
#[tokio::test]
async fn get_missing_is_not_found() {
let a = make_adapter();
assert!(matches!(a.get("nope.txt").await, Err(DomainError::NotFound(_))));
assert!(matches!(
a.get("nope.txt").await,
Err(DomainError::NotFound(_))
));
}
#[tokio::test]
@@ -186,7 +195,10 @@ mod tests {
let a = make_adapter();
a.put("file.txt", one_shot(b"data")).await.unwrap();
a.delete("file.txt").await.unwrap();
assert!(matches!(a.get("file.txt").await, Err(DomainError::NotFound(_))));
assert!(matches!(
a.get("file.txt").await,
Err(DomainError::NotFound(_))
));
}
#[tokio::test]
@@ -213,9 +225,15 @@ mod tests {
#[tokio::test]
async fn rejects_empty_key() {
let a = make_adapter();
assert!(matches!(a.put("", one_shot(b"x")).await, Err(DomainError::Validation(_))));
assert!(matches!(
a.put("", one_shot(b"x")).await,
Err(DomainError::Validation(_))
));
assert!(matches!(a.get("").await, Err(DomainError::Validation(_))));
assert!(matches!(a.delete("").await, Err(DomainError::Validation(_))));
assert!(matches!(
a.delete("").await,
Err(DomainError::Validation(_))
));
}
#[tokio::test]
@@ -230,8 +248,14 @@ mod tests {
#[tokio::test]
async fn rejects_path_traversal() {
let a = make_adapter();
assert!(matches!(a.get("../escape").await, Err(DomainError::Validation(_))));
assert!(matches!(a.get("a/../../../etc").await, Err(DomainError::Validation(_))));
assert!(matches!(
a.get("../escape").await,
Err(DomainError::Validation(_))
));
assert!(matches!(
a.get("a/../../../etc").await,
Err(DomainError::Validation(_))
));
}
#[tokio::test]
@@ -246,8 +270,14 @@ mod tests {
#[tokio::test]
async fn rejects_invalid_list_prefix() {
let a = make_adapter();
assert!(matches!(a.list(Some("")).await, Err(DomainError::Validation(_))));
assert!(matches!(a.list(Some("../escape")).await, Err(DomainError::Validation(_))));
assert!(matches!(
a.list(Some("")).await,
Err(DomainError::Validation(_))
));
assert!(matches!(
a.list(Some("../escape")).await,
Err(DomainError::Validation(_))
));
}
#[tokio::test]
@@ -275,7 +305,9 @@ mod tests {
#[tokio::test]
async fn put_bytes_get_bytes_roundtrip() {
let a = make_adapter();
a.put_bytes("data.bin", Bytes::from("hello bytes")).await.unwrap();
a.put_bytes("data.bin", Bytes::from("hello bytes"))
.await
.unwrap();
let got = a.get_bytes("data.bin").await.unwrap();
assert_eq!(got.as_ref(), b"hello bytes");
}
@@ -283,7 +315,10 @@ mod tests {
#[tokio::test]
async fn get_bytes_missing_is_not_found() {
let a = make_adapter();
assert!(matches!(a.get_bytes("nope.bin").await, Err(DomainError::NotFound(_))));
assert!(matches!(
a.get_bytes("nope.bin").await,
Err(DomainError::NotFound(_))
));
}
#[test]