From 9ffc090b3b2248def2aa9390ca1fd4028fb3663b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 28 May 2019 22:39:33 -0700 Subject: [PATCH] feat(index): port index::insert() --- src/index.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/index.rs diff --git a/src/index.rs b/src/index.rs new file mode 100644 index 0000000..6da24ca --- /dev/null +++ b/src/index.rs @@ -0,0 +1,84 @@ +use std::fs::{self, OpenOptions}; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::time::{SystemTime, UNIX_EPOCH}; + +use digest::Digest; +use hex; +use serde_derive::{Deserialize, Serialize}; +use serde_json::{self, json, Value}; +use sha1::Sha1; +use sha2::Sha256; +use ssri::Integrity; + +const INDEX_VERSION: &str = "5"; + +#[derive(Deserialize, Serialize)] +struct Entry { + key: String, + integrity: String, + time: u128, + size: u128, + metadata: Value, +} + +pub fn insert(cache: &Path, key: &str, sri: Integrity) -> std::io::Result<()> { + let bucket = bucket_path(&cache, &key); + fs::create_dir_all(bucket.parent().unwrap())?; + let stringified = serde_json::to_string(&Entry { + key: String::from(key), + integrity: sri.to_string(), + time: now(), + size: 0, // TODO - probably do something about this. + metadata: json!(null), + }) + .expect("Failed to serialize entry."); + let str = format!("\n{}\t{}", hash_entry(&stringified), stringified); + OpenOptions::new() + .create(true) + .append(true) + .open(bucket)? + .write_all(&str.into_bytes()) +} + +pub fn find(_cache: &Path, _key: &str) { + unimplemented!(); +} + +pub fn delete(_cache: &Path, _key: &str) { + unimplemented!(); +} + +pub fn ls(_cache: &Path) { + unimplemented!(); +} + +fn bucket_path(cache: &Path, key: &str) -> PathBuf { + let hashed = hash_key(&key); + let mut path = PathBuf::new(); + path.push(cache); + path.push(format!("index-v{}", INDEX_VERSION)); + path.push(&hashed[0..2]); + path.push(&hashed[2..4]); + path.push(&hashed[4..]); + path +} + +fn hash_key(key: &str) -> String { + let mut hasher = Sha1::new(); + hasher.input(&key); + hex::encode(hasher.result()) +} + +fn hash_entry(key: &str) -> String { + let mut hasher = Sha256::new(); + hasher.input(&key); + hex::encode(hasher.result()) +} + +fn now() -> u128 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_millis() +}