use bytestring::ByteString;
use serde::Deserialize;
use sioc::error::EventError;
use sioc::prelude::*;
#[derive(Debug, EventType, DeserializePayload)]
struct A;
#[derive(Debug, EventType, DeserializePayload)]
struct B;
#[derive(Debug)]
enum MyEvent {
A(Event<A>),
B(Event<B>),
}
enum MyEventPayload {
A(<Event<A> as EventHandler>::Payload),
B(<Event<B> as EventHandler>::Payload),
}
impl<'de> Deserialize<'de> for MyEventPayload {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_seq(MyEventVisitor)
}
}
struct MyEventVisitor;
impl<'de> serde::de::Visitor<'de> for MyEventVisitor {
type Value = MyEventPayload;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a Socket.IO event payload")
}
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where
V: serde::de::SeqAccess<'de>,
{
let name: &str = seq
.next_element()?
.ok_or_else(|| serde::de::Error::invalid_length(0, &"event name"))?;
match name {
<Event<A> as EventHandler>::Payload::NAME => {
let payload = <Event<A> as EventHandler>::Payload::deserialize_payload(&mut seq)?;
Ok(MyEventPayload::A(payload))
}
<Event<B> as EventHandler>::Payload::NAME => {
let payload = <Event<B> as EventHandler>::Payload::deserialize_payload(&mut seq)?;
Ok(MyEventPayload::B(payload))
}
_ => Err(serde::de::Error::unknown_variant(
name,
&[
<Event<A> as EventHandler>::Payload::NAME,
<Event<B> as EventHandler>::Payload::NAME,
],
)),
}
}
}
impl TryFrom<DynEvent> for MyEvent {
type Error = EventError;
fn try_from(event: DynEvent) -> Result<Self, EventError> {
let payload = sioc::payload::from_json(&event.payload)?;
match payload {
MyEventPayload::A(args) => {
let event_a =
<Event<A> as EventHandler>::handle(args, event.id, event.attachments)?;
Ok(MyEvent::A(event_a))
}
MyEventPayload::B(args) => {
let event_b =
<Event<B> as EventHandler>::handle(args, event.id, event.attachments)?;
Ok(MyEvent::B(event_b))
}
}
}
}
fn main() -> Result<(), EventError> {
let event = DynEvent {
payload: ByteString::from_static("[\"a\"]"),
attachments: None,
id: None,
};
let my_event = MyEvent::try_from(event)?;
println!("{:?}", my_event);
Ok(())
}