1mod mh_code;
5mod prefix;
6mod to_cid;
7
8pub use self::mh_code::{Code, Multihash, POSEIDON_BLS12_381_A1_FC1, SHA2_256_TRUNC254_PADDED};
9pub use self::prefix::Prefix;
10use cid::CidGeneric;
11pub use cid::{Error, Version};
12pub use multihash;
13use multihash::MultihashDigest;
14use std::convert::TryFrom;
15use std::fmt;
16
17#[cfg(feature = "cbor")]
18use serde::{de, ser};
19#[cfg(feature = "cbor")]
20use serde_cbor::tags::Tagged;
21
22#[cfg(feature = "cbor")]
23const CBOR_TAG_CID: u64 = 42;
24#[cfg(feature = "cbor")]
27const MULTIBASE_IDENTITY: u8 = 0;
28
29#[cfg(feature = "json")]
30pub mod json;
31
32pub const DAG_CBOR: u64 = 0x71;
33pub const FIL_COMMITMENT_SEALED: u64 = 0xf102;
34pub const FIL_COMMITMENT_UNSEALED: u64 = 0xf101;
35pub const RAW: u64 = 0x55;
36
37pub fn new_from_cbor(bz: &[u8], code: Code) -> Cid {
39 let hash = code.digest(bz);
40 Cid::new_v1(DAG_CBOR, hash)
41}
42
43pub fn new_from_prefix(prefix: &Prefix, data: &[u8]) -> Result<Cid, Error> {
45 let hash: Multihash = Code::try_from(prefix.mh_type)?.digest(data);
46 Cid::new(prefix.version, prefix.codec, hash)
47}
48
49#[derive(PartialEq, Eq, Clone, Copy, Default, Hash, PartialOrd, Ord)]
50pub struct Cid(CidGeneric<multihash::U32>);
51
52impl Cid {
55 pub fn new(version: Version, codec: u64, hash: Multihash) -> Result<Self, Error> {
57 Ok(Cid(CidGeneric::new(version, codec, hash)?))
58 }
59
60 pub fn new_v1(codec: u64, hash: Multihash) -> Self {
62 Cid(CidGeneric::new_v1(codec, hash))
63 }
64
65 pub fn version(&self) -> Version {
67 self.0.version()
68 }
69
70 pub fn codec(&self) -> u64 {
72 self.0.codec()
73 }
74
75 pub fn hash(&self) -> &Multihash {
77 &self.0.hash()
78 }
79
80 pub fn read_bytes<R: std::io::Read>(reader: R) -> Result<Self, Error> {
82 Ok(Cid(CidGeneric::read_bytes(reader)?))
83 }
84
85 pub fn to_bytes(&self) -> Vec<u8> {
87 self.0.to_bytes()
88 }
89}
90
91#[cfg(feature = "cbor")]
92impl ser::Serialize for Cid {
93 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
94 where
95 S: ser::Serializer,
96 {
97 let mut cid_bytes = self.to_bytes();
98
99 cid_bytes.insert(0, MULTIBASE_IDENTITY);
101
102 let value = serde_bytes::Bytes::new(&cid_bytes);
103 Tagged::new(Some(CBOR_TAG_CID), &value).serialize(s)
104 }
105}
106
107#[cfg(feature = "cbor")]
108impl<'de> de::Deserialize<'de> for Cid {
109 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110 where
111 D: de::Deserializer<'de>,
112 {
113 let tagged = Tagged::<serde_bytes::ByteBuf>::deserialize(deserializer)?;
114 match tagged.tag {
115 Some(CBOR_TAG_CID) | None => {
116 let mut bz = tagged.value.into_vec();
117
118 if bz.first() == Some(&MULTIBASE_IDENTITY) {
119 bz.remove(0);
120 }
121
122 Ok(Cid::try_from(bz)
123 .map_err(|e| de::Error::custom(format!("Failed to deserialize Cid: {}", e)))?)
124 }
125 Some(_) => Err(de::Error::custom("unexpected tag")),
126 }
127 }
128}
129
130impl fmt::Display for Cid {
131 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132 write!(f, "{}", self.0)
133 }
134}
135
136impl fmt::Debug for Cid {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 write!(f, "Cid(\"{}\")", self)
139 }
140}