mod mh_code;
mod prefix;
mod to_cid;
pub use self::mh_code::{Code, Multihash, POSEIDON_BLS12_381_A1_FC1, SHA2_256_TRUNC254_PADDED};
pub use self::prefix::Prefix;
use cid::CidGeneric;
pub use cid::{Error, Version};
pub use multihash;
use multihash::MultihashDigest;
use std::convert::TryFrom;
use std::fmt;
#[cfg(feature = "cbor")]
use serde::{de, ser};
#[cfg(feature = "cbor")]
use serde_cbor::tags::Tagged;
#[cfg(feature = "cbor")]
const CBOR_TAG_CID: u64 = 42;
#[cfg(feature = "cbor")]
const MULTIBASE_IDENTITY: u8 = 0;
#[cfg(feature = "json")]
pub mod json;
pub const DAG_CBOR: u64 = 0x71;
pub const FIL_COMMITMENT_SEALED: u64 = 0xf102;
pub const FIL_COMMITMENT_UNSEALED: u64 = 0xf101;
pub const RAW: u64 = 0x55;
pub fn new_from_cbor(bz: &[u8], code: Code) -> Cid {
let hash = code.digest(bz);
Cid::new_v1(DAG_CBOR, hash)
}
pub fn new_from_prefix(prefix: &Prefix, data: &[u8]) -> Result<Cid, Error> {
let hash: Multihash = Code::try_from(prefix.mh_type)?.digest(data);
Cid::new(prefix.version, prefix.codec, hash)
}
#[derive(PartialEq, Eq, Clone, Copy, Default, Hash, PartialOrd, Ord)]
pub struct Cid(CidGeneric<multihash::U32>);
impl Cid {
pub fn new(version: Version, codec: u64, hash: Multihash) -> Result<Self, Error> {
Ok(Cid(CidGeneric::new(version, codec, hash)?))
}
pub fn new_v1(codec: u64, hash: Multihash) -> Self {
Cid(CidGeneric::new_v1(codec, hash))
}
pub fn version(&self) -> Version {
self.0.version()
}
pub fn codec(&self) -> u64 {
self.0.codec()
}
pub fn hash(&self) -> &Multihash {
&self.0.hash()
}
pub fn read_bytes<R: std::io::Read>(reader: R) -> Result<Self, Error> {
Ok(Cid(CidGeneric::read_bytes(reader)?))
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes()
}
}
#[cfg(feature = "cbor")]
impl ser::Serialize for Cid {
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
let mut cid_bytes = self.to_bytes();
cid_bytes.insert(0, MULTIBASE_IDENTITY);
let value = serde_bytes::Bytes::new(&cid_bytes);
Tagged::new(Some(CBOR_TAG_CID), &value).serialize(s)
}
}
#[cfg(feature = "cbor")]
impl<'de> de::Deserialize<'de> for Cid {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
let tagged = Tagged::<serde_bytes::ByteBuf>::deserialize(deserializer)?;
match tagged.tag {
Some(CBOR_TAG_CID) | None => {
let mut bz = tagged.value.into_vec();
if bz.first() == Some(&MULTIBASE_IDENTITY) {
bz.remove(0);
}
Ok(Cid::try_from(bz)
.map_err(|e| de::Error::custom(format!("Failed to deserialize Cid: {}", e)))?)
}
Some(_) => Err(de::Error::custom("unexpected tag")),
}
}
}
impl fmt::Display for Cid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for Cid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Cid(\"{}\")", self)
}
}