Skip to main content

ruststream_lapin/
context.rs

1//! Per-delivery context fields exposed to handlers.
2//!
3//! [`AmqpContext`] carries the AMQP delivery metadata that is not part of the payload or the
4//! headers. Request it in a handler by typing the context parameter as
5//! `Context<'_, AmqpContext>` and read individual fields with the zero-sized keys in [`keys`].
6
7use ruststream::{BuildContext, Field};
8
9use crate::message::LapinMessage;
10
11/// Native AMQP delivery metadata, built once per delivery.
12#[derive(Debug, Clone, Default, PartialEq, Eq)]
13pub struct AmqpContext {
14    exchange: String,
15    routing_key: String,
16    redelivered: bool,
17    delivery_tag: u64,
18}
19
20impl AmqpContext {
21    /// The exchange the message was published to (empty for the default exchange).
22    #[must_use]
23    pub fn exchange(&self) -> &str {
24        &self.exchange
25    }
26
27    /// The routing key the message was published with.
28    #[must_use]
29    pub fn routing_key(&self) -> &str {
30        &self.routing_key
31    }
32
33    /// Whether the broker marked the delivery as redelivered.
34    #[must_use]
35    pub fn redelivered(&self) -> bool {
36        self.redelivered
37    }
38
39    /// The channel-local delivery tag.
40    #[must_use]
41    pub fn delivery_tag(&self) -> u64 {
42        self.delivery_tag
43    }
44}
45
46impl BuildContext<LapinMessage> for AmqpContext {
47    fn build(msg: &LapinMessage) -> Self {
48        Self {
49            exchange: msg.exchange().to_owned(),
50            routing_key: msg.routing_key().to_owned(),
51            redelivered: msg.redelivered(),
52            delivery_tag: msg.delivery_tag(),
53        }
54    }
55}
56
57/// Zero-sized [`Field`] keys reading one [`AmqpContext`] field each.
58pub mod keys {
59    use ruststream::ContextField;
60
61    use super::{AmqpContext, Field};
62
63    /// Reads the source exchange name.
64    #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
65    pub struct Exchange;
66
67    impl Field<AmqpContext> for Exchange {
68        type Value<'a> = &'a str;
69
70        fn get(self, src: &AmqpContext) -> &str {
71            src.exchange()
72        }
73    }
74
75    impl ContextField for Exchange {
76        type Context = AmqpContext;
77        type Value = String;
78        fn read(self, src: &AmqpContext) -> String {
79            src.exchange().to_owned()
80        }
81    }
82
83    /// Reads the routing key.
84    #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
85    pub struct RoutingKey;
86
87    impl Field<AmqpContext> for RoutingKey {
88        type Value<'a> = &'a str;
89
90        fn get(self, src: &AmqpContext) -> &str {
91            src.routing_key()
92        }
93    }
94
95    impl ContextField for RoutingKey {
96        type Context = AmqpContext;
97        type Value = String;
98        fn read(self, src: &AmqpContext) -> String {
99            src.routing_key().to_owned()
100        }
101    }
102
103    /// Reads the redelivered flag.
104    #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
105    pub struct Redelivered;
106
107    impl Field<AmqpContext> for Redelivered {
108        type Value<'a> = bool;
109
110        fn get(self, src: &AmqpContext) -> bool {
111            src.redelivered()
112        }
113    }
114
115    impl ContextField for Redelivered {
116        type Context = AmqpContext;
117        type Value = bool;
118        fn read(self, src: &AmqpContext) -> bool {
119            src.redelivered()
120        }
121    }
122
123    /// Reads the channel-local delivery tag.
124    #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
125    pub struct DeliveryTag;
126
127    impl Field<AmqpContext> for DeliveryTag {
128        type Value<'a> = u64;
129
130        fn get(self, src: &AmqpContext) -> u64 {
131            src.delivery_tag()
132        }
133    }
134
135    impl ContextField for DeliveryTag {
136        type Context = AmqpContext;
137        type Value = u64;
138        fn read(self, src: &AmqpContext) -> u64 {
139            src.delivery_tag()
140        }
141    }
142}