dwn_core/message/descriptor/
mod.rs

1use 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}