nectar_primitives/chunk/encryption/
reference.rs1use std::mem::size_of;
4
5use crate::chunk::ChunkAddress;
6
7use super::error::EncryptionError;
8use super::key::EncryptionKey;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct EncryptedChunkRef {
16 address: ChunkAddress,
17 key: EncryptionKey,
18}
19
20impl EncryptedChunkRef {
21 pub const SIZE: usize = size_of::<ChunkAddress>() + EncryptionKey::SIZE;
23
24 pub const fn new(address: ChunkAddress, key: EncryptionKey) -> Self {
26 Self { address, key }
27 }
28
29 pub const fn address(&self) -> &ChunkAddress {
31 &self.address
32 }
33
34 pub const fn key(&self) -> &EncryptionKey {
36 &self.key
37 }
38
39 pub fn into_parts(self) -> (ChunkAddress, EncryptionKey) {
41 (self.address, self.key)
42 }
43
44 pub fn write_to(&self, buf: &mut [u8]) {
46 buf[..size_of::<ChunkAddress>()].copy_from_slice(self.address.as_bytes());
47 buf[size_of::<ChunkAddress>()..Self::SIZE].copy_from_slice(self.key.as_bytes());
48 }
49}
50
51impl From<&EncryptedChunkRef> for [u8; EncryptedChunkRef::SIZE] {
52 fn from(r: &EncryptedChunkRef) -> Self {
53 let mut buf = [0u8; EncryptedChunkRef::SIZE];
54 r.write_to(&mut buf);
55 buf
56 }
57}
58
59impl From<EncryptedChunkRef> for [u8; EncryptedChunkRef::SIZE] {
60 fn from(r: EncryptedChunkRef) -> Self {
61 (&r).into()
62 }
63}
64
65impl From<&EncryptedChunkRef> for Vec<u8> {
66 fn from(r: &EncryptedChunkRef) -> Self {
67 let mut v = Self::with_capacity(EncryptedChunkRef::SIZE);
68 v.extend_from_slice(r.address.as_bytes());
69 v.extend_from_slice(r.key.as_bytes());
70 v
71 }
72}
73
74impl TryFrom<&[u8]> for EncryptedChunkRef {
75 type Error = EncryptionError;
76
77 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
78 if slice.len() != Self::SIZE {
79 return Err(EncryptionError::InvalidReferenceLength { len: slice.len() });
80 }
81 let addr = ChunkAddress::from_slice(&slice[..size_of::<ChunkAddress>()])
82 .map_err(|_| EncryptionError::InvalidReferenceLength { len: slice.len() })?;
83 let key = EncryptionKey::try_from(&slice[size_of::<ChunkAddress>()..])?;
84 Ok(Self { address: addr, key })
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use alloy_primitives::B256;
92
93 #[test]
94 fn encrypted_roundtrip() {
95 let addr = ChunkAddress::from(B256::repeat_byte(0xcd));
96 let key = EncryptionKey::from([0xef; 32]);
97 let enc_ref = EncryptedChunkRef::new(addr, key.clone());
98
99 assert_eq!(enc_ref.address(), &addr);
100 assert_eq!(enc_ref.key(), &key);
101
102 let bytes: [u8; 64] = (&enc_ref).into();
103 assert_eq!(bytes.len(), 64);
104
105 let recovered = EncryptedChunkRef::try_from(bytes.as_slice()).unwrap();
106 assert_eq!(recovered, enc_ref);
107 }
108
109 #[test]
110 fn invalid_length() {
111 let bad = [0u8; 48];
112 let err = EncryptedChunkRef::try_from(bad.as_slice()).unwrap_err();
113 assert!(matches!(
114 err,
115 EncryptionError::InvalidReferenceLength { len: 48 }
116 ));
117 }
118
119 #[test]
120 fn write_to_buffer() {
121 let addr = ChunkAddress::from(B256::repeat_byte(0x22));
122 let key = EncryptionKey::from([0x33; 32]);
123 let enc_ref = EncryptedChunkRef::new(addr, key);
124
125 let mut buf = [0u8; 64];
126 enc_ref.write_to(&mut buf);
127 assert_eq!(&buf[..32], &[0x22; 32]);
128 assert_eq!(&buf[32..], &[0x33; 32]);
129 }
130}