udp 3.1.0

A lightweight and efficient Rust library for building UDP servers with request-response handling.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
use crate::*;

/// Provides a default implementation for ContextData.
impl Default for ContextData {
    /// Creates a default ContextData with empty values.
    ///
    /// # Returns
    ///
    /// - `Self` - A new instance with default values.
    #[inline(always)]
    fn default() -> Self {
        Self {
            aborted: false,
            socket: None,
            request: Request::new(),
            response: Response::default(),
            client_addr: None,
            attributes: HashMap::new(),
        }
    }
}

/// Provides a default implementation for Context.
impl Default for Context {
    /// Creates a default Context wrapping default ContextData.
    ///
    /// # Returns
    ///
    /// - `Self` - A new instance with default values.
    #[inline(always)]
    fn default() -> Self {
        Self(arc_rwlock(ContextData::default()))
    }
}

/// Implementation of methods for ContextData.
impl ContextData {
    /// Creates a new ContextData with the given socket, request, and client address.
    ///
    /// # Arguments
    ///
    /// - `ArcRwLockUdpSocket` - The network socket.
    /// - `Request` - The request data.
    /// - `SocketAddr` - The client's socket address.
    ///
    /// # Returns
    ///
    /// - `Self` - A new ContextData instance.
    pub fn new(socket: ArcRwLockUdpSocket, request: Request, client_addr: SocketAddr) -> Self {
        Self {
            aborted: false,
            socket: Some(socket),
            request,
            response: Response::default(),
            client_addr: Some(client_addr),
            attributes: HashMap::new(),
        }
    }

    /// Gets the aborted flag.
    ///
    /// # Returns
    ///
    /// - `bool` - The aborted flag.
    pub fn get_aborted(&self) -> bool {
        self.aborted
    }

    /// Sets the aborted flag.
    ///
    /// # Arguments
    ///
    /// - `bool` - The new value for the aborted flag.
    pub fn set_aborted(&mut self, aborted: bool) {
        self.aborted = aborted;
    }

    /// Gets the socket.
    ///
    /// # Returns
    ///
    /// - `Option<ArcRwLockUdpSocket>` - The socket if present.
    pub fn get_socket(&self) -> Option<ArcRwLockUdpSocket> {
        self.socket.clone()
    }

    /// Gets the request.
    ///
    /// # Returns
    ///
    /// - `&Request` - Reference to the request.
    pub fn get_request(&self) -> &Request {
        &self.request
    }

    /// Gets the response.
    ///
    /// # Returns
    ///
    /// - `&Response` - Reference to the response.
    pub fn get_response(&self) -> &Response {
        &self.response
    }

    /// Gets the response mutably.
    ///
    /// # Returns
    ///
    /// - `&mut Response` - Mutable reference to the response.
    pub fn get_response_mut(&mut self) -> &mut Response {
        &mut self.response
    }

    /// Gets the client address.
    ///
    /// # Returns
    ///
    /// - `Option<SocketAddr>` - The client address if present.
    pub fn get_client_addr(&self) -> Option<SocketAddr> {
        self.client_addr
    }

    /// Gets the attributes.
    ///
    /// # Returns
    ///
    /// - `&ThreadSafeAttributeStore` - Reference to the attributes.
    pub fn get_attributes(&self) -> &ThreadSafeAttributeStore {
        &self.attributes
    }

    /// Gets the attributes mutably.
    ///
    /// # Returns
    ///
    /// - `&mut ThreadSafeAttributeStore` - Mutable reference to the attributes.
    pub fn get_attributes_mut(&mut self) -> &mut ThreadSafeAttributeStore {
        &mut self.attributes
    }
}

/// Implementation of methods for Context.
impl Context {
    /// Creates a new Context with the given socket, request, and client address.
    ///
    /// # Arguments
    ///
    /// - `socket` - The network socket.
    /// - `request` - The request data.
    /// - `client_addr` - The client's socket address.
    ///
    /// # Returns
    ///
    /// - `Self` - A new Context instance.
    pub fn new(socket: &ArcRwLockUdpSocket, request: &Request, client_addr: SocketAddr) -> Self {
        Self(arc_rwlock(ContextData::new(
            socket.clone(),
            request.clone(),
            client_addr,
        )))
    }

