cloudevents/binding/http_0_2/
serializer.rs

1use std::{cell::RefCell, rc::Rc};
2
3use crate::binding::http_0_2::builder::Builder;
4use crate::binding::{
5    http_0_2::{header_prefix, SPEC_VERSION_HEADER},
6    CLOUDEVENTS_JSON_HEADER,
7};
8use crate::event::SpecVersion;
9use crate::message::BinaryDeserializer;
10use crate::message::{
11    BinarySerializer, Error, MessageAttributeValue, Result, StructuredSerializer,
12};
13use crate::Event;
14use http::Request;
15use http_0_2 as http;
16use std::convert::TryFrom;
17use std::fmt::Debug;
18
19macro_rules! str_to_header_value {
20    ($header_value:expr) => {
21        http::header::HeaderValue::from_str(&$header_value.to_string()).map_err(|e| {
22            crate::message::Error::Other {
23                source: Box::new(e),
24            }
25        })
26    };
27}
28
29pub struct Serializer<T> {
30    builder: Rc<RefCell<dyn Builder<T>>>,
31}
32
33impl<T> Serializer<T> {
34    pub fn new<B: Builder<T> + 'static>(delegate: B) -> Serializer<T> {
35        let builder = Rc::new(RefCell::new(delegate));
36        Serializer { builder }
37    }
38}
39
40impl<T> BinarySerializer<T> for Serializer<T> {
41    fn set_spec_version(self, spec_version: SpecVersion) -> Result<Self> {
42        self.builder
43            .borrow_mut()
44            .header(SPEC_VERSION_HEADER, str_to_header_value!(spec_version)?);
45        Ok(self)
46    }
47
48    fn set_attribute(self, name: &str, value: MessageAttributeValue) -> Result<Self> {
49        self.builder
50            .borrow_mut()
51            .header(&header_prefix(name), str_to_header_value!(value)?);
52        Ok(self)
53    }
54
55    fn set_extension(self, name: &str, value: MessageAttributeValue) -> Result<Self> {
56        self.builder
57            .borrow_mut()
58            .header(&header_prefix(name), str_to_header_value!(value)?);
59        Ok(self)
60    }
61
62    fn end_with_data(self, bytes: Vec<u8>) -> Result<T> {
63        self.builder.borrow_mut().body(bytes)
64    }
65
66    fn end(self) -> Result<T> {
67        self.builder.borrow_mut().finish()
68    }
69}
70
71impl<T> StructuredSerializer<T> for Serializer<T> {
72    fn set_structured_event(self, bytes: Vec<u8>) -> Result<T> {
73        let mut builder = self.builder.borrow_mut();
74        builder.header(
75            http::header::CONTENT_TYPE.as_str(),
76            http::HeaderValue::from_static(CLOUDEVENTS_JSON_HEADER),
77        );
78        builder.body(bytes)
79    }
80}
81
82impl<T> BinarySerializer<http::request::Request<Option<T>>> for http::request::Builder
83where
84    T: TryFrom<Vec<u8>>,
85    <T as TryFrom<Vec<u8>>>::Error: Debug,
86{
87    fn set_spec_version(mut self, sv: SpecVersion) -> Result<Self> {
88        self = self.header(SPEC_VERSION_HEADER, &sv.to_string());
89        Ok(self)
90    }
91
92    fn set_attribute(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
93        let key = &header_prefix(name);
94        self = self.header(key, &value.to_string());
95        Ok(self)
96    }
97
98    fn set_extension(mut self, name: &str, value: MessageAttributeValue) -> Result<Self> {
99        let key = &header_prefix(name);
100        self = self.header(key, &value.to_string());
101        Ok(self)
102    }
103
104    fn end_with_data(self, bytes: Vec<u8>) -> Result<http::request::Request<Option<T>>> {
105        let body = T::try_from(bytes).unwrap();
106        self.body(Some(body)).map_err(|e| Error::Other {
107            source: Box::new(e),
108        })
109    }
110
111    fn end(self) -> Result<http::request::Request<Option<T>>> {
112        self.body(None).map_err(|e| Error::Other {
113            source: Box::new(e),
114        })
115    }
116}
117
118impl<T> TryFrom<Event> for Request<Option<T>>
119where
120    T: TryFrom<Vec<u8>>,
121    <T as TryFrom<Vec<u8>>>::Error: Debug,
122{
123    type Error = crate::message::Error;
124
125    fn try_from(event: Event) -> Result<Self> {
126        BinaryDeserializer::deserialize_binary(event, http::request::Builder::new())
127    }
128}
129
130#[cfg(test)]
131mod tests {
132    use crate::test::fixtures;
133    use bytes::Bytes;
134    use http::Request;
135    use http_0_2 as http;
136    use std::convert::TryFrom;
137
138    #[test]
139    fn test_event_to_http_request() {
140        let event = fixtures::v10::minimal_string_extension();
141        let request: Request<Option<Vec<u8>>> = Request::try_from(event).unwrap();
142
143        assert_eq!(request.headers()["ce-id"], "0001");
144        assert_eq!(request.headers()["ce-type"], "test_event.test_application");
145    }
146
147    #[test]
148    fn test_event_to_bytes_body() {
149        let event = fixtures::v10::full_binary_json_data_string_extension();
150        let request: Request<Option<Vec<u8>>> = Request::try_from(event).unwrap();
151
152        assert_eq!(request.headers()["ce-id"], "0001");
153        assert_eq!(request.headers()["ce-type"], "test_event.test_application");
154        assert_eq!(
155            request.body().as_ref().unwrap(),
156            &Bytes::from(fixtures::json_data().to_string())
157        );
158    }
159}