cloudevents/binding/http/
serializer.rs1use 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}