sssync 0.1.1

A version control system for large files backed by online blob storage
use std::error::Error;
use std::fs::File;
use std::io;
use std::io::Write;
use std::path::Path;

use xxhash_rust::xxh3::{xxh3_128, Xxh3};

#[allow(clippy::needless_range_loop)]
fn u128_to_byte_array(n: u128) -> [u8; 16] {
    let mut out: [u8; 16] = [0; 16];

    for i in 0..16 {
        out[i] = (n >> (16 - i)) as u8;
    }

    out
}

struct Xxh3Writer {
    hasher: Xxh3,
}

impl Xxh3Writer {
    pub const fn new() -> Self {
        Self {
            hasher: Xxh3::new(),
        }
    }
}

impl Write for Xxh3Writer {
    fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
        self.hasher.update(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        Ok(())
    }
}

pub fn hash_file(path: &Path) -> Result<String, Box<dyn Error>> {
    let mut hasher = Xxh3Writer::new();
    let mut file = File::open(&path)?;
    io::copy(&mut file, &mut hasher)?;
    let hash = hasher.hasher.digest128();
    Ok(hex::encode(&u128_to_byte_array(hash)))
}

pub fn hash_string(s: String) -> String {
    hex::encode(&u128_to_byte_array(xxh3_128(s.as_bytes())))
}