pub mod bin;
pub mod kv;
use self::{bin::Bin, kv::Kv};
use crate::{
crypto::{asym::KeyPair, DetachedKey, Encrypted},
error::Result,
utils::{Diff, DiffExt, Id, TagSet},
};
use async_std::sync::Arc;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Header {
pub id: Id,
pub tags: TagSet, sec: Encrypted<SecHeader, KeyPair>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) enum Type {
Kv,
Bin,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct Timestamp {
pub(crate) created: DateTime<Utc>,
pub(crate) updated: DateTime<Utc>,
}
impl Timestamp {
pub(crate) fn create() -> Self {
let now = Utc::now();
Self {
created: now,
updated: now,
}
}
pub(crate) fn update(&mut self) {
self.updated = Utc::now();
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) struct SecHeader {
pub(crate) t: Type,
time: Timestamp,
pub(crate) size: u64,
pub(crate) chunks: Vec<u32>,
}
impl DetachedKey<KeyPair> for SecHeader {}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub(crate) enum Body {
Kv(Kv),
Bin(Bin),
}
impl Body {
fn apply(&mut self, d: Diff) -> Result<()> {
match self {
Self::Kv(ref mut kv) => kv.apply(d),
Self::Bin(_) => unimplemented!(),
}
}
}
impl DetachedKey<KeyPair> for Body {}
pub type RecordRef = Arc<Record>;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Record {
pub header: Header,
body: Encrypted<Body, KeyPair>,
}
impl Record {
pub(crate) fn create(tags: TagSet, diff: Diff) -> Result<Self> {
let (t, mut body) = match diff {
Diff::Map(_) => (Type::Kv, Body::Kv(Kv::new())),
Diff::Binary(_) => unimplemented!(),
};
body.apply(diff)?;
let body = Encrypted::new(body);
let sec = Encrypted::new(SecHeader {
t,
time: Timestamp::create(),
size: 0,
chunks: vec![],
});
let header = Header {
id: Id::random(),
tags: tags.into(),
sec,
};
Ok(Self { header, body })
}
pub(crate) fn apply(&mut self, diff: Diff) -> Result<()> {
match self.body.deref_mut()? {
Body::Kv(kv) => kv
.apply(diff)
.map(|_| self.header.sec.deref_mut().unwrap().time.update()),
Body::Bin(_) => unimplemented!(),
}
}
pub fn kv(&self) -> &Kv {
match self.body.deref() {
Ok(Body::Kv(ref kv)) => kv,
_ => unimplemented!(),
}
}
}