asyncapi/channel.rs
1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 ChannelBinding, ExternalDocumentation, Message, OperationBinding, OperationTrait, Parameter,
6 ReferenceOr, Tag,
7};
8
9/// Describes the operations available on a single channel.
10///
11/// # Examples
12/// ```json
13/// {
14/// "description": "This channel is used to exchange messages about users signing up",
15/// "subscribe": {
16/// "summary": "A user signed up.",
17/// "message": {
18/// "description": "A longer description of the message",
19/// "payload": {
20/// "type": "object",
21/// "properties": {
22/// "user": {
23/// "$ref": "#/components/schemas/user"
24/// },
25/// "signup": {
26/// "$ref": "#/components/schemas/signup"
27/// }
28/// }
29/// }
30/// }
31/// },
32/// "bindings": {
33/// "amqp": {
34/// "is": "queue",
35/// "queue": {
36/// "exclusive": true
37/// }
38/// }
39/// }
40/// }
41/// ```
42///
43/// ```yaml
44/// description: This channel is used to exchange messages about users signing up
45/// subscribe:
46/// summary: A user signed up.
47/// message:
48/// description: A longer description of the message
49/// payload:
50/// type: object
51/// properties:
52/// user:
53/// $ref: "#/components/schemas/user"
54/// signup:
55/// bindings:
56/// amqp:
57/// is: queue
58/// queue:
59/// exclusive: true
60/// ```
61///
62/// Using `oneOf` to specify multiple messages per operation:
63///
64/// ```json
65/// {
66/// "subscribe": {
67/// "message": {
68/// "oneOf": [
69/// { "$ref": "#/components/messages/signup" },
70/// { "$ref": "#/components/messages/login" }
71/// ]
72/// }
73/// }
74/// }
75/// ```
76///
77/// ```yaml
78/// subscribe:
79/// message:
80/// oneOf:
81/// - $ref: '#/components/messages/signup'
82/// - $ref: '#/components/messages/login'
83/// ```
84#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
85#[serde(rename_all = "camelCase")]
86pub struct Channel {
87 /// Allows for an external definition of this channel item. The referenced structure
88 /// MUST be in the format of a
89 /// [Channel Item Object][crate::Channel].
90 /// If there are conflicts between the referenced definition and this Channel Item's
91 /// definition, the behavior is *undefined*.
92 #[deprecated(note = "The $ref field in Channel Item Object is now deprecated
93 from AsyncAPI 2.3.0. The current plan is that the $ref field will be
94 removed from Channel Item Object in AsyncAPI 3.0, and replaced with
95 Reference Object.")]
96 #[serde(rename = "$ref")]
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub reference: Option<String>,
99 /// An optional description of this channel item.
100 /// [CommonMark syntax](https://spec.commonmark.org/) can be used for rich
101 /// text representation.
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub description: Option<String>,
104 /// The servers on which this channel is available, specified as an optional unordered
105 /// list of names (string keys) of [Server Objects][crate::Server] defined in the
106 /// [Servers Object][crate::Server] (a map). If `servers` is absent or empty then this
107 /// channel must be available on all servers defined in the [Servers Object][crate::Server].
108 #[serde(default, skip_serializing_if = "Vec::is_empty")]
109 pub servers: Vec<String>,
110 /// A definition of the SUBSCRIBE operation, which defines the messages produced
111 /// by the application and sent to the channel.
112 #[serde(skip_serializing_if = "Option::is_none")]
113 pub subscribe: Option<Operation>,
114 /// A definition of the PUBLISH operation, which defines the messages consumed
115 /// by the application from the channel.
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub publish: Option<Operation>,
118 /// A map of the parameters included in the channel name. It SHOULD be present only
119 /// when using channels with expressions (as defined by
120 /// [RFC 6570 section 2.2](https://tools.ietf.org/html/rfc6570#section-2.2)).
121 ///
122 /// Describes a map of parameters included in a channel name.
123 ///
124 /// This map MUST contain all the parameters used in the parent channel name.
125 ///
126 /// # Examples
127 ///
128 /// ```json
129 /// {
130 /// "user/{userId}/signup": {
131 /// "parameters": {
132 /// "userId": {
133 /// "description": "Id of the user.",
134 /// "schema": {
135 /// "type": "string"
136 /// }
137 /// }
138 /// },
139 /// "subscribe": {
140 /// "$ref": "#/components/messages/userSignedUp"
141 /// }
142 /// }
143 /// }
144 /// ```
145 ///
146 /// ```yaml
147 /// user/{userId}/signup:
148 /// parameters:
149 /// userId:
150 /// description: Id of the user.
151 /// schema:
152 /// type: string
153 /// subscribe:
154 /// $ref: "#/components/messages/userSignedUp"
155 /// ```
156 #[serde(default, skip_serializing_if = "IndexMap::is_empty")]
157 pub parameters: IndexMap<String, ReferenceOr<Parameter>>,
158 /// A map where the keys describe the name of the protocol and the values
159 /// describe protocol-specific definitions for the channel.
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub bindings: Option<ReferenceOr<ChannelBinding>>,
162 /// This object can be extended with
163 /// [Specification Extensions](https://www.asyncapi.com/docs/specifications/v2.3.0#specificationExtensions).
164 #[serde(flatten)]
165 pub extensions: IndexMap<String, serde_json::Value>,
166}
167
168/// Describes a publish or a subscribe operation. This provides a place to document how
169/// and why messages are sent and received.
170///
171/// For example, an operation might describe a chat application use case where a user sends
172/// a text message to a group. A publish operation describes messages that are received by
173/// the chat application, whereas a subscribe operation describes messages that are sent by
174/// the chat application.
175///
176/// # Examples
177/// ```json
178/// {
179/// "operationId": "registerUser",
180/// "summary": "Action to sign a user up.",
181/// "description": "A longer description",
182/// "tags": [
183/// { "name": "user" },
184/// { "name": "signup" },
185/// { "name": "register" }
186/// ],
187/// "message": {
188/// "headers": {
189/// "type": "object",
190/// "properties": {
191/// "applicationInstanceId": {
192/// "description": "Unique identifier for a given instance of the publishing application",
193/// "type": "string"
194/// }
195/// }
196/// },
197/// "payload": {
198/// "type": "object",
199/// "properties": {
200/// "user": {
201/// "$ref": "#/components/schemas/userCreate"
202/// },
203/// "signup": {
204/// "$ref": "#/components/schemas/signup"
205/// }
206/// }
207/// }
208/// },
209/// "bindings": {
210/// "amqp": {
211/// "ack": false
212/// }
213/// },
214/// "traits": [
215/// { "$ref": "#/components/operationTraits/kafka" }
216/// ]
217/// }
218/// ```
219///
220/// ```yaml
221/// operationId: registerUser
222/// summary: Action to sign a user up.
223/// description: A longer description
224/// tags:
225/// - name: user
226/// - name: signup
227/// - name: register
228/// message:
229/// headers:
230/// type: object
231/// properties:
232/// applicationInstanceId:
233/// description: Unique identifier for a given instance of the publishing application
234/// type: string
235/// payload:
236/// type: object
237/// properties:
238/// user:
239/// $ref: "#/components/schemas/userCreate"
240/// signup:
241/// $ref: "#/components/schemas/signup"
242/// bindings:
243/// amqp:
244/// ack: false
245/// traits:
246/// - $ref: "#/components/operationTraits/kafka"
247/// ```
248#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
249#[serde(rename_all = "camelCase")]
250pub struct Operation {
251 /// Unique string used to identify the operation.
252 /// The id MUST be unique among all operations described in the API.
253 /// The operationId value is **case-sensitive**.
254 /// Tools and libraries MAY use the operationId to uniquely identify an
255 /// operation, therefore, it is RECOMMENDED to follow common programming
256 /// naming conventions.
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub operation_id: Option<String>,
259 /// A short summary of what the operation is about.
260 #[serde(skip_serializing_if = "Option::is_none")]
261 pub summary: Option<String>,
262 /// A verbose explanation of the operation.
263 /// [CommonMark syntax](https://spec.commonmark.org/)
264 /// can be used for rich text representation.
265 #[serde(skip_serializing_if = "Option::is_none")]
266 pub description: Option<String>,
267 /// A list of tags for API documentation control.
268 /// Tags can be used for logical grouping of operations.
269 #[serde(default, skip_serializing_if = "Vec::is_empty")]
270 pub tags: Vec<Tag>,
271 /// Additional external documentation for this operation.
272 #[serde(skip_serializing_if = "Option::is_none")]
273 pub external_docs: Option<ExternalDocumentation>,
274 /// A map where the keys describe the name of the protocol and the
275 /// values describe protocol-specific definitions for the operation.
276 #[serde(skip_serializing_if = "Option::is_none")]
277 pub bindings: Option<ReferenceOr<OperationBinding>>,
278 /// A list of traits to apply to the operation object.
279 /// Traits MUST be merged into the operation object using the
280 /// [JSON Merge Patch](https://tools.ietf.org/html/rfc7386)
281 /// algorithm in the same order they are defined here.
282 #[serde(default, skip_serializing_if = "Vec::is_empty")]
283 pub traits: Vec<ReferenceOr<OperationTrait>>,
284 /// A definition of the message that will be published or received on
285 /// this channel. `oneOf` is allowed here to specify multiple messages, however,
286 /// **a message MUST be valid only against one of the referenced message objects.**
287 #[serde(default, skip_serializing_if = "Option::is_none")]
288 pub message: Option<OperationMessageType>,
289 /// This object can be extended with
290 /// [Specification Extensions](https://www.asyncapi.com/docs/specifications/v2.3.0#specificationExtensions).
291 #[serde(flatten)]
292 pub extensions: IndexMap<String, serde_json::Value>,
293}
294
295#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
296#[serde(untagged)]
297pub enum OperationMessageType {
298 Map(IndexMap<String, ReferenceOr<Message>>),
299 Single(ReferenceOr<Message>),
300}