cloudevents/binding/http/
serializer.rs

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