jazz-rs 0.1.0

A framework for CRDT based, end-to-end enrypted distributed apps
Documentation
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()),
            // Null nonce is safe IFF the key is unique to this log
            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);
            }
        }
    }
}