pub use sn_data_types::register::{Entry, EntryHash};
use crate::{Error, Result, Safe};
use log::debug;
use sn_url::{SafeContentType, SafeUrl, XorUrl};
use std::collections::BTreeSet;
use xor_name::XorName;
impl Safe {
pub async fn register_create(
&self,
name: Option<XorName>,
type_tag: u64,
private: bool,
) -> Result<XorUrl> {
let xorname = self
.safe_client
.store_register(name, type_tag, None, private)
.await?;
let xorurl = SafeUrl::encode_register(
xorname,
type_tag,
SafeContentType::Raw,
self.xorurl_base,
private,
)?;
Ok(xorurl)
}
pub async fn register_read(&self, url: &str) -> Result<BTreeSet<(EntryHash, Entry)>> {
debug!("Getting Public Register data from: {:?}", url);
let (safeurl, _) = self.parse_and_resolve_url(url).await?;
self.fetch_register_entries(&safeurl).await
}
pub async fn register_read_entry(&self, url: &str, hash: EntryHash) -> Result<Entry> {
debug!("Getting Public Register data from: {:?}", url);
let (safeurl, _) = self.parse_and_resolve_url(url).await?;
self.fetch_register_entry(&safeurl, hash).await
}
pub(crate) async fn fetch_register_entries(
&self,
safeurl: &SafeUrl,
) -> Result<BTreeSet<(EntryHash, Entry)>> {
let address = safeurl.register_address()?;
match self.safe_client.read_register(address).await {
Ok(data) => {
debug!("Register retrieved...");
Ok(data)
}
Err(Error::EmptyContent(_)) => Err(Error::EmptyContent(format!(
"Register found at \"{}\" was empty",
safeurl
))),
Err(Error::ContentNotFound(_)) => Err(Error::ContentNotFound(
"No Register found at this address".to_string(),
)),
other => other,
}
}
pub(crate) async fn fetch_register_entry(
&self,
safeurl: &SafeUrl,
hash: EntryHash,
) -> Result<Entry> {
let address = safeurl.register_address()?;
self.safe_client.get_register_entry(address, hash).await
}
pub async fn write_to_register(
&self,
url: &str,
data: Vec<u8>,
parents: BTreeSet<EntryHash>,
) -> Result<EntryHash> {
let (safeurl, _) = self.parse_and_resolve_url(url).await?;
let address = safeurl.register_address()?;
self.safe_client
.write_to_register(address, data, parents)
.await
}
}
#[cfg(test)]
mod tests {
use crate::{api::app::test_helpers::new_safe_instance, retry_loop};
use anyhow::Result;
#[tokio::test]
async fn test_register_create() -> Result<()> {
let safe = new_safe_instance().await?;
let xorurl = safe.register_create(None, 25_000, false).await?;
let xorurl_priv = safe.register_create(None, 25_000, true).await?;
let received_data = retry_loop!(safe.register_read(&xorurl));
let received_data_priv = retry_loop!(safe.register_read(&xorurl_priv));
assert!(received_data.is_empty());
assert!(received_data_priv.is_empty());
let initial_data = b"initial data";
let hash = safe
.write_to_register(&xorurl, initial_data.to_vec(), Default::default())
.await?;
let hash_priv = safe
.write_to_register(&xorurl_priv, initial_data.to_vec(), Default::default())
.await?;
let received_entry = retry_loop!(safe.register_read_entry(&xorurl, hash));
let received_entry_priv = retry_loop!(safe.register_read_entry(&xorurl_priv, hash_priv));
assert_eq!(received_entry, initial_data.to_vec());
assert_eq!(received_entry_priv, initial_data.to_vec());
Ok(())
}
}