atrium_api/types/
cid_link.rs1use ipld_core::cid::{Cid, Error};
2use ipld_core::ipld::Ipld;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct CidLink(pub Cid);
8
9#[derive(Serialize, Deserialize)]
10struct Link {
11 #[serde(rename = "$link")]
12 link: crate::types::string::Cid,
13}
14
15impl Serialize for CidLink {
16 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
17 if serializer.is_human_readable() {
18 Link { link: crate::types::string::Cid::new(self.0) }.serialize(serializer)
19 } else {
20 self.0.serialize(serializer)
21 }
22 }
23}
24
25impl<'de> Deserialize<'de> for CidLink {
26 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
27 let ipld = Ipld::deserialize(deserializer)?;
28 match &ipld {
29 Ipld::Link(cid) => {
30 return Ok(Self(*cid));
31 }
32 Ipld::Map(map) => {
33 if map.len() == 1 {
34 if let Some(Ipld::String(link)) = map.get("$link") {
35 return Ok(Self(
36 Cid::try_from(link.as_str()).map_err(serde::de::Error::custom)?,
37 ));
38 }
39 }
40 }
41 _ => {}
42 }
43 Err(serde::de::Error::custom("Invalid cid-link"))
44 }
45}
46
47impl TryFrom<&str> for CidLink {
48 type Error = Error;
49
50 fn try_from(s: &str) -> Result<Self, Self::Error> {
51 Ok(Self(Cid::try_from(s)?))
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use serde_ipld_dagcbor::{from_slice, to_vec};
59 use serde_json::{from_str, to_string};
60
61 const CID_LINK_JSON: &str =
62 r#"{"$link":"bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy"}"#;
63
64 const CID_LINK_DAGCBOR: [u8; 41] = [
65 0xd8, 0x2a, 0x58, 0x25, 0x00, 0x01, 0x55, 0x12, 0x20, 0x2c, 0x26, 0xb4, 0x6b, 0x68, 0xff,
66 0xc6, 0x8f, 0xf9, 0x9b, 0x45, 0x3c, 0x1d, 0x30, 0x41, 0x34, 0x13, 0x42, 0x2d, 0x70, 0x64,
67 0x83, 0xbf, 0xa0, 0xf9, 0x8a, 0x5e, 0x88, 0x62, 0x66, 0xe7, 0xae,
68 ];
69
70 fn cid() -> Cid {
71 Cid::try_from("bafkreibme22gw2h7y2h7tg2fhqotaqjucnbc24deqo72b6mkl2egezxhvy").unwrap()
72 }
73
74 #[test]
75 fn test_cid_link_serialize_json() {
76 let cid_link = CidLink(cid());
77
78 let serialized = to_string(&cid_link).expect("failed to serialize cid-link");
79 assert_eq!(serialized, CID_LINK_JSON);
80 }
81
82 #[test]
83 fn test_cid_link_serialize_dagcbor() {
84 let cid_link = CidLink(cid());
85
86 let serialized = to_vec(&cid_link).expect("failed to serialize cid-link");
87 assert_eq!(serialized, CID_LINK_DAGCBOR);
88 }
89
90 #[test]
91 fn test_cid_link_deserialize_json() {
92 let deserialized =
93 from_str::<CidLink>(CID_LINK_JSON).expect("failed to deserialize cid-link");
94
95 assert_eq!(deserialized, CidLink(cid()));
96 }
97
98 #[test]
99 fn test_cid_link_deserialize_dagcbor() {
100 let deserialized =
101 from_slice::<CidLink>(&CID_LINK_DAGCBOR).expect("failed to deserialize cid-link");
102
103 assert_eq!(deserialized, CidLink(cid()));
104 }
105
106 #[test]
107 fn test_cid_link_deserialize_any_json() {
108 #[derive(Deserialize, Debug, PartialEq, Eq)]
109 #[serde(untagged)]
110 enum Enum {
111 CidLink(CidLink),
112 }
113
114 let deserialized = from_str::<Enum>(CID_LINK_JSON).expect("failed to deserialize cid-link");
115 assert_eq!(deserialized, Enum::CidLink(CidLink(cid())));
116 }
117
118 #[test]
119 fn test_cid_link_deserialize_any_dagcbor() {
120 #[derive(Deserialize, Debug, PartialEq, Eq)]
121 #[serde(untagged)]
122 enum Enum {
123 CidLink(CidLink),
124 }
125
126 let deserialized =
127 from_slice::<Enum>(&CID_LINK_DAGCBOR).expect("failed to deserialize cid-link");
128 assert_eq!(deserialized, Enum::CidLink(CidLink(cid())));
129 }
130
131 #[test]
132 fn test_cid_link_serde_json() {
133 let cid_link = CidLink(cid());
139 let serialized = to_string(&cid_link).expect("failed to serialize cid-link");
140 let deserialized =
141 from_str::<CidLink>(&serialized).expect("failed to deserialize cid-link");
142 assert_eq!(deserialized, cid_link);
143 }
144
145 #[test]
146 fn test_cid_link_serde_dagcbor() {
147 let deserialized =
148 from_slice::<Cid>(&CID_LINK_DAGCBOR).expect("failed to deserialize cid-link");
149 let serialized = to_vec(&deserialized).expect("failed to serialize cid-link");
150 assert_eq!(serialized, CID_LINK_DAGCBOR);
151
152 let cid_link = CidLink(cid());
153 let serialized = to_vec(&cid_link).expect("failed to serialize cid-link");
154 let deserialized =
155 from_slice::<CidLink>(&serialized).expect("failed to deserialize cid-link");
156 assert_eq!(deserialized, cid_link);
157 }
158}