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