aerox/client/mod.rs
1//! High-level client API
2//!
3//! Provides a simplified client interface for common use cases.
4
5use crate::{Error, Result};
6use aerox_client::{HighLevelClient as InnerClient, StreamClient as InnerStream};
7use aerox_client::Result as ClientResult;
8use std::future::Future;
9use std::pin::Pin;
10
11/// High-level client with automatic message handling
12///
13/// This is a simplified wrapper around [`aerox_client::HighLevelClient`] that provides
14/// a cleaner API for common client operations.
15///
16/// # Example
17///
18/// ```rust,no_run,ignore
19/// use aerox::Client;
20///
21/// #[tokio::main]
22/// async fn main() -> aerox::Result<()> {
23/// let mut client = Client::connect("127.0.0.1:8080").await?;
24///
25/// // Register message handler
26/// client.on_message(1001, |id, msg: MyMessage| async move {
27/// println!("Received: {:?}", msg);
28/// Ok(())
29/// }).await?;
30///
31/// // Send message
32/// client.send(1001, &my_message).await?;
33///
34/// Ok(())
35/// }
36/// ```
37pub struct Client {
38 inner: InnerClient,
39}
40
41impl Client {
42 /// Connect to a server
43 ///
44 /// # Arguments
45 ///
46 /// * `addr` - Server address (e.g., "127.0.0.1:8080")
47 ///
48 /// # Example
49 ///
50 /// ```rust,no_run,ignore
51 /// let client = Client::connect("127.0.0.1:8080").await?;
52 /// ```
53 pub async fn connect(addr: impl Into<String>) -> Result<Self> {
54 let addr_str = addr.into();
55 let socket_addr: std::net::SocketAddr = addr_str.parse().map_err(|e| {
56 Error::Custom(format!("Invalid address '{}': {}", addr_str, e))
57 })?;
58
59 let inner = InnerClient::connect(socket_addr)
60 .await
61 .map_err(Error::from)?;
62
63 Ok(Self { inner })
64 }
65
66 /// Register a message handler
67 ///
68 /// # Arguments
69 ///
70 /// * `msg_id` - Message ID to handle
71 /// * `f` - Async handler function
72 ///
73 /// # Example
74 ///
75 /// ```rust,no_run,ignore
76 /// client.on_message(1001, |id, msg: MyMessage| async move {
77 /// println!("Received message {}: {:?}", id, msg);
78 /// Ok(())
79 /// }).await?;
80 /// ```
81 pub async fn on_message<M, F>(&mut self, msg_id: u16, f: F) -> Result<()>
82 where
83 M: prost::Message + Default + Send + 'static,
84 F: Fn(u16, M) -> Pin<Box<dyn Future<Output = ClientResult<()>> + Send>>
85 + Send
86 + Sync
87 + 'static,
88 {
89 self.inner
90 .on_message(msg_id, f)
91 .await
92 .map_err(Error::from)?;
93 Ok(())
94 }
95
96 /// Send a message
97 ///
98 /// # Arguments
99 ///
100 /// * `msg_id` - Message ID
101 /// * `msg` - Message to send (must implement [`prost::Message`])
102 ///
103 /// # Example
104 ///
105 /// ```rust,no_run,ignore
106 /// client.send(1001, &my_message).await?;
107 /// ```
108 pub async fn send<M: prost::Message>(&mut self, msg_id: u16, msg: &M) -> Result<()> {
109 self.inner.send(msg_id, msg).await.map_err(Error::from)
110 }
111
112 /// Check if connected to the server
113 ///
114 /// # Example
115 ///
116 /// ```rust,no_run,ignore
117 /// if client.is_connected().await {
118 /// println!("Still connected");
119 /// }
120 /// ```
121 pub async fn is_connected(&self) -> bool {
122 self.inner.is_connected().await
123 }
124
125 /// Get the inner client for advanced use cases
126 pub fn inner(&self) -> &InnerClient {
127 &self.inner
128 }
129
130 /// Get a mutable reference to the inner client for advanced use cases
131 pub fn inner_mut(&mut self) -> &mut InnerClient {
132 &mut self.inner
133 }
134
135 /// Consume and return the inner client
136 pub fn into_inner(self) -> InnerClient {
137 self.inner
138 }
139}
140
141/// Low-level stream client
142///
143/// This is a re-export of [`aerox_client::StreamClient`] for users who need
144/// fine-grained control over message handling.
145///
146/// # Example
147///
148/// ```rust,no_run,ignore
149/// use aerox::StreamClient;
150///
151/// #[tokio::main]
152/// async fn main() -> aerox::Result<()> {
153/// let mut client = StreamClient::connect("127.0.0.1:8080").await?;
154///
155/// // Manual send/receive loop
156/// client.send_message(1001, &msg).await?;
157/// let (msg_id, response) = client.recv_message::<Response>().await?;
158///
159/// client.close().await?;
160/// Ok(())
161/// }
162/// ```
163pub use aerox_client::StreamClient;