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