noosphere_storage/
encoding.rs

1use anyhow::Result;
2use base64::prelude::{Engine, BASE64_URL_SAFE_NO_PAD};
3use cid::{
4    multihash::{Code, MultihashDigest},
5    Cid,
6};
7use libipld_core::{
8    codec::{Codec, Decode, Encode},
9    ipld::Ipld,
10    serde::{from_ipld, to_ipld},
11};
12use serde::{de::DeserializeOwned, Serialize};
13
14/// Encode some bytes as an unpadded URL-safe base64 string
15pub fn base64_encode(data: &[u8]) -> Result<String> {
16    Ok(BASE64_URL_SAFE_NO_PAD.encode(data))
17}
18
19/// Decode some bytes from an unpadded URL-safe base64 string
20pub fn base64_decode(encoded: &str) -> Result<Vec<u8>> {
21    BASE64_URL_SAFE_NO_PAD
22        .decode(encoded)
23        .map_err(anyhow::Error::from)
24}
25
26/// Produces a CID for a block with a Blake3_256 hash; note that the bytes are
27/// presumed to be encoded with the specified codec (honor system; this is
28/// not validated in any way).
29pub fn derive_cid<C>(block: &[u8]) -> Cid
30where
31    C: Codec + Default,
32    u64: From<C>,
33{
34    Cid::new_v1(u64::from(C::default()), Code::Blake3_256.digest(block))
35}
36
37/// Encode any encodable type as a block using the specified codec
38pub fn block_encode<C, T>(encodable: &T) -> Result<(Cid, Vec<u8>)>
39where
40    C: Codec + Default,
41    T: Encode<C>,
42    u64: From<C>,
43{
44    let codec = C::default();
45    let block = codec.encode(encodable)?;
46
47    Ok((derive_cid(&block), block))
48}
49
50/// Decode any block as IPLD using the specified codec
51pub fn block_decode<C, Ipld>(block: &[u8]) -> Result<Ipld>
52where
53    C: Codec + Default,
54    Ipld: Decode<C>,
55{
56    C::default().decode::<Ipld>(block)
57}
58
59/// Encode any serializable type as a block using the specified codec
60pub fn block_serialize<C, T>(any: T) -> Result<(Cid, Vec<u8>)>
61where
62    C: Codec + Default,
63    T: Serialize,
64    Ipld: Encode<C>,
65    u64: From<C>,
66{
67    block_encode(&to_ipld(any)?)
68}
69
70/// Decode any block as a deserializable type using the specified codec
71pub fn block_deserialize<C, T>(block: &[u8]) -> Result<T>
72where
73    C: Codec + Default,
74    T: DeserializeOwned,
75    Ipld: Decode<C>,
76{
77    Ok(from_ipld(block_decode(block)?)?)
78}