use conundrum::{symm_encr::EncrKey, unauth_symm_encr::UnauthEncryptionStream};
use std::{
cell::{RefCell, RefMut},
io::Write,
rc::Rc,
};
use jazz_telepathy::{logs::LogWriteAccess, TelepathyNode};
use super::LogEncryption;
pub(crate) struct LogWriter {
content_telepathy: Rc<RefCell<TelepathyNode>>,
write_access: LogWriteAccess,
encryption_stream: UnauthEncryptionStream<LogEncryption>,
}
impl LogWriter {
pub(crate) fn new(
content_telepathy: Rc<RefCell<TelepathyNode>>,
write_access: LogWriteAccess,
encryption_key: EncrKey<LogEncryption>,
) -> Self {
Self {
content_telepathy,
write_access,
encryption_stream: UnauthEncryptionStream::new(encryption_key, [0; 12].into()),
}
}
}
impl Write for LogWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut logs = RefMut::map(self.content_telepathy.borrow_mut(), |telepathy| {
&mut telepathy.local_state.logs
});
let current_len = logs
.current_data(&self.write_access.id())
.map(|d| d.len())
.unwrap_or(0) as u64;
let mut nonce: [u8; 12] = [0; 12];
(&mut nonce[0..8]).copy_from_slice(¤t_len.to_le_bytes());
let mut encrypted = buf.to_vec();
self.encryption_stream.xor_chunk(&mut encrypted);
logs.append(&self.write_access, &encrypted)
.map(|_ok| encrypted.len())
.map_err(|log_err| match log_err {
jazz_telepathy::logs::LogError::InvalidHash => {
std::io::Error::new(std::io::ErrorKind::InvalidData, log_err)
}
jazz_telepathy::logs::LogError::InvalidSignature(_) => {
std::io::Error::new(std::io::ErrorKind::PermissionDenied, log_err)
}
})
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}