dwn_core/message/descriptor/
mod.rs1use std::fmt::Display;
2
3use serde::{Deserialize, Deserializer, Serialize};
4use serde_json::Value;
5
6mod protocols;
7mod records;
8
9pub use protocols::*;
10pub use records::*;
11use time::OffsetDateTime;
12
13use super::cid::{CidGenerationError, compute_cid_cbor};
14
15#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
16#[serde(untagged)]
17pub enum Descriptor {
18 ProtocolsConfigure(Box<ProtocolsConfigure>),
19 ProtocolsQuery(Box<ProtocolsQuery>),
20 RecordsDelete(Box<RecordsDelete>),
21 RecordsQuery(Box<RecordsQuery>),
22 RecordsRead(Box<RecordsRead>),
23 RecordsSync(Box<RecordsSync>),
24 RecordsWrite(Box<RecordsWrite>),
25}
26
27impl Descriptor {
28 pub fn compute_entry_id(&self) -> Result<String, CidGenerationError> {
29 #[derive(Serialize)]
30 #[serde(rename_all = "camelCase")]
31 struct RecordIdGeneration {
32 descriptor_cid: String,
33 }
34
35 let generator = RecordIdGeneration {
36 descriptor_cid: compute_cid_cbor(self)?,
37 };
38
39 compute_cid_cbor(&generator)
40 }
41
42 pub fn message_timestamp(&self) -> Option<&OffsetDateTime> {
43 match self {
44 Descriptor::ProtocolsConfigure(_) => None,
45 Descriptor::ProtocolsQuery(_) => None,
46 Descriptor::RecordsDelete(d) => Some(&d.message_timestamp),
47 Descriptor::RecordsQuery(d) => Some(&d.message_timestamp),
48 Descriptor::RecordsRead(d) => Some(&d.message_timestamp),
49 Descriptor::RecordsSync(d) => Some(&d.message_timestamp),
50 Descriptor::RecordsWrite(d) => Some(&d.message_timestamp),
51 }
52 }
53}
54
55impl<'de> Deserialize<'de> for Descriptor {
56 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57 where
58 D: Deserializer<'de>,
59 {
60 let raw = Value::deserialize(deserializer)?;
61
62 let Some(interface) = raw.get("interface") else {
63 return Err(serde::de::Error::custom("no interface"));
64 };
65 let interface = serde_json::from_value::<Interface>(interface.clone())
66 .map_err(|_| serde::de::Error::custom("unsupported interface"))?;
67
68 let Some(method) = raw.get("method") else {
69 return Err(serde::de::Error::custom("no method"));
70 };
71 let method = serde_json::from_value::<Method>(method.clone())
72 .map_err(|_| serde::de::Error::custom("unsupported method"))?;
73
74 match (interface, method) {
75 (Interface::Protocols, Method::Configure) => {
76 let desc: ProtocolsConfigure =
77 serde_json::from_value(raw).map_err(serde::de::Error::custom)?;
78 Ok(Descriptor::ProtocolsConfigure(Box::new(desc)))
79 }
80 (Interface::Protocols, Method::Query) => {
81 let desc: ProtocolsQuery =
82 serde_json::from_value(raw).map_err(serde::de::Error::custom)?;
83 Ok(Descriptor::ProtocolsQuery(Box::new(desc)))
84 }
85 (Interface::Records, Method::Query) => {
86 let desc: RecordsQuery =
87 serde_json::from_value(raw).map_err(serde::de::Error::custom)?;
88 Ok(Descriptor::RecordsQuery(Box::new(desc)))
89 }
90 (Interface::Records, Method::Read) => {
91 let desc: RecordsRead =
92 serde_json::from_value(raw).map_err(serde::de::Error::custom)?;
93 Ok(Descriptor::RecordsRead(Box::new(desc)))
94 }
95 (Interface::Records, Method::Sync) => {
96 let desc: RecordsSync =
97 serde_json::from_value(raw).map_err(serde::de::Error::custom)?;
98 Ok(Descriptor::RecordsSync(Box::new(desc)))
99 }
100 (Interface::Records, Method::Write) => {
101 let desc: RecordsWrite =
102 serde_json::from_value(raw).map_err(serde::de::Error::custom)?;
103 Ok(Descriptor::RecordsWrite(Box::new(desc)))
104 }
105 _ => Err(serde::de::Error::custom(
106 "Unsupported interface / method combination",
107 )),
108 }
109 }
110}
111
112#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
113pub enum Interface {
114 Protocols,
115 Records,
116}
117
118impl Display for Interface {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 write!(f, "{:?}", self)
121 }
122}
123
124#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
125pub enum Method {
126 Configure,
127 Delete,
128 Query,
129 Read,
130 Sync,
131 Write,
132}
133
134impl Display for Method {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 write!(f, "{:?}", self)
137 }
138}
139
140#[cfg(test)]
141mod test {
142 use mime::TEXT_PLAIN;
143 use semver::Version;
144
145 use crate::message::Message;
146
147 use super::*;
148
149 #[test]
150 fn test_serialize_records_query() {
151 let msg = RecordsQueryBuilder {
152 filter: RecordFilter {
153 schema: Some("schema".to_string()),
154 protocol: Some("protocol".to_string()),
155 protocol_version: Some(Version::new(1, 2, 3)),
156 record_id: Some("record id".to_string()),
157 ..Default::default()
158 },
159 }
160 .build()
161 .unwrap();
162 let ser = serde_json::to_string_pretty(&msg).unwrap();
163 println!("{}", ser);
164 let des = serde_json::from_str::<Message>(&ser).unwrap();
165 assert_eq!(des, msg);
166 }
167
168 #[test]
169 fn test_serialize_records_read() {
170 let msg = RecordsReadBuilder::new("test".to_string()).build().unwrap();
171 let ser = serde_json::to_string_pretty(&msg).unwrap();
172 println!("{}", ser);
173 let des = serde_json::from_str::<Message>(&ser).unwrap();
174 assert_eq!(des, msg);
175 }
176
177 #[test]
178 fn test_serialize_records_write() {
179 let msg = RecordsWriteBuilder {
180 context_id: None,
181 data: Some(vec![0, 1, 2, 3]),
182 data_format: Some(TEXT_PLAIN),
183 protocol: Some("protocol".to_string()),
184 protocol_version: Some(Version::new(1, 2, 3)),
185 protocol_path: Some("protocol path".to_string()),
186 published: Some(true),
187 record_id: Some("record id".to_string()),
188 schema: Some("schema".to_string()),
189 }
190 .build()
191 .unwrap();
192 let ser = serde_json::to_string_pretty(&msg).unwrap();
193 println!("{}", ser);
194 let des = serde_json::from_str::<Message>(&ser).unwrap();
195 assert_eq!(des, msg);
196 }
197}