fe2o3_amqp_types/messaging/
target.rs1use serde_amqp::macros::{DeserializeComposite, SerializeComposite};
2use serde_amqp::primitives::{Array, Boolean, Symbol};
3use serde_amqp::Value;
4
5use crate::definitions::{Fields, Seconds};
6
7use super::{
8 Address, LifetimePolicy, NodeProperties, SupportedDistModes, TerminusDurability,
9 TerminusExpiryPolicy,
10};
11
12#[cfg(feature = "transaction")]
13use crate::transaction::Coordinator;
14
15#[derive(Debug, Clone)]
20pub enum TargetArchetype {
21 Target(Target),
23
24 #[cfg_attr(docsrs, doc(cfg(feature = "transaction")))]
26 #[cfg(feature = "transaction")]
27 Coordinator(Coordinator),
28}
29
30mod target_archetype_serde_impl {
31 use serde::{
32 de::{self, VariantAccess},
33 ser,
34 };
35
36 use super::TargetArchetype;
37
38 impl ser::Serialize for TargetArchetype {
39 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
40 where
41 S: serde::Serializer,
42 {
43 match self {
44 TargetArchetype::Target(value) => value.serialize(serializer),
45 #[cfg(feature = "transaction")]
46 TargetArchetype::Coordinator(value) => value.serialize(serializer),
47 }
48 }
49 }
50
51 enum Field {
52 Target,
53 #[cfg(feature = "transaction")]
54 Coordinator,
55 }
56
57 struct FieldVisitor {}
58
59 impl<'de> de::Visitor<'de> for FieldVisitor {
60 type Value = Field;
61
62 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
63 formatter.write_str("variant identifier for TargetArchetype")
64 }
65
66 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
67 where
68 E: de::Error,
69 {
70 let val = match v {
71 "amqp:target:list" => Field::Target,
72 #[cfg(feature = "transaction")]
73 "amqp:coordinator:list" => Field::Coordinator,
74 _ => {
75 return Err(de::Error::custom(
76 "Wrong descriptor symbol value for Target archetype",
77 ))
78 }
79 };
80 Ok(val)
81 }
82
83 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
84 where
85 E: de::Error,
86 {
87 let val = match v {
88 0x0000_0000_0000_0029 => Field::Target,
89 #[cfg(feature = "transaction")]
90 0x0000_0000_0000_0030 => Field::Coordinator,
91 _ => {
92 return Err(de::Error::custom(
93 "Wrong descriptor code value for Target archetype",
94 ))
95 }
96 };
97 Ok(val)
98 }
99 }
100
101 impl<'de> de::Deserialize<'de> for Field {
102 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
103 where
104 D: serde::Deserializer<'de>,
105 {
106 deserializer.deserialize_identifier(FieldVisitor {})
107 }
108 }
109
110 struct Visitor {}
111
112 impl<'de> de::Visitor<'de> for Visitor {
113 type Value = TargetArchetype;
114
115 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
116 formatter.write_str("variant identifier for TargetArchetype")
117 }
118
119 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
120 where
121 A: de::EnumAccess<'de>,
122 {
123 let (val, variant) = data.variant()?;
124
125 match val {
126 Field::Target => {
127 let value = variant.newtype_variant()?;
128 Ok(TargetArchetype::Target(value))
129 }
130 #[cfg(feature = "transaction")]
131 Field::Coordinator => {
132 let value = variant.newtype_variant()?;
133 Ok(TargetArchetype::Coordinator(value))
134 }
135 }
136 }
137 }
138
139 impl<'de> de::Deserialize<'de> for TargetArchetype {
140 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
141 where
142 D: serde::Deserializer<'de>,
143 {
144 #[cfg(not(feature = "transaction"))]
145 const VARIANTS: &[&str] = &["amqp:target:list"];
146 #[cfg(feature = "transaction")]
147 const VARIANTS: &[&str] = &["amqp:target:list", "amqp:coordinator:list"];
148 deserializer.deserialize_enum("TargetArchetype", VARIANTS, Visitor {})
149 }
150 }
151}
152
153#[derive(Debug, Clone, Default, DeserializeComposite, SerializeComposite)]
159#[amqp_contract(
160 name = "amqp:target:list",
161 code = "0x0000_0000:0x0000_0029",
162 encoding = "list",
163 rename_all = "kebab-case"
164)]
165pub struct Target {
166 pub address: Option<Address>,
168
169 #[amqp_contract(default)]
171 pub durable: TerminusDurability,
172
173 #[amqp_contract(default)]
175 pub expiry_policy: TerminusExpiryPolicy,
176
177 #[amqp_contract(default)]
179 pub timeout: Seconds,
180
181 #[amqp_contract(default)]
183 pub dynamic: Boolean,
184
185 pub dynamic_node_properties: Option<NodeProperties>,
197
198 pub capabilities: Option<Array<Symbol>>,
200}
201
202impl Target {
203 pub fn builder() -> TargetBuilder {
205 TargetBuilder::new()
206 }
207}
208
209impl TryFrom<TargetArchetype> for Target {
210 type Error = TargetArchetype;
211
212 fn try_from(value: TargetArchetype) -> Result<Self, Self::Error> {
213 match value {
214 TargetArchetype::Target(target) => Ok(target),
215 #[cfg(feature = "transaction")]
216 _ => Err(value),
217 }
218 }
219}
220
221impl<T: Into<Address>> From<T> for Target {
222 fn from(val: T) -> Self {
223 Self {
224 address: Some(val.into()),
225 ..Default::default()
226 }
227 }
229}
230
231impl<T: Into<Target>> From<T> for TargetArchetype {
232 fn from(value: T) -> Self {
233 let target = value.into();
234 Self::Target(target)
235 }
236}
237
238#[derive(Debug, Default, Clone)]
240pub struct TargetBuilder {
241 pub target: Target,
243}
244
245impl TargetBuilder {
246 pub fn new() -> Self {
248 Self {
249 target: Default::default(),
250 }
251 }
252
253 pub fn address(mut self, address: impl Into<Address>) -> Self {
255 self.target.address = Some(address.into());
256 self
257 }
258
259 pub fn durable(mut self, durability: TerminusDurability) -> Self {
261 self.target.durable = durability;
262 self
263 }
264
265 pub fn expiry_policy(mut self, policy: TerminusExpiryPolicy) -> Self {
267 self.target.expiry_policy = policy;
268 self
269 }
270
271 pub fn timeout(mut self, timeout: Seconds) -> Self {
273 self.target.timeout = timeout;
274 self
275 }
276
277 pub fn dynamic(mut self, dynamic: bool) -> Self {
279 self.target.dynamic = dynamic;
280 self
281 }
282
283 pub fn dynamic_node_properties(mut self, properties: impl Into<Fields>) -> Self {
306 self.target.dynamic_node_properties = Some(properties.into());
307 self
308 }
309
310 pub fn add_lifetime_policy(mut self, policy: impl Into<LifetimePolicy>) -> Self {
331 let policy: LifetimePolicy = policy.into();
332 match &mut self.target.dynamic_node_properties {
333 Some(map) => {
334 map.insert(Symbol::from("lifetime-policy"), Value::from(policy));
335 }
336 None => {
337 self.target.dynamic_node_properties = Some(policy.into());
338 }
339 };
340 self
341 }
342
343 pub fn add_supported_dist_modes(mut self, modes: impl Into<SupportedDistModes>) -> Self {
364 let modes: SupportedDistModes = modes.into();
365 match &mut self.target.dynamic_node_properties {
366 Some(map) => {
367 map.insert(Symbol::from("supported-dist-modes"), Value::from(modes));
368 }
369 None => self.target.dynamic_node_properties = Some(modes.into()),
370 };
371 self
372 }
373
374 pub fn capabilities(mut self, capabilities: impl Into<Array<Symbol>>) -> Self {
376 self.target.capabilities = Some(capabilities.into());
377 self
378 }
379
380 pub fn build(self) -> Target {
382 self.target
383 }
384}
385
386#[cfg(test)]
387mod tests {
388 use serde_amqp::{from_slice, to_vec};
389
390 use super::{Target, TargetArchetype};
391
392 #[test]
393 fn test_target_archetype_variant_target() {
394 let target = Target::default();
395 let buf = to_vec(&target).unwrap();
396 let archetype: TargetArchetype = from_slice(&buf).unwrap();
397 println!("{:?}", archetype);
398
399 }
401
402 #[cfg(feature = "transaction")]
403 #[test]
404 fn test_target_archetype_variant_coordinator() {
405 use crate::transaction::Coordinator;
406 let coordinator = Coordinator::new(None);
407 let buf = to_vec(&coordinator).unwrap();
408 let archetype: TargetArchetype = from_slice(&buf).unwrap();
409 println!("{:?}", archetype);
410
411 }
413}