firecloud-core 0.2.0

Core types and traits for FireCloud distributed storage
Documentation
//! Chunk-related types for content-addressed storage

use serde::{Deserialize, Serialize};
use std::fmt;

/// A 256-bit BLAKE3 hash identifying a chunk
#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ChunkHash(pub [u8; 32]);

impl ChunkHash {
    /// Create from raw bytes
    pub fn from_bytes(bytes: [u8; 32]) -> Self {
        Self(bytes)
    }

    /// Hash data to create a ChunkHash
    pub fn hash(data: &[u8]) -> Self {
        let hash = blake3::hash(data);
        Self(*hash.as_bytes())
    }

    /// Get as hex string
    pub fn to_hex(&self) -> String {
        hex::encode(self.0)
    }

    /// Parse from hex string
    pub fn from_hex(s: &str) -> Result<Self, hex::FromHexError> {
        let bytes = hex::decode(s)?;
        let arr: [u8; 32] = bytes.try_into().map_err(|_| hex::FromHexError::InvalidStringLength)?;
        Ok(Self(arr))
    }
}

impl fmt::Debug for ChunkHash {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "ChunkHash({})", &self.to_hex()[..16])
    }
}

impl fmt::Display for ChunkHash {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", &self.to_hex()[..16])
    }
}

/// Unique identifier for a chunk (alias for ChunkHash in content-addressed storage)
pub type ChunkId = ChunkHash;

/// Metadata about a stored chunk
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChunkMetadata {
    /// Content hash (also serves as ID)
    pub hash: ChunkHash,
    /// Size in bytes (after compression, before encryption)
    pub size: u64,
    /// Original (uncompressed) size
    pub original_size: u64,
    /// Compression algorithm used
    pub compression: CompressionType,
    /// Whether this chunk is encrypted
    pub encrypted: bool,
}

/// Compression algorithms supported
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CompressionType {
    None,
    Zstd,
    Lz4,
}

/// A chunk of file data
#[derive(Debug, Clone)]
pub struct Chunk {
    /// Metadata about this chunk
    pub metadata: ChunkMetadata,
    /// The actual data (compressed and/or encrypted)
    pub data: bytes::Bytes,
}

impl Chunk {
    /// Create a new chunk from raw data
    pub fn new(data: bytes::Bytes, original_size: u64, compression: CompressionType) -> Self {
        let hash = ChunkHash::hash(&data);
        Self {
            metadata: ChunkMetadata {
                hash,
                size: data.len() as u64,
                original_size,
                compression,
                encrypted: false,
            },
            data,
        }
    }

    /// Get the chunk's content hash
    pub fn hash(&self) -> &ChunkHash {
        &self.metadata.hash
    }
}