use crate::db::types::{DbTid, DidKey}; use bytes::Bytes; use jacquard_common::CowStr; use jacquard_common::types::cid::IpldCid; use jacquard_common::types::string::Handle; use serde::{Deserialize, Serialize}; use smol_str::SmolStr; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum RepoStatus { Backfilling, Synced, Error(SmolStr), Deactivated, Takendown, Suspended, } #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) struct Commit { pub version: i64, pub rev: DbTid, pub data: IpldCid, pub prev: Option, #[serde(with = "jacquard_common::serde_bytes_helper")] pub sig: Bytes, } #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(bound(deserialize = "'i: 'de"))] pub(crate) struct RepoState<'i> { pub status: RepoStatus, pub root: Option, pub last_message_time: Option, pub last_updated_at: i64, pub tracked: bool, pub index_id: u64, #[serde(borrow)] pub signing_key: Option>, #[serde(borrow)] pub pds: Option>, pub handle: Option, } #[cfg(test)] mod tests { use super::*; use jacquard_common::types::string::Tid; #[test] fn v2_persisted_schema_golden_fixture() { for (status, golden) in [ (RepoStatus::Backfilling, "ab4261636b66696c6c696e67"), (RepoStatus::Synced, "a653796e636564"), ( RepoStatus::Error("stinkpot".into()), "81a54572726f72a87374696e6b706f74", ), (RepoStatus::Deactivated, "ab4465616374697661746564"), (RepoStatus::Takendown, "a954616b656e646f776e"), (RepoStatus::Suspended, "a953757370656e646564"), ] { let encoded = rmp_serde::to_vec(&status).unwrap(); assert_eq!(hex::encode(&encoded), golden); assert_eq!( rmp_serde::from_slice::(&encoded).unwrap(), status ); } let state = RepoState { status: RepoStatus::Error("stinkpot".into()), root: Some(Commit { version: 3, rev: DbTid::from(&Tid::new("3jzfcijpj2z2a").unwrap()), data: jacquard_repo::mst::util::compute_cid(b"root").unwrap(), prev: None, sig: Bytes::from_static(b"\x01\x02\x03"), }), last_message_time: Some(-1), last_updated_at: 42, tracked: true, index_id: 7, signing_key: Some(DidKey(std::borrow::Cow::Borrowed(&[0xed, 1, 2, 3]))), pds: Some("https://pds.example".into()), handle: Some(Handle::new_static("alice.test").unwrap()), }; let encoded = rmp_serde::to_vec(&state).unwrap(); assert_eq!( hex::encode(&encoded), "9981a54572726f72a87374696e6b706f749503c40817fd6873eaf07c06c424017112204813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2c0c403010203ff2ac307c404ed010203b368747470733a2f2f7064732e6578616d706c65aa616c6963652e74657374" ); let decoded: RepoState<'_> = rmp_serde::from_slice(&encoded).unwrap(); assert!(matches!(&decoded.status, RepoStatus::Error(value) if value == "stinkpot")); let root = decoded.root.unwrap(); assert_eq!(root.version, 3); assert_eq!(root.rev, DbTid::from(&Tid::new("3jzfcijpj2z2a").unwrap())); assert_eq!( root.data, jacquard_repo::mst::util::compute_cid(b"root").unwrap() ); assert!(root.prev.is_none()); assert_eq!(root.sig.as_ref(), b"\x01\x02\x03"); assert_eq!(decoded.last_message_time, Some(-1)); assert_eq!(decoded.last_updated_at, 42); assert!(decoded.tracked); assert_eq!(decoded.index_id, 7); assert_eq!( decoded.signing_key.as_ref().map(|key| key.0.as_ref()), Some([0xed, 1, 2, 3].as_slice()) ); assert_eq!(decoded.pds.as_deref(), Some("https://pds.example")); assert_eq!( decoded.handle.as_ref().map(Handle::as_str), Some("alice.test") ); } }