106 lines
2.3 KiB
Rust
106 lines
2.3 KiB
Rust
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<CommentId, Comment>,
|
|
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<String>,
|
|
pub last_edit_time: Option<u64>,
|
|
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<Self, base64::DecodeError> {
|
|
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), ()))));
|
|
}
|
|
}
|