style: apply cargo fmt to entire codebase
Standardize code formatting across all 173 Rust source files using rustfmt. No functional changes - purely cosmetic. This establishes a consistent code style baseline for the project going forward.
This commit is contained in:
@@ -1,33 +1,33 @@
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use zip::{ZipWriter, write::SimpleFileOptions};
|
||||
use thiserror::Error;
|
||||
use tracing::*;
|
||||
use async_trait::async_trait;
|
||||
use crate::{
|
||||
application::dtos::file_dto::FileDto,
|
||||
application::dtos::folder_dto::FolderDto,
|
||||
application::ports::inbound::FolderUseCase,
|
||||
application::ports::file_ports::FileRetrievalUseCase,
|
||||
application::ports::inbound::FolderUseCase,
|
||||
application::ports::zip_ports::ZipPort,
|
||||
common::errors::{Result, DomainError, ErrorKind},
|
||||
common::errors::{DomainError, ErrorKind, Result},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use std::io::{Cursor, Read, Write};
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use tracing::*;
|
||||
use zip::{ZipWriter, write::SimpleFileOptions};
|
||||
|
||||
/// Error related to ZIP file creation
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ZipError {
|
||||
#[error("IO error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
|
||||
#[error("ZIP error: {0}")]
|
||||
ZipError(#[from] zip::result::ZipError),
|
||||
|
||||
|
||||
#[error("Error reading file: {0}")]
|
||||
FileReadError(String),
|
||||
|
||||
|
||||
#[error("Error getting folder contents: {0}")]
|
||||
FolderContentsError(String),
|
||||
|
||||
|
||||
#[error("Folder not found: {0}")]
|
||||
FolderNotFound(String),
|
||||
}
|
||||
@@ -54,18 +54,24 @@ pub struct ZipService {
|
||||
|
||||
impl ZipService {
|
||||
/// Creates a new instance of the ZIP service with a reference to the file service
|
||||
pub fn new(file_service: Arc<dyn FileRetrievalUseCase>, folder_service: Arc<dyn FolderUseCase>) -> Self {
|
||||
pub fn new(
|
||||
file_service: Arc<dyn FileRetrievalUseCase>,
|
||||
folder_service: Arc<dyn FolderUseCase>,
|
||||
) -> Self {
|
||||
Self {
|
||||
file_service,
|
||||
folder_service,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Creates a ZIP file with the contents of a folder and all its subfolders
|
||||
/// Returns the ZIP bytes
|
||||
pub async fn create_folder_zip(&self, folder_id: &str, folder_name: &str) -> Result<Vec<u8>> {
|
||||
info!("Creating ZIP for folder: {} (ID: {})", folder_name, folder_id);
|
||||
|
||||
info!(
|
||||
"Creating ZIP for folder: {} (ID: {})",
|
||||
folder_name, folder_id
|
||||
);
|
||||
|
||||
// Verify if the folder exists
|
||||
let folder = match self.folder_service.get_folder(folder_id).await {
|
||||
Ok(folder) => folder,
|
||||
@@ -74,31 +80,32 @@ impl ZipService {
|
||||
return Err(ZipError::FolderNotFound(folder_id.to_string()).into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Create an in-memory buffer for the ZIP
|
||||
let buf = Cursor::new(Vec::new());
|
||||
let mut zip = ZipWriter::new(buf);
|
||||
|
||||
|
||||
// Set compression options
|
||||
let options = SimpleFileOptions::default()
|
||||
.compression_method(zip::CompressionMethod::Deflated)
|
||||
.unix_permissions(0o755);
|
||||
|
||||
|
||||
// Object to track processed folders and avoid cycles
|
||||
let mut processed_folders = std::collections::HashSet::new();
|
||||
|
||||
|
||||
// Process the root folder and build the ZIP
|
||||
self.process_folder_recursively(
|
||||
&mut zip,
|
||||
&folder,
|
||||
folder_name,
|
||||
&options,
|
||||
&mut processed_folders
|
||||
).await?;
|
||||
|
||||
&mut processed_folders,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Finalize the ZIP and get the bytes
|
||||
let mut zip_buf = zip.finish()?;
|
||||
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
match zip_buf.read_to_end(&mut bytes) {
|
||||
Ok(_) => Ok(bytes),
|
||||
@@ -108,7 +115,7 @@ impl ZipService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Alternative implementation to avoid recursion in async
|
||||
async fn process_folder_recursively(
|
||||
&self,
|
||||
@@ -116,31 +123,31 @@ impl ZipService {
|
||||
folder: &FolderDto,
|
||||
path: &str,
|
||||
options: &SimpleFileOptions,
|
||||
processed_folders: &mut std::collections::HashSet<String>
|
||||
processed_folders: &mut std::collections::HashSet<String>,
|
||||
) -> Result<()> {
|
||||
// Structure to represent pending work
|
||||
struct PendingFolder {
|
||||
folder: FolderDto,
|
||||
path: String,
|
||||
}
|
||||
|
||||
|
||||
// Work queue for iterative processing
|
||||
let mut work_queue = vec![PendingFolder {
|
||||
folder: folder.clone(),
|
||||
path: path.to_string(),
|
||||
}];
|
||||
|
||||
|
||||
// Process the queue while there are elements
|
||||
while let Some(current) = work_queue.pop() {
|
||||
let folder_id = current.folder.id.to_string();
|
||||
|
||||
|
||||
// Avoid cycles
|
||||
if processed_folders.contains(&folder_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
processed_folders.insert(folder_id.clone());
|
||||
|
||||
|
||||
// Create the directory entry in the ZIP
|
||||
let folder_path = format!("{}/", current.path);
|
||||
match zip.add_directory(&folder_path, *options) {
|
||||
@@ -150,30 +157,39 @@ impl ZipService {
|
||||
// Continue even if creating the directory fails (it could be a duplicate)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add files from the folder to the ZIP
|
||||
let files = match self.file_service.list_files(Some(&folder_id)).await {
|
||||
Ok(files) => files,
|
||||
Err(e) => {
|
||||
error!("Error listing files in folder {}: {}", folder_id, e);
|
||||
return Err(ZipError::FolderContentsError(format!("Error listing files: {}", e)).into());
|
||||
return Err(ZipError::FolderContentsError(format!(
|
||||
"Error listing files: {}",
|
||||
e
|
||||
))
|
||||
.into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Add each file to the ZIP
|
||||
for file in files {
|
||||
self.add_file_to_zip(zip, &file, &folder_path, options).await?;
|
||||
self.add_file_to_zip(zip, &file, &folder_path, options)
|
||||
.await?;
|
||||
}
|
||||
|
||||
|
||||
// Process subfolders
|
||||
let subfolders = match self.folder_service.list_folders(Some(&folder_id)).await {
|
||||
Ok(folders) => folders,
|
||||
Err(e) => {
|
||||
error!("Error listing subfolders in {}: {}", folder_id, e);
|
||||
return Err(ZipError::FolderContentsError(format!("Error listing subfolders: {}", e)).into());
|
||||
return Err(ZipError::FolderContentsError(format!(
|
||||
"Error listing subfolders: {}",
|
||||
e
|
||||
))
|
||||
.into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Add subfolders to the queue
|
||||
for subfolder in subfolders {
|
||||
let subfolder_path = format!("{}/{}", current.path, subfolder.name);
|
||||
@@ -183,10 +199,10 @@ impl ZipService {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
// Adds a file to the ZIP
|
||||
async fn add_file_to_zip(
|
||||
&self,
|
||||
@@ -197,29 +213,31 @@ impl ZipService {
|
||||
) -> Result<()> {
|
||||
let file_path = format!("{}{}", folder_path, file.name);
|
||||
info!("Adding file to ZIP: {}", file_path);
|
||||
|
||||
|
||||
// Get the file content
|
||||
let file_id = file.id.to_string();
|
||||
let content = match self.file_service.get_file_content(&file_id).await {
|
||||
Ok(content) => content,
|
||||
Err(e) => {
|
||||
error!("Error reading file content {}: {}", file_id, e);
|
||||
return Err(ZipError::FileReadError(format!("Error reading file {}: {}", file_id, e)).into());
|
||||
return Err(ZipError::FileReadError(format!(
|
||||
"Error reading file {}: {}",
|
||||
file_id, e
|
||||
))
|
||||
.into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Write file to the ZIP
|
||||
match zip.start_file_from_path(std::path::Path::new(&file_path), *options) {
|
||||
Ok(_) => {
|
||||
match zip.write_all(&content) {
|
||||
Ok(_) => {
|
||||
debug!("File added to ZIP: {}", file_path);
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error writing file content {}: {}", file_path, e);
|
||||
Err(ZipError::IoError(e).into())
|
||||
}
|
||||
Ok(_) => match zip.write_all(&content) {
|
||||
Ok(_) => {
|
||||
debug!("File added to ZIP: {}", file_path);
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error writing file content {}: {}", file_path, e);
|
||||
Err(ZipError::IoError(e).into())
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
@@ -241,4 +259,4 @@ impl ZipPort for ZipService {
|
||||
) -> std::result::Result<Vec<u8>, DomainError> {
|
||||
self.create_folder_zip(folder_id, folder_name).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user