strut_rabbitmq/repr/ingress/
header.rs1use crate::util::Morph;
2use lapin::types::AMQPValue;
3use serde::de::{Error, Visitor};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use std::fmt::Formatter;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub enum Header {
23 Boolean(bool),
25 Int(i32),
27 UInt(u32),
29 String(String),
31}
32
33impl Serialize for Header {
34 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
35 where
36 S: Serializer,
37 {
38 match self {
39 Self::Boolean(b) => serializer.serialize_bool(*b),
40 Self::Int(i) => serializer.serialize_i32(*i),
41 Self::UInt(u) => serializer.serialize_u32(*u),
42 Self::String(s) => serializer.serialize_str(s),
43 }
44 }
45}
46
47impl<'de> Deserialize<'de> for Header {
48 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
49 where
50 D: Deserializer<'de>,
51 {
52 deserializer.deserialize_any(HeaderVisitor)
53 }
54}
55
56struct HeaderVisitor;
57
58impl<'de> Visitor<'de> for HeaderVisitor {
59 type Value = Header;
60
61 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
62 formatter.write_str("a RabbitMQ header value: a boolean, an integer, or a string")
63 }
64
65 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
66 where
67 E: Error,
68 {
69 Ok(Header::Boolean(value))
70 }
71
72 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
73 where
74 E: Error,
75 {
76 Ok(Header::Int(value.try_into().map_err(E::custom)?))
77 }
78
79 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
80 where
81 E: Error,
82 {
83 Ok(Header::UInt(value.try_into().map_err(E::custom)?))
84 }
85
86 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
87 where
88 E: Error,
89 {
90 Ok(Header::String(value.to_string()))
91 }
92
93 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
94 where
95 E: Error,
96 {
97 Ok(Header::String(value))
98 }
99}
100
101impl Header {
102 pub fn is_empty(&self) -> bool {
106 match self {
107 Header::String(s) => s.is_empty(),
108 _ => false,
109 }
110 }
111}
112
113impl From<Header> for AMQPValue {
114 fn from(value: Header) -> Self {
115 match value {
116 Header::Boolean(b) => AMQPValue::morph(b),
117 Header::Int(i) => AMQPValue::morph(i),
118 Header::UInt(u) => AMQPValue::morph(u),
119 Header::String(s) => AMQPValue::morph(s),
120 }
121 }
122}
123
124impl From<bool> for Header {
125 fn from(value: bool) -> Self {
126 Self::Boolean(value)
127 }
128}
129
130impl From<i8> for Header {
131 fn from(value: i8) -> Self {
132 Self::Int(value as i32)
133 }
134}
135
136impl From<i16> for Header {
137 fn from(value: i16) -> Self {
138 Self::Int(value as i32)
139 }
140}
141
142impl From<i32> for Header {
143 fn from(value: i32) -> Self {
144 Self::Int(value)
145 }
146}
147
148impl From<u8> for Header {
149 fn from(value: u8) -> Self {
150 Self::UInt(value as u32)
151 }
152}
153
154impl From<u16> for Header {
155 fn from(value: u16) -> Self {
156 Self::UInt(value as u32)
157 }
158}
159
160impl From<u32> for Header {
161 fn from(value: u32) -> Self {
162 Self::UInt(value)
163 }
164}
165
166impl From<&str> for Header {
167 fn from(value: &str) -> Self {
168 Self::String(value.into())
169 }
170}
171
172impl From<String> for Header {
173 fn from(value: String) -> Self {
174 Self::String(value)
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181 use pretty_assertions::assert_eq;
182
183 #[test]
184 fn serialization() {
185 let input = vec![
187 Header::Boolean(true),
188 Header::Int(-1),
189 Header::UInt(0),
190 Header::UInt(1),
191 Header::String("hello".into()),
192 ];
193 let expected_result = "[true,-1,0,1,\"hello\"]";
194
195 let actual_result = serde_json::to_string(&input).unwrap();
197
198 assert_eq!(expected_result, actual_result);
200 }
201
202 #[test]
203 fn deserialization() {
204 let input = "[true,-1,0,1,\"hello\"]";
206 let expected_result = vec![
207 AMQPValue::morph(true),
208 AMQPValue::LongInt(-1), AMQPValue::LongUInt(0),
210 AMQPValue::LongUInt(1),
211 AMQPValue::morph("hello"),
212 ];
213
214 let actual_result = serde_json::from_str::<Vec<Header>>(input)
216 .unwrap()
217 .into_iter()
218 .map(AMQPValue::from)
219 .collect::<Vec<_>>();
220
221 assert_eq!(expected_result, actual_result);
223 }
224}