Skip to main content

nectar_primitives/file/
entry_ref.rs

1//! Unified file entry reference type.
2
3use crate::chunk::ChunkAddress;
4#[cfg(feature = "encryption")]
5use crate::chunk::encryption::EncryptedChunkRef;
6
7use super::error::FileError;
8
9/// A typed chunk reference: either a plain 32-byte address or an encrypted 64-byte ref.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum EntryRef {
12    /// Plain 32-byte chunk address.
13    Plain(ChunkAddress),
14    /// Encrypted 64-byte reference (address + decryption key).
15    #[cfg(feature = "encryption")]
16    Encrypted(EncryptedChunkRef),
17}
18
19impl EntryRef {
20    /// Parse an entry reference from raw bytes.
21    ///
22    /// - 32 bytes → `Plain`
23    /// - 64 bytes → `Encrypted` (requires `encryption` feature)
24    pub fn try_from_bytes(bytes: &[u8]) -> Result<Self, FileError> {
25        match bytes.len() {
26            32 => {
27                let addr_bytes: [u8; 32] = bytes.try_into().expect("length checked");
28                Ok(Self::Plain(ChunkAddress::from(addr_bytes)))
29            }
30            #[cfg(feature = "encryption")]
31            64 => {
32                let enc_ref = EncryptedChunkRef::try_from(bytes)
33                    .map_err(|_| FileError::InvalidEntryRef { len: bytes.len() })?;
34                Ok(Self::Encrypted(enc_ref))
35            }
36            len => Err(FileError::InvalidEntryRef { len }),
37        }
38    }
39
40    /// The chunk address (first 32 bytes of any reference).
41    pub const fn address(&self) -> &ChunkAddress {
42        match self {
43            Self::Plain(addr) => addr,
44            #[cfg(feature = "encryption")]
45            Self::Encrypted(enc) => enc.address(),
46        }
47    }
48}
49
50impl From<ChunkAddress> for EntryRef {
51    fn from(addr: ChunkAddress) -> Self {
52        Self::Plain(addr)
53    }
54}
55
56#[cfg(feature = "encryption")]
57impl From<EncryptedChunkRef> for EntryRef {
58    fn from(enc: EncryptedChunkRef) -> Self {
59        Self::Encrypted(enc)
60    }
61}
62
63impl From<&EntryRef> for Vec<u8> {
64    fn from(entry_ref: &EntryRef) -> Self {
65        match entry_ref {
66            EntryRef::Plain(addr) => addr.as_bytes().to_vec(),
67            #[cfg(feature = "encryption")]
68            EntryRef::Encrypted(enc) => Self::from(enc),
69        }
70    }
71}