firecloud-core 0.2.0

Core types and traits for FireCloud distributed storage
Documentation
//! File-related types

use crate::chunk::ChunkHash;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// Unique identifier for a file
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FileId(pub Uuid);

impl FileId {
    /// Generate a new random file ID
    pub fn new() -> Self {
        Self(Uuid::new_v4())
    }

    /// Create from UUID
    pub fn from_uuid(uuid: Uuid) -> Self {
        Self(uuid)
    }
}

impl Default for FileId {
    fn default() -> Self {
        Self::new()
    }
}

impl std::fmt::Display for FileId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

/// Metadata about a file
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileMetadata {
    /// Unique file identifier
    pub id: FileId,
    /// Original filename
    pub name: String,
    /// MIME type (if known)
    pub mime_type: Option<String>,
    /// Original file size in bytes
    pub size: u64,
    /// Creation timestamp (Unix millis)
    pub created_at: i64,
    /// Last modified timestamp (Unix millis)
    pub modified_at: i64,
    /// BLAKE3 hash of entire original file
    pub content_hash: ChunkHash,
}

/// A manifest describing how a file is chunked and stored
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileManifest {
    /// File metadata
    pub metadata: FileMetadata,
    /// Ordered list of chunk hashes that make up this file
    pub chunks: Vec<ChunkHash>,
    /// Encrypted Data Encryption Key (DEK) - encrypted with user's KEK
    pub encrypted_dek: Option<Vec<u8>>,
    /// Salt used for KEK derivation (if encrypted_dek is present)
    pub salt: Option<Vec<u8>>,
    /// Version number for conflict resolution
    pub version: u64,
}

impl FileManifest {
    /// Create a new manifest for a file
    pub fn new(metadata: FileMetadata, chunks: Vec<ChunkHash>) -> Self {
        Self {
            metadata,
            chunks,
            encrypted_dek: None,
            salt: None,
            version: 1,
        }
    }

    /// Total number of chunks
    pub fn chunk_count(&self) -> usize {
        self.chunks.len()
    }
}