Skip to main content

firecloud_core/
file.rs

1//! File-related types
2
3use crate::chunk::ChunkHash;
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7/// Unique identifier for a file
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub struct FileId(pub Uuid);
10
11impl FileId {
12    /// Generate a new random file ID
13    pub fn new() -> Self {
14        Self(Uuid::new_v4())
15    }
16
17    /// Create from UUID
18    pub fn from_uuid(uuid: Uuid) -> Self {
19        Self(uuid)
20    }
21}
22
23impl Default for FileId {
24    fn default() -> Self {
25        Self::new()
26    }
27}
28
29impl std::fmt::Display for FileId {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        write!(f, "{}", self.0)
32    }
33}
34
35/// Metadata about a file
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct FileMetadata {
38    /// Unique file identifier
39    pub id: FileId,
40    /// Original filename
41    pub name: String,
42    /// MIME type (if known)
43    pub mime_type: Option<String>,
44    /// Original file size in bytes
45    pub size: u64,
46    /// Creation timestamp (Unix millis)
47    pub created_at: i64,
48    /// Last modified timestamp (Unix millis)
49    pub modified_at: i64,
50    /// BLAKE3 hash of entire original file
51    pub content_hash: ChunkHash,
52}
53
54/// A manifest describing how a file is chunked and stored
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct FileManifest {
57    /// File metadata
58    pub metadata: FileMetadata,
59    /// Ordered list of chunk hashes that make up this file
60    pub chunks: Vec<ChunkHash>,
61    /// Encrypted Data Encryption Key (DEK) - encrypted with user's KEK
62    pub encrypted_dek: Option<Vec<u8>>,
63    /// Salt used for KEK derivation (if encrypted_dek is present)
64    pub salt: Option<Vec<u8>>,
65    /// Version number for conflict resolution
66    pub version: u64,
67}
68
69impl FileManifest {
70    /// Create a new manifest for a file
71    pub fn new(metadata: FileMetadata, chunks: Vec<ChunkHash>) -> Self {
72        Self {
73            metadata,
74            chunks,
75            encrypted_dek: None,
76            salt: None,
77            version: 1,
78        }
79    }
80
81    /// Total number of chunks
82    pub fn chunk_count(&self) -> usize {
83        self.chunks.len()
84    }
85}