use std::sync::Arc; use anyhow::Result; use crate::backend::Id; use crate::backend::Node; #[derive(Clone)] pub struct IpfsEmbedBackend { ipfs: Arc>, } impl IpfsEmbedBackend { pub fn ipfs(&self) -> Arc> { self.ipfs.clone() } } #[async_trait::async_trait] impl daglib::DagBackend for IpfsEmbedBackend { async fn get(&self, id: Id) -> Result> { log::trace!("GET {:?}", id); let block = self.ipfs.fetch(id.as_ref(), self.ipfs.peers()).await?; let node = block.decode::()?; Ok(Some((id, node))) } async fn put(&mut self, node: Node) -> Result { log::trace!("PUT {:?}", node); let block = libipld::block::Block::encode(libipld::cbor::DagCborCodec, libipld::multihash::Code::Blake3_256, &node)?; let cid = Id::from(block.cid().clone()); self.ipfs .insert(&block) .map(|_| cid) } } impl IpfsEmbedBackend { pub async fn new_in_memory(cache_size: u64) -> Result { let in_memory = None; // that's how it works... let config = ipfs_embed::Config::new(in_memory, cache_size); ipfs_embed::Ipfs::new(config).await.map(Arc::new).map(|ipfs| IpfsEmbedBackend { ipfs }) } pub async fn new_with_config(cfg: ipfs_embed::Config) -> Result { ipfs_embed::Ipfs::new(cfg) .await .map(Arc::new) .map(|ipfs| IpfsEmbedBackend { ipfs }) } pub async fn write_payload(&self, payload: &crate::backend::Payload) -> Result { log::trace!("Write payload: {:?}", payload); let block = libipld::block::Block::encode(libipld::cbor::DagCborCodec, libipld::multihash::Code::Blake3_256, &payload)?; log::trace!("Block = {:?}", block); let _ = self.ipfs.insert(&block)?; log::trace!("Inserted. CID = {}", block.cid()); Ok(block.cid().clone()) } pub async fn get_payload(&self, cid: &cid::Cid) -> Result { let block = self.ipfs.fetch(cid, self.ipfs.peers()).await?; log::trace!("Block = {:?}", block); let payload = block.decode::()?; log::trace!("Payload = {:?}", payload); Ok(payload) } } #[cfg(test)] mod tests { use super::*; use crate::backend::Payload; #[tokio::test] async fn test_roundtrip_payload() { let backend = IpfsEmbedBackend::new_in_memory(1024).await.unwrap(); let cid = backend.write_payload(&Payload::now_from_text(String::from("test"))).await.unwrap(); let payload = backend.ipfs().fetch(&cid, backend.ipfs().peers()).await.unwrap(); let payload = payload.decode::().unwrap(); assert_eq!(payload.content(), "test".as_bytes()) } }