cloudevents/event/v10/
format.rs

1use super::Attributes;
2use crate::event::data::is_json_content_type;
3use crate::event::format::{
4    parse_data_base64, parse_data_base64_json, parse_data_json, parse_data_string,
5};
6use crate::event::{Data, ExtensionValue};
7use base64::prelude::*;
8use chrono::{DateTime, Utc};
9use serde::de::IntoDeserializer;
10use serde::ser::SerializeMap;
11use serde::{Deserialize, Serializer};
12use serde_json::{Map, Value};
13use std::collections::HashMap;
14use url::Url;
15
16pub(crate) struct EventFormatDeserializer {}
17
18impl crate::event::format::EventFormatDeserializer for EventFormatDeserializer {
19    fn deserialize_attributes<E: serde::de::Error>(
20        map: &mut Map<String, Value>,
21    ) -> Result<crate::event::Attributes, E> {
22        Ok(crate::event::Attributes::V10(Attributes {
23            id: extract_field!(map, "id", String, E)?,
24            ty: extract_field!(map, "type", String, E)?,
25            source: extract_field!(map, "source", String, E)?,
26            datacontenttype: extract_optional_field!(map, "datacontenttype", String, E)?,
27            dataschema: extract_optional_field!(map, "dataschema", String, E, |s: String| {
28                Url::parse(&s)
29            })?,
30            subject: extract_optional_field!(map, "subject", String, E)?,
31            time: extract_optional_field!(map, "time", String, E, |s: String| {
32                DateTime::parse_from_rfc3339(&s).map(DateTime::<Utc>::from)
33            })?,
34        }))
35    }
36
37    fn deserialize_data<E: serde::de::Error>(
38        content_type: &str,
39        map: &mut Map<String, Value>,
40    ) -> Result<Option<Data>, E> {
41        let data = map.remove("data");
42        let data_base64 = map.remove("data_base64");
43
44        let is_json = is_json_content_type(content_type);
45
46        Ok(match (data, data_base64, is_json) {
47            (Some(d), None, true) => Some(Data::Json(parse_data_json(d)?)),
48            (Some(d), None, false) => Some(Data::String(parse_data_string(d)?)),
49            (None, Some(d), true) => match parse_data_base64_json::<E>(d.to_owned()) {
50                Ok(x) => Some(Data::Json(x)),
51                Err(_) => Some(Data::Binary(parse_data_base64(d)?)),
52            },
53            (None, Some(d), false) => Some(Data::Binary(parse_data_base64(d)?)),
54            (Some(_), Some(_), _) => {
55                return Err(E::custom("Cannot have both data and data_base64 field"))
56            }
57            (None, None, _) => None,
58        })
59    }
60}
61
62pub(crate) struct EventFormatSerializer {}
63
64impl<S: serde::Serializer> crate::event::format::EventFormatSerializer<S, Attributes>
65    for EventFormatSerializer
66{
67    fn serialize(
68        attributes: &Attributes,
69        data: &Option<Data>,
70        extensions: &HashMap<String, ExtensionValue>,
71        serializer: S,
72    ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error> {
73        let num = 4
74            + [
75                attributes.datacontenttype.is_some(),
76                attributes.dataschema.is_some(),
77                attributes.subject.is_some(),
78                attributes.time.is_some(),
79                data.is_some(),
80            ]
81            .iter()
82            .filter(|&b| *b)
83            .count()
84            + extensions.len();
85
86        let mut state = serializer.serialize_map(Some(num))?;
87        state.serialize_entry("specversion", "1.0")?;
88        state.serialize_entry("id", &attributes.id)?;
89        state.serialize_entry("type", &attributes.ty)?;
90        state.serialize_entry("source", &attributes.source)?;
91        if let Some(datacontenttype) = &attributes.datacontenttype {
92            state.serialize_entry("datacontenttype", datacontenttype)?;
93        }
94        if let Some(dataschema) = &attributes.dataschema {
95            state.serialize_entry("dataschema", dataschema)?;
96        }
97        if let Some(subject) = &attributes.subject {
98            state.serialize_entry("subject", subject)?;
99        }
100        if let Some(time) = &attributes.time {
101            state.serialize_entry("time", time)?;
102        }
103        match data {
104            Some(Data::Json(j)) => state.serialize_entry("data", j)?,
105            Some(Data::String(s)) => state.serialize_entry("data", s)?,
106            Some(Data::Binary(v)) => {
107                state.serialize_entry("data_base64", &BASE64_STANDARD.encode(v))?
108            }
109            _ => (),
110        };
111        for (k, v) in extensions {
112            state.serialize_entry(k, v)?;
113        }
114        state.end()
115    }
116}