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
//! WebSocket support for Autumn applications.
//!
//! This module provides ergonomic WebSocket handling through the [`#[ws]`](macro@crate::ws)
//! macro and re-exports of Axum's WebSocket types.
//!
//! # Two-function pattern
//!
//! WebSocket handlers in Autumn use a **two-function pattern**: the outer
//! function runs at HTTP upgrade time (before the WebSocket connection is
//! established) and returns a closure that handles the live socket.
//!
//! This split gives you:
//! - **Pre-upgrade access** to Axum extractors (auth, session, state)
//! - **Post-upgrade ownership** of the `WebSocket` + captured values
//! - A natural place for connection rejection (return an error before upgrade)
//!
//! # Examples
//!
//! ```rust,ignore
//! use autumn_web::prelude::*;
//! use autumn_web::ws::{WebSocket, Message};
//!
//! // Simple echo server
//! #[ws("/echo")]
//! async fn echo() -> impl WsHandler {
//! |mut socket: WebSocket| async move {
//! while let Some(Ok(msg)) = socket.recv().await {
//! if let Message::Text(text) = msg {
//! socket.send(Message::Text(text)).await.ok();
//! }
//! }
//! }
//! }
//!
//! // With state and graceful shutdown
//! #[ws("/chat")]
//! async fn chat(state: AppState) -> impl WsHandler {
//! let channels = state.channels();
//! let tx = channels.sender("lobby");
//! let mut rx = channels.subscribe("lobby");
//!
//! |mut socket: WebSocket, shutdown: CancellationToken| async move {
//! loop {
//! tokio::select! {
//! Some(Ok(Message::Text(text))) = socket.recv() => {
//! tx.send(text.to_string()).ok();
//! }
//! Ok(msg) = rx.recv() => {
//! socket.send(Message::Text(msg.into())).await.ok();
//! }
//! _ = shutdown.cancelled() => {
//! socket.send(Message::Close(None)).await.ok();
//! break;
//! }
//! }
//! }
//! }
//! }
//! ```
use Future;
use Pin;
pub use WebSocketUpgrade;
pub use ;
pub use CancellationToken;
/// Trait for WebSocket connection handlers.
///
/// Implemented automatically for closures matching the supported signatures.
/// Users never implement this trait directly — they return closures from
/// `#[ws]` handler functions.
///
/// # Supported signatures
///
/// ```rust,ignore
/// // Minimal: just the socket
/// |socket: WebSocket| async move { /* ... */ }
///
/// // With shutdown signal
/// |socket: WebSocket, shutdown: CancellationToken| async move { /* ... */ }
/// ```
// ── Blanket impl: closure taking (WebSocket) ───────────────────────
// NOTE: We cannot have a second blanket impl for `FnOnce(WebSocket, CancellationToken)`
// because it conflicts with the above. Instead, we provide a newtype wrapper.
/// Wrapper that enables `|socket, shutdown|` closures as [`WsHandler`].
///
/// Users don't construct this directly. The `#[ws]` macro detects the
/// `CancellationToken` parameter in the closure and wraps it automatically.
/// For manual usage:
///
/// ```rust,ignore
/// use autumn_web::ws::{WithShutdown, WebSocket, CancellationToken};
///
/// let handler = WithShutdown(|socket: WebSocket, shutdown: CancellationToken| async move {
/// // ...
/// });
/// ```
;