use conundrum::{symm_encr::EncrKey, unauth_symm_encr::UnauthEncryptionStream};
use futures::channel::mpsc::UnboundedReceiver;
use std::io::Read;
use jazz_telepathy::{logs::LogAppendMessage, UpdateSource};
use super::LogEncryption;
pub(crate) struct LogReader {
receiver: UnboundedReceiver<(LogAppendMessage, UpdateSource)>,
buf: std::io::Cursor<Vec<u8>>,
decryption_stream: UnauthEncryptionStream<LogEncryption>,
}
impl LogReader {
pub fn new(
receiver: UnboundedReceiver<(LogAppendMessage, UpdateSource)>,
log_encr_key: EncrKey<LogEncryption>,
) -> Self {
Self {
receiver,
buf: std::io::Cursor::new(Vec::new()),
decryption_stream: UnauthEncryptionStream::new(log_encr_key, [0; 12].into()),
}
}
}
impl Read for LogReader {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
loop {
let read_from_buf = self.buf.read(buf)?;
if read_from_buf == 0 {
match self.receiver.try_next() {
Ok(Some((log_append_message, _))) => {
let mut decrypted = log_append_message.append.to_vec();
self.decryption_stream.xor_chunk(&mut decrypted);
self.buf = std::io::Cursor::new(decrypted);
}
Ok(None) => panic!("Unexpected channel close in LogReader"),
Err(recv_err) => {
return Err(std::io::Error::new(
std::io::ErrorKind::Interrupted,
recv_err,
))
}
}
} else {
return Ok(read_from_buf);
}
}
}
}