parent
2ddfec4bfc
commit
a515ac47ae
@ -0,0 +1,4 @@
|
||||
//! Consts
|
||||
|
||||
/// Size for most buffers
|
||||
pub const BUFFER_SIZE: usize = 4096;
|
@ -1 +1,47 @@
|
||||
//! Handles building the database, and exposes data structures for the database and ways to interact with them
|
||||
use super::*;
|
||||
use std::{
|
||||
collections::{
|
||||
HashMap,
|
||||
HashSet,
|
||||
},
|
||||
path::{
|
||||
PathBuf,
|
||||
Path,
|
||||
},
|
||||
};
|
||||
use chrono::{
|
||||
DateTime,
|
||||
Utc,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Database
|
||||
{
|
||||
/// Key here is the actual location in /tmp/videl of the database and versioned files
|
||||
database: HashMap<PathBuf,Entry>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Entry
|
||||
{
|
||||
/// Versions are a hashset because we don't need to version files that are /entirely/ identical. (i.e. same timestamp and hash)
|
||||
versions: HashSet<Version>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Version
|
||||
{
|
||||
date: DateTime<Utc>,
|
||||
hash: hash::Sha256Sum,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl Version
|
||||
{
|
||||
/// Gets the lowermost name of the path for this specific version
|
||||
pub fn get_pathname(&self) -> String
|
||||
{
|
||||
format!("{}", self.date.timestamp_nanos())
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,149 @@
|
||||
//! Hashing abstraction
|
||||
use super::*;
|
||||
use sha2::{
|
||||
Sha256, Digest,
|
||||
};
|
||||
use tokio::{
|
||||
prelude::*,
|
||||
io::{
|
||||
AsyncRead,
|
||||
},
|
||||
};
|
||||
use std::{
|
||||
io,
|
||||
marker::Unpin,
|
||||
};
|
||||
|
||||
pub const SHA256_SIZE: usize = 32;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, Ord, PartialOrd)]
|
||||
pub struct Sha256Sum([u8; SHA256_SIZE]);
|
||||
|
||||
impl Default for Sha256Sum
|
||||
{
|
||||
#[inline]
|
||||
fn default() -> Self
|
||||
{
|
||||
Self([0; SHA256_SIZE])
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha256Sum
|
||||
{
|
||||
/// Create a new empty hash sum container
|
||||
pub const fn empty() -> Self
|
||||
{
|
||||
Self([0; SHA256_SIZE])
|
||||
}
|
||||
|
||||
pub const fn from_raw(from: [u8; SHA256_SIZE]) -> Self
|
||||
{
|
||||
Self(from)
|
||||
}
|
||||
|
||||
pub fn from_slice(from: &[u8]) -> Self
|
||||
{
|
||||
let mut output = [0u8; SHA256_SIZE];
|
||||
assert_eq!(util::copy_slice(&mut output, from), SHA256_SIZE);
|
||||
Self(output)
|
||||
}
|
||||
|
||||
/// Compute SHA256 hash from a slice
|
||||
pub fn compute_slice<T>(from: T) -> Self
|
||||
where T: AsRef<[u8]>
|
||||
{
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(from.as_ref());
|
||||
|
||||
Self::from_slice(&hasher.finalize()[..])
|
||||
}
|
||||
|
||||
/// Compute SHA256 from a stream
|
||||
///
|
||||
/// # Notes
|
||||
/// Will read until 0 bytes are returned from the `read()` call.
|
||||
pub async fn compute_stream<W>(from: &mut W) -> io::Result<Self>
|
||||
where W: AsyncRead + Unpin
|
||||
{
|
||||
let mut read;
|
||||
let mut buffer = [0u8; consts::BUFFER_SIZE];
|
||||
let mut hasher = Sha256::new();
|
||||
while {read = from.read(&mut buffer[..]).await?; read != 0} {
|
||||
hasher.update(&buffer[..read]);
|
||||
}
|
||||
Ok(Self::from_slice(&hasher.finalize()[..]))
|
||||
}
|
||||
|
||||
/// Compute from a stream into this instance. Return the number of bytes successfully written into the instance.
|
||||
pub async fn compute_into<W>(&mut self, from: &mut W) -> io::Result<usize>
|
||||
where W: AsyncRead + Unpin
|
||||
{
|
||||
let mut read;
|
||||
let mut done=0;
|
||||
let mut buffer = [0u8; consts::BUFFER_SIZE];
|
||||
let mut hasher = Sha256::new();
|
||||
while {read = from.read(&mut buffer[..]).await?; done += read; read !=0} {
|
||||
hasher.update(&buffer[..read]);
|
||||
}
|
||||
util::copy_slice(self, hasher.finalize());
|
||||
Ok(done)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Sha256Sum
|
||||
{
|
||||
#[inline] fn as_ref(&self) -> &[u8]
|
||||
{
|
||||
&self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<[u8]> for Sha256Sum
|
||||
{
|
||||
#[inline] fn as_mut(&mut self) -> &mut [u8]
|
||||
{
|
||||
&mut self.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; SHA256_SIZE]> for Sha256Sum
|
||||
{
|
||||
#[inline] fn from(from: [u8; SHA256_SIZE]) -> Self
|
||||
{
|
||||
Self(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Sha256> for Sha256Sum
|
||||
{
|
||||
fn from(from: Sha256) -> Self
|
||||
{
|
||||
Self::from_slice(&from.finalize())
|
||||
}
|
||||
}
|
||||
|
||||
/// Update a hasher from a stream async
|
||||
pub async fn stream_async<H, W>(hasher: &mut H, from: &mut W) -> io::Result<usize>
|
||||
where H: Digest,
|
||||
W: AsyncRead + Unpin
|
||||
{
|
||||
let mut read;
|
||||
let mut done=0;
|
||||
let mut buffer = [0u8; consts::BUFFER_SIZE];
|
||||
while {read = from.read(&mut buffer[..]).await?; done += read; read !=0} {
|
||||
hasher.update(&buffer[..read]);
|
||||
}
|
||||
Ok(done)
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Sha256Sum
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
||||
{
|
||||
for byte in self.0.iter()
|
||||
{
|
||||
write!(f, "{:02x}", byte)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
//! Utility functions
|
||||
use std::{
|
||||
borrow::{
|
||||
Borrow,
|
||||
ToOwned,
|
||||
},
|
||||
};
|
||||
|
||||
/// Copy slice `src` into `dst` and return the number of elements copied.
|
||||
#[inline] pub fn copy_slice<T,U,V,W,X>(mut dst: V, src: W) -> usize
|
||||
where V: AsMut<[T]>,
|
||||
W: AsRef<[U]>,
|
||||
U: ToOwned<Owned=X>,
|
||||
X: Borrow<U> + Into<T>
|
||||
{
|
||||
|
||||
let mut i=0;
|
||||
for (d, s) in dst.as_mut().iter_mut().zip(src.as_ref().iter())
|
||||
{
|
||||
*d = s.to_owned().into();
|
||||
i+=1
|
||||
}
|
||||
i
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests
|
||||
{
|
||||
#[test]
|
||||
fn copy_slice()
|
||||
{
|
||||
let mut to = [0u8; 40];
|
||||
let from = [10u8; 37];
|
||||
|
||||
assert_eq!(super::copy_slice(&mut to, &from), 37);
|
||||
|
||||
assert_eq!(from, &to[0..37]);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue