use std::ops::Deref;
use anyhow::Result;
use cid::Cid;
use libipld_cbor::DagCborCodec;
use noosphere_storage::BlockStore;
use tokio::sync::OnceCell;
use crate::data::AddressBookIpld;
use super::Identities;
pub struct AddressBook<S: BlockStore> {
cid: Cid,
store: S,
body: OnceCell<AddressBookIpld>,
}
impl<S> AddressBook<S>
where
S: BlockStore,
{
pub fn cid(&self) -> &Cid {
&self.cid
}
pub fn at(cid: &Cid, store: &S) -> Self {
AddressBook {
cid: *cid,
store: store.clone(),
body: OnceCell::new(),
}
}
pub async fn to_body(&self) -> Result<AddressBookIpld> {
Ok(self
.body
.get_or_try_init(|| async { self.store.load::<DagCborCodec, _>(self.cid()).await })
.await?
.clone())
}
pub async fn at_or_empty<C>(cid: Option<C>, store: &mut S) -> Result<AddressBook<S>>
where
C: Deref<Target = Cid>,
{
Ok(match cid {
Some(cid) => Self::at(&cid, store),
None => Self::empty(store).await?,
})
}
pub async fn empty(store: &mut S) -> Result<Self> {
let ipld = AddressBookIpld::empty(store).await?;
let cid = store.save::<DagCborCodec, _>(ipld).await?;
Ok(AddressBook {
cid,
store: store.clone(),
body: OnceCell::new(),
})
}
pub async fn get_identities(&self) -> Result<Identities<S>> {
let ipld = self.to_body().await?;
Ok(Identities::at(&ipld.identities, &self.store.clone()))
}
}