use serde::{Deserialize, Serialize};
use ulid::Ulid;
use crate::frontmatter::Frontmatter;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct NoteId(pub Ulid);
impl NoteId {
pub fn new() -> Self {
Self(Ulid::new())
}
pub fn timestamp_ms(&self) -> u64 {
self.0.timestamp_ms()
}
}
impl Default for NoteId {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for NoteId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ContentHash(pub [u8; 32]);
impl ContentHash {
pub fn compute(frontmatter: &Frontmatter, body: &str) -> Self {
use sha2::{Digest, Sha256};
let canonical = serde_jcs::to_string(frontmatter).expect(
"Frontmatter est toujours sérialisable en JCS (pas de f32::NAN ni de types non-JSON)",
);
let mut hasher = Sha256::new();
hasher.update(canonical.as_bytes());
hasher.update(b"\n---\n");
hasher.update(body.as_bytes());
ContentHash(hasher.finalize().into())
}
pub fn hex(&self) -> String {
self.0.iter().map(|b| format!("{b:02x}")).collect()
}
}
impl std::fmt::Display for ContentHash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.hex())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct NoteVersion(pub u32);
impl NoteVersion {
pub fn initial() -> Self {
Self(1)
}
pub fn next(&self) -> Self {
Self(self.0 + 1)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(transparent)]
pub struct IntegritySignature(pub Vec<u8>);