Skip to content

Commit

Permalink
feat(socketioxide): properly send binary payloads embedded in structs
Browse files Browse the repository at this point in the history
In order to reduce possible API-use confusion, ConfOperators and
BroadcastOperators now has a new type param, for a new (sealed) trait,
BinaryHolding, which "tells" the struct whether or not the user has
added binary data or not.

If the user has not added binary data, the operator will be
WithoutBinary, and emit() and emit_with_ack() take a T: Serialize as
usual, and those methods will attempt to extract any binary payloads
from the user-provided struct before sending the event.

If the user explicitly adds binary data (by calling the bin() method),
they will get back a new instance of the operator that is WithBinary.
Then the emit() and emit_with_ack() methods will take a
serde_json::Value, which is expected to already have placeholder objects
where any binary payload is supposed to be.
  • Loading branch information
kelnos committed Apr 15, 2024
1 parent 77220b3 commit 07ef868
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 138 deletions.
2 changes: 1 addition & 1 deletion e2e/socketioxide/socketioxide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn on_connect(socket: SocketRef, Data(data): Data<Value>) {
|s: SocketRef, Data::<Value>(data), Bin(bin)| async move {
let ack = s
.bin(bin)
.emit_with_ack::<_, Value>("emit-with-ack", data)
.emit_with_ack::<Value>("emit-with-ack", data)
.unwrap()
.await
.unwrap();
Expand Down
28 changes: 17 additions & 11 deletions socketioxide/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crate::{
extract::SocketRef,
handler::ConnectHandler,
layer::SocketIoLayer,
operators::{BroadcastOperators, RoomParam},
operators::{
holding::{WithBinary, WithoutBinary},
BroadcastOperators, RoomParam,
},
service::SocketIoService,
BroadcastError, DisconnectError,
};
Expand Down Expand Up @@ -375,7 +378,7 @@ impl<A: Adapter> SocketIo<A> {
/// println!("found socket on /custom_ns namespace with id: {}", socket.id);
/// }
#[inline]
pub fn of<'a>(&self, path: impl Into<&'a str>) -> Option<BroadcastOperators<A>> {
pub fn of<'a>(&self, path: impl Into<&'a str>) -> Option<BroadcastOperators<WithoutBinary, A>> {
self.get_op(path.into())
}

Expand All @@ -401,7 +404,7 @@ impl<A: Adapter> SocketIo<A> {
/// println!("found socket on / ns in room1 with id: {}", socket.id);
/// }
#[inline]
pub fn to(&self, rooms: impl RoomParam) -> BroadcastOperators<A> {
pub fn to(&self, rooms: impl RoomParam) -> BroadcastOperators<WithoutBinary, A> {
self.get_default_op().to(rooms)
}

Expand Down Expand Up @@ -429,7 +432,7 @@ impl<A: Adapter> SocketIo<A> {
/// println!("found socket on / ns in room1 with id: {}", socket.id);
/// }
#[inline]
pub fn within(&self, rooms: impl RoomParam) -> BroadcastOperators<A> {
pub fn within(&self, rooms: impl RoomParam) -> BroadcastOperators<WithoutBinary, A> {
self.get_default_op().within(rooms)
}

Expand Down Expand Up @@ -462,7 +465,7 @@ impl<A: Adapter> SocketIo<A> {
/// println!("found socket on / ns in room1 with id: {}", socket.id);
/// }
#[inline]
pub fn except(&self, rooms: impl RoomParam) -> BroadcastOperators<A> {
pub fn except(&self, rooms: impl RoomParam) -> BroadcastOperators<WithoutBinary, A> {
self.get_default_op().except(rooms)
}

Expand All @@ -489,7 +492,7 @@ impl<A: Adapter> SocketIo<A> {
/// println!("found socket on / ns in room1 with id: {}", socket.id);
/// }
#[inline]
pub fn local(&self) -> BroadcastOperators<A> {
pub fn local(&self) -> BroadcastOperators<WithoutBinary, A> {
self.get_default_op().local()
}

Expand Down Expand Up @@ -532,7 +535,7 @@ impl<A: Adapter> SocketIo<A> {
/// }
/// });
#[inline]
pub fn timeout(&self, timeout: Duration) -> BroadcastOperators<A> {
pub fn timeout(&self, timeout: Duration) -> BroadcastOperators<WithoutBinary, A> {
self.get_default_op().timeout(timeout)
}

Expand All @@ -559,9 +562,12 @@ impl<A: Adapter> SocketIo<A> {
/// .to("room3")
/// .except("room2")
/// .bin(vec![Bytes::from_static(&[1, 2, 3, 4])])
/// .emit("test", ());
/// .emit("test", ().into());
#[inline]
pub fn bin(&self, binary: impl IntoIterator<Item = impl Into<Bytes>>) -> BroadcastOperators<A> {
pub fn bin(
&self,
binary: impl IntoIterator<Item = impl Into<Bytes>>,
) -> BroadcastOperators<WithBinary, A> {
self.get_default_op().bin(binary)
}

Expand Down Expand Up @@ -787,7 +793,7 @@ impl<A: Adapter> SocketIo<A> {

/// Returns a new operator on the given namespace
#[inline(always)]
fn get_op(&self, path: &str) -> Option<BroadcastOperators<A>> {
fn get_op(&self, path: &str) -> Option<BroadcastOperators<WithoutBinary, A>> {
self.0
.get_ns(path)
.map(|ns| BroadcastOperators::new(ns).broadcast())
Expand All @@ -799,7 +805,7 @@ impl<A: Adapter> SocketIo<A> {
///
/// If the **default namespace "/" is not found** this fn will panic!
#[inline(always)]
fn get_default_op(&self) -> BroadcastOperators<A> {
fn get_default_op(&self) -> BroadcastOperators<WithoutBinary, A> {
self.get_op("/").expect("default namespace not found")
}
}
Expand Down
Loading

0 comments on commit 07ef868

Please sign in to comment.