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;