Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement shared custom data #428

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
10 changes: 10 additions & 0 deletions socketio/src/asynchronous/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rust_engineio::{
header::{HeaderMap, HeaderValue},
};
use std::collections::HashMap;
use std::sync::Arc;
use url::Url;

use crate::{error::Result, Event, Payload, TransportType};
Expand Down Expand Up @@ -38,6 +39,7 @@ pub struct ClientBuilder {
pub(crate) max_reconnect_attempts: Option<u8>,
pub(crate) reconnect_delay_min: u64,
pub(crate) reconnect_delay_max: u64,
pub(crate) data: Option<Arc<dyn std::any::Any + Send + Sync>>,
}

impl ClientBuilder {
Expand Down Expand Up @@ -97,9 +99,17 @@ impl ClientBuilder {
max_reconnect_attempts: None,
reconnect_delay_min: 1000,
reconnect_delay_max: 5000,
data: None,
}
}

/// Sets the client's custom data.
// TODO: write example usage
pub fn set_data<D: std::any::Any + Send + Sync>(mut self, data: Arc<D>) -> Self {
self.data = Some(data);
self
}

/// Sets the target namespace of the client. The namespace should start
/// with a leading `/`. Valid examples are e.g. `/admin`, `/foo`.
/// If the String provided doesn't start with a leading `/`, it is
Expand Down
9 changes: 9 additions & 0 deletions socketio/src/asynchronous/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub struct Client {
auth: Option<serde_json::Value>,
builder: Arc<RwLock<ClientBuilder>>,
disconnect_reason: Arc<RwLock<DisconnectReason>>,
data: Arc<dyn std::any::Any + Send + Sync>,
}

impl Client {
Expand All @@ -87,11 +88,19 @@ impl Client {
nsp: builder.namespace.to_owned(),
outstanding_acks: Arc::new(RwLock::new(Vec::new())),
auth: builder.auth.clone(),
data: builder.data.clone().unwrap_or(Arc::new(())),
builder: Arc::new(RwLock::new(builder)),
disconnect_reason: Arc::new(RwLock::new(DisconnectReason::default())),
})
}

/// Attempts to fetch data given by [`ClientBuilder::set_data`]
///
/// None is returned if data was not given or data does not match [`ClientBuilder::data`]
pub fn custom_data<D: Send + Sync + 'static>(&self) -> Option<Arc<D>> {
Arc::clone(&self.data).downcast().ok()
}

/// Connects the client to a server. Afterwards the `emit_*` methods can be
/// called to interact with the server.
pub(crate) async fn connect(&self) -> Result<()> {
Expand Down
10 changes: 10 additions & 0 deletions socketio/src/client/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub struct ClientBuilder {
opening_headers: Option<HeaderMap>,
transport_type: TransportType,
auth: Option<serde_json::Value>,
data: Option<Arc<dyn std::any::Any + Send + Sync>>,
pub(crate) reconnect: bool,
pub(crate) reconnect_on_disconnect: bool,
// None reconnect attempts represent infinity.
Expand Down Expand Up @@ -98,9 +99,17 @@ impl ClientBuilder {
max_reconnect_attempts: None,
reconnect_delay_min: 1000,
reconnect_delay_max: 5000,
data: None,
}
}

/// Sets the client's custom data.
// TODO: write example usage
pub fn set_data<D: std::any::Any + Send + Sync>(mut self, data: Arc<D>) -> Self {
self.data = Some(data);
self
}

/// Sets the target namespace of the client. The namespace should start
/// with a leading `/`. Valid examples are e.g. `/admin`, `/foo`.
pub fn namespace<T: Into<String>>(mut self, namespace: T) -> Self {
Expand Down Expand Up @@ -365,6 +374,7 @@ impl ClientBuilder {
self.on,
self.on_any,
self.auth,
self.data.unwrap_or(Arc::new(())),
)?;
socket.connect()?;

Expand Down
11 changes: 11 additions & 0 deletions socketio/src/client/raw_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::time::Duration;
use std::time::Instant;

use crate::socket::Socket as InnerSocket;
use crate::client::builder::ClientBuilder;

/// Represents an `Ack` as given back to the caller. Holds the internal `id` as
/// well as the current ack'ed state. Holds data which will be accessible as
Expand Down Expand Up @@ -41,6 +42,7 @@ pub struct RawClient {
nsp: String,
// Data send in the opening packet (commonly used as for auth)
auth: Option<Value>,
data: Arc<dyn std::any::Any + Send + Sync>,
}

impl RawClient {
Expand All @@ -54,6 +56,7 @@ impl RawClient {
on: Arc<Mutex<HashMap<Event, Callback<SocketCallback>>>>,
on_any: Arc<Mutex<Option<Callback<SocketAnyCallback>>>>,
auth: Option<Value>,
data: Arc<dyn std::any::Any + Send + Sync>,
) -> Result<Self> {
Ok(RawClient {
socket,
Expand All @@ -62,9 +65,17 @@ impl RawClient {
on_any,
outstanding_acks: Arc::new(Mutex::new(Vec::new())),
auth,
data,
})
}

/// Attempts to fetch data given by [`ClientBuilder::set_data`]
///
/// None is returned if data was not given or data does not match [`ClientBuilder::data`]
pub fn custom_data<D: Send + Sync + 'static>(&self) -> Option<Arc<D>> {
Arc::clone(&self.data).downcast().ok()
}

/// Connects the client to a server. Afterwards the `emit_*` methods can be
/// called to interact with the server. Attention: it's not allowed to add a
/// callback after a call to this method.
Expand Down