    /// Acquires a read lock on the inner context data.
    ///
    /// # Returns
    ///
    /// - `RwLockReadGuard<ContextData>` - The read guard for the inner context.
    async fn read(&self) -> RwLockReadGuard<'_, ContextData> {
        self.0.read().await
    }

    /// Acquires a write lock on the inner context data.
    ///
    /// # Returns
    ///
    /// - `RwLockWriteGuard<ContextData>` - The write guard for the inner context.
    async fn write(&self) -> RwLockWriteGuard<'_, ContextData> {
        self.0.write().await
    }

    /// Checks if the context has been marked as aborted.
    ///
    /// # Returns
    ///
    /// - `bool` - True if the context is aborted, otherwise false.
    pub async fn get_aborted(&self) -> bool {
        self.read().await.get_aborted()
    }

    /// Sets the aborted flag for the context.
    ///
    /// # Arguments
    ///
    /// - `aborted` - The aborted state to set.
    pub async fn set_aborted(&self, aborted: bool) {
        self.write().await.set_aborted(aborted);
    }

    /// Marks the context as aborted.
    pub async fn aborted(&self) {
        self.set_aborted(true).await;
    }

    /// Cancels the aborted state of the context.
    pub async fn cancel_aborted(&self) {
        self.set_aborted(false).await;
    }

    /// Retrieves the underlying network socket, if available.
    ///
    /// # Returns
    ///
    /// - `Option<ArcRwLockUdpSocket>` - The thread-safe, shareable network socket if it exists.
    pub async fn try_get_socket(&self) -> Option<ArcRwLockUdpSocket> {
        self.read().await.get_socket()
    }

    /// Retrieves the underlying network socket.
    ///
    /// # Returns
    ///
    /// - `ArcRwLockUdpSocket` - The thread-safe, shareable network socket.
    ///
    /// # Panics
    ///
    /// - If the network socket is not found.
    pub async fn get_socket(&self) -> ArcRwLockUdpSocket {
        self.try_get_socket().await.unwrap()
    }

    /// Retrieves the current request.
    ///
    /// # Returns
    ///
    /// - `Request` - A clone of the current request.
    pub async fn get_request(&self) -> Request {
        self.read().await.get_request().clone()
    }

    /// Retrieves the current response.
    ///
    /// # Returns
    ///
    /// - `Response` - A clone of the current response.
    pub async fn get_response(&self) -> Response {
        self.read().await.get_response().clone()
    }

    /// Retrieves the client address, if available.
    ///
    /// # Returns
    ///
    /// - `Option<SocketAddr>` - The client address if present.
    pub async fn try_get_client_addr(&self) -> Option<SocketAddr> {
        self.read().await.get_client_addr()
    }

    /// Retrieves the client address.
    ///
    /// # Returns
    ///
    /// - `SocketAddr` - The client address.
    ///
    /// # Panics
    ///
    /// - If the client address is not found.
    pub async fn get_client_addr(&self) -> SocketAddr {
        self.try_get_client_addr().await.unwrap()
    }

    /// Retrieves the client address as a string.
    ///
    /// # Returns
    ///
    /// - `Option<String>` - The string representation of the client address if available.
    pub async fn try_get_client_addr_string(&self) -> Option<String> {
        self.try_get_client_addr()
            .await
            .map(|addr| addr.to_string())
    }

    /// Retrieves the client host IP address.
    ///
    /// # Returns
    ///
    /// - `Option<IpAddr>` - The client IP address if available.
    pub async fn try_get_client_host(&self) -> Option<IpAddr> {
        self.try_get_client_addr().await.map(|addr| addr.ip())
    }

    /// Retrieves the client port number.
    ///
    /// # Returns
    ///
    /// - `Option<u16>` - The client port number if available.
    pub async fn try_get_client_port(&self) -> Option<u16> {
        self.try_get_client_addr().await.map(|addr| addr.port())
    }

    /// Sets an attribute in the context.
    ///
    /// # Arguments
    ///
    /// - `K` - The key of the attribute to set.
    /// - `V` - The value of the attribute.
    ///
    /// # Returns
    ///
    /// - `&Self` - A reference to the modified context.
    pub async fn set_attribute<K, V>(&self, key: K, value: V) -> &Self
    where
        K: AsRef<str>,
        V: AnySendSyncClone,
    {
        self.write()
            .await
            .get_attributes_mut()
            .insert(key.as_ref().to_owned(), Arc::new(value));
        self
    }

    /// Attempts to retrieve a specific attribute by its key.
    ///
    /// # Arguments
    ///
    /// - `K` - The key of the attribute to retrieve.
    ///
    /// # Returns
    ///
    /// - `Option<V>` - The attribute value if it exists and can be cast to the specified type.
    pub async fn try_get_attribute<V, K>(&self, key: K) -> Option<V>
    where
        V: AnySendSyncClone,
        K: AsRef<str>,
    {
        self.read()
            .await
            .get_attributes()
            .get(key.as_ref())
            .and_then(|arc| arc.downcast_ref::<V>())
            .cloned()
    }

    /// Retrieves a specific attribute by its key.
    ///
    /// # Arguments
    ///
    /// - `K` - The key of the attribute to retrieve.
    ///
    /// # Returns
    ///
    /// - `V` - The attribute value.
    ///
    /// # Panics
    ///
    /// - If the attribute is not found.
    pub async fn get_attribute<V, K>(&self, key: K) -> V
    where
        V: AnySendSyncClone,
        K: AsRef<str>,
    {
        self.try_get_attribute(key).await.unwrap()
    }

    /// Removes an attribute from the context.
    ///
    /// # Arguments
    ///
    /// - `K` - The key of the attribute to remove.
    ///
    /// # Returns
    ///
    /// - `&Self` - A reference to the modified context.
    pub async fn remove_attribute<K>(&self, key: K) -> &Self
    where
        K: AsRef<str>,
    {
        self.write().await.get_attributes_mut().remove(key.as_ref());
        self
    }

    /// Clears all attributes from the context.
    ///
    /// # Returns
    ///
    /// - `&Self` - A reference to the modified context.
    pub async fn clear_attributes(&self) -> &Self {
        self.write().await.get_attributes_mut().clear();
        self
    }

    /// Sends a response to the client.
    ///
    /// # Arguments
    ///
    /// - `Into<ResponseData>` - The response data.
    ///
    /// # Returns
    ///
    /// - `ResponseResult` - Result of the send operation.
    pub async fn send<T>(&self, data: T) -> ResponseResult
    where
        T: Into<ResponseData>,
    {
        let socket_opt: Option<ArcRwLockUdpSocket> = self.try_get_socket().await;
        let addr_opt: Option<SocketAddr> = self.try_get_client_addr().await;
        let response: Response = Response::from(data);
        response.send(&socket_opt, &addr_opt).await
    }
}