perf: zero-alloc File → FileDto via into_parts() ownership transfer
- Add FileParts struct and File::into_parts() to yield owned fields - Rewrite From<File> for FileDto to move id, name, path, folder_id, owner_id by ownership instead of .to_string() copies - Eliminates ~5 heap allocations per file (5000 saved per 1000-file listing)
This commit is contained in:
@@ -60,24 +60,30 @@ pub struct FileDto {
|
|||||||
|
|
||||||
impl From<File> for FileDto {
|
impl From<File> for FileDto {
|
||||||
fn from(file: File) -> Self {
|
fn from(file: File) -> Self {
|
||||||
let name = file.name();
|
// Consume the entity by moving all fields — zero heap allocations
|
||||||
let mime = file.mime_type();
|
// for id, name, path, folder_id, owner_id (previously 5× .to_string()).
|
||||||
let size = file.size();
|
let parts = file.into_parts();
|
||||||
|
|
||||||
|
let icon_class = Arc::from(icon_class_for(&parts.name, &parts.mime_type));
|
||||||
|
let icon_special_class = Arc::from(icon_special_class_for(&parts.name, &parts.mime_type));
|
||||||
|
let category = Arc::from(category_for(&parts.name, &parts.mime_type));
|
||||||
|
let size_formatted = format_file_size(parts.size);
|
||||||
|
let mime_type = Arc::from(parts.mime_type.as_str());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: file.id().to_string(),
|
id: parts.id,
|
||||||
name: name.to_string(),
|
name: parts.name,
|
||||||
path: file.path_string().to_string(),
|
path: parts.path_string,
|
||||||
size,
|
size: parts.size,
|
||||||
mime_type: Arc::from(mime),
|
mime_type,
|
||||||
folder_id: file.folder_id().map(String::from),
|
folder_id: parts.folder_id,
|
||||||
created_at: file.created_at(),
|
created_at: parts.created_at,
|
||||||
modified_at: file.modified_at(),
|
modified_at: parts.modified_at,
|
||||||
icon_class: Arc::from(icon_class_for(name, mime)),
|
icon_class,
|
||||||
icon_special_class: Arc::from(icon_special_class_for(name, mime)),
|
icon_special_class,
|
||||||
category: Arc::from(category_for(name, mime)),
|
category,
|
||||||
size_formatted: format_file_size(size),
|
size_formatted,
|
||||||
owner_id: file.owner_id().map(String::from),
|
owner_id: parts.owner_id,
|
||||||
sort_date: None,
|
sort_date: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,24 @@ use crate::domain::services::path_service::StoragePath;
|
|||||||
// Re-export entity errors from the centralized module
|
// Re-export entity errors from the centralized module
|
||||||
pub use super::entity_errors::{FileError, FileResult};
|
pub use super::entity_errors::{FileError, FileResult};
|
||||||
|
|
||||||
|
/// Owned parts of a [`File`] entity, produced by [`File::into_parts()`].
|
||||||
|
///
|
||||||
|
/// Consuming a `File` into `FileParts` **moves** every field without cloning,
|
||||||
|
/// eliminating 3-5 heap allocations that previously occurred when converting
|
||||||
|
/// `File → FileDto` via `.to_string()` on each getter.
|
||||||
|
pub struct FileParts {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub storage_path: StoragePath,
|
||||||
|
pub path_string: String,
|
||||||
|
pub size: u64,
|
||||||
|
pub mime_type: String,
|
||||||
|
pub folder_id: Option<String>,
|
||||||
|
pub created_at: u64,
|
||||||
|
pub modified_at: u64,
|
||||||
|
pub owner_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a file in the system's domain model.
|
* Represents a file in the system's domain model.
|
||||||
*
|
*
|
||||||
@@ -167,6 +185,25 @@ impl File {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Consume the entity and return all fields by ownership.
|
||||||
|
///
|
||||||
|
/// Use this when converting `File` into a DTO to avoid cloning
|
||||||
|
/// every `String` field (saves 3-5 heap allocations per file).
|
||||||
|
pub fn into_parts(self) -> FileParts {
|
||||||
|
FileParts {
|
||||||
|
id: self.id,
|
||||||
|
name: self.name,
|
||||||
|
storage_path: self.storage_path,
|
||||||
|
path_string: self.path_string,
|
||||||
|
size: self.size,
|
||||||
|
mime_type: self.mime_type,
|
||||||
|
folder_id: self.folder_id,
|
||||||
|
created_at: self.created_at,
|
||||||
|
modified_at: self.modified_at,
|
||||||
|
owner_id: self.owner_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
pub fn id(&self) -> &str {
|
pub fn id(&self) -> &str {
|
||||||
&self.id
|
&self.id
|
||||||
|
|||||||
Reference in New Issue
Block a user