use rand::prelude::*;
pub struct SBXF<T> {
handler: T,
}
impl<T: Handler> SBXF<T> {
pub fn new(handler: T) -> Self {
SBXF { handler }
}
pub fn upload_file(&self, data: Vec<u8>) -> Result<(), ()> {
let block_size = self.calculate_blocksize(data.len());
let mut blocks = data.len() / block_size;
if data.len() % block_size != 0 {
blocks += 1;
};
for i in 0..blocks {
let block_start = i * block_size;
let block_end = (block_start + block_size).min(data.len());
let block = self.size_block(&data[block_start..block_end], block_size);
let encrypted_block = self.encrypt_block(block);
self.handler.save_block(encrypted_block)?;
}
let _ = self.handler.save_meta(data);
Ok(())
}
fn calculate_blocksize(&self, size: usize) -> usize {
(size.next_power_of_two() >> 3)
.max(4 * 1024) .min(64 * 1024 * 1024) }
fn size_block(&self, raw_block: &[u8], block_size: usize) -> Vec<u8> {
let block = if raw_block.len() == block_size {
raw_block.to_owned()
} else {
let mut rng = rand::thread_rng();
let mut new_block = raw_block.to_owned();
let padding_len = block_size - new_block.len();
for _ in 0..padding_len {
new_block.push(rng.gen());
}
new_block
};
block
}
fn encrypt_block(&self, block: Vec<u8>) -> Vec<u8> {
block
}
}
pub trait Handler {
fn save_meta(&self, data: Vec<u8>) -> Result<(), ()>;
fn save_block(&self, data: Vec<u8>) -> Result<(), ()>;
}
#[cfg(test)]
mod tests {
use super::*;
struct DummyHandler;
impl Handler for DummyHandler {
fn save_meta(&self, _: Vec<u8>) -> Result<(), ()> {
Ok(())
}
fn save_block(&self, _: Vec<u8>) -> Result<(), ()> {
Ok(())
}
}
#[test]
fn upload_smoke() {
let sbxf = SBXF::new(DummyHandler);
sbxf.upload_file(vec![42, 42, 255])
.expect("failed to upload");
}
#[test]
fn calculate_blocksize() {
let sbxf = SBXF::new(DummyHandler);
assert_eq!(32 * 1024, sbxf.calculate_blocksize(200 * 1024));
assert_eq!(32 * 1024, sbxf.calculate_blocksize(256 * 1024));
assert_eq!(64 * 1024, sbxf.calculate_blocksize((256 * 1024) + 1));
}
#[test]
fn calculate_small_blocksize() {
let sbxf = SBXF::new(DummyHandler);
assert_eq!(4096, sbxf.calculate_blocksize(0));
assert_eq!(4096, sbxf.calculate_blocksize(1));
assert_eq!(4096, sbxf.calculate_blocksize(4242));
assert_eq!(4096, sbxf.calculate_blocksize(32 * 1024)); assert_eq!(8192, sbxf.calculate_blocksize((32 * 1024) + 1)); }
#[test]
fn calculate_large_blocksize() {
let sbxf = SBXF::new(DummyHandler);
assert_eq!(
32 * 1024 * 1024,
sbxf.calculate_blocksize(256 * 1024 * 1024)
); assert_eq!(
64 * 1024 * 1024,
sbxf.calculate_blocksize(256 * 1024 * 1024 + 1)
); assert_eq!(
64 * 1024 * 1024,
sbxf.calculate_blocksize(1024 * 1024 * 1024)
); assert_eq!(
64 * 1024 * 1024,
sbxf.calculate_blocksize(1024 * 1024 * 1024 * 1024)
); }
#[test]
fn resize_block() {
let sbxf = SBXF::new(DummyHandler);
let new_block = sbxf.size_block(&[42, 255, 0], 666);
assert_eq!(666, new_block.len());
assert_eq!(42, new_block[0]);
assert_eq!(255, new_block[1]);
assert_eq!(0, new_block[2]);
}
}