use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::path::Path; pub use typed_sled::Tree; const DB_DIR: &str = "db"; pub type Time = u64; #[derive(Clone)] pub struct Dbs { pub comment: Tree, pub comment_approved: Tree<(TopicHash, Time, CommentId), ()>, pub comment_pending: Tree<(TopicHash, Time, CommentId), ()>, } pub fn load_dbs(path: Option<&Path>) -> Dbs { let db = sled::Config::new(); let db = if let Some(path) = path { db.path(path.join(DB_DIR)) } else { db.temporary(true) } .open() .expect("Cannot open db"); Dbs { comment: Tree::open(&db, "comment"), comment_approved: Tree::open(&db, "comment_approved"), comment_pending: Tree::open(&db, "comment_pending"), } } #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct Comment { pub topic_hash: TopicHash, pub author: String, pub email: Option, pub last_edit_time: Option, pub post_time: u64, pub text: String, } #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct TopicHash(pub [u8; 32]); impl TopicHash { pub fn from_topic(topic: &str) -> Self { let mut hasher = Sha256::new(); hasher.update(topic.as_bytes()); Self(hasher.finalize().into()) } } impl AsRef<[u8]> for TopicHash { fn as_ref(&self) -> &[u8] { &self.0 } } #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct CommentId(pub [u8; 16]); impl CommentId { pub fn new() -> Self { Self(rand::random()) } pub fn zero() -> Self { Self([0; 16]) } pub fn max() -> Self { Self([255; 16]) } pub fn to_base64(&self) -> String { base64::encode_config(self.0, base64::URL_SAFE_NO_PAD) } pub fn from_base64(s: &str) -> Result { let mut buf = [0; 16]; base64::decode_config_slice(s, base64::URL_SAFE_NO_PAD, &mut buf).map(|_| Self(buf)) } } impl AsRef<[u8]> for CommentId { fn as_ref(&self) -> &[u8] { &self.0 } } #[cfg(test)] mod test { #[test] fn test_typed_sled() { let db = sled::Config::new().temporary(true).open().unwrap(); let tree = typed_sled::Tree::<(u32, u32), ()>::open(&db, "test"); tree.insert(&(123, 456), &()).unwrap(); tree.flush().unwrap(); let mut iter = tree.range((123, 0)..(124, 0)); //let mut iter = tree.iter(); assert_eq!(iter.next(), Some(Ok(((123, 456), ())))); } }