use core::fmt;
use core::num::NonZeroU16;
use musli::alloc::Global;
use musli::mode::Binary;
use musli::{Decode, Encode};
#[doc(inline)]
pub use musli_web_macros::define;
pub trait Id
where
Self: 'static + Sized + fmt::Debug,
{
fn id(&self) -> MessageId;
fn from_id(id: MessageId) -> Self;
#[doc(hidden)]
fn __do_not_implement_id();
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
#[repr(transparent)]
#[musli(transparent)]
pub struct ChannelId {
repr: u16,
}
impl ChannelId {
pub const NONE: Self = Self::new(0);
#[inline]
pub(crate) const fn new(repr: u16) -> Self {
Self { repr }
}
#[inline]
#[cfg(feature = "ws")]
pub(crate) const fn raw(&self) -> u16 {
self.repr
}
}
impl fmt::Debug for ChannelId {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.repr == 0 {
f.write_str("NONE")
} else {
write!(f, "{:04x}", self.repr)
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
#[repr(transparent)]
#[musli(transparent)]
pub struct MessageId(NonZeroU16);
impl fmt::Display for MessageId {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl MessageId {
pub const ERROR_MESSAGE: Self = unsafe { Self::new_unchecked((i16::MAX as u16) + 1) };
pub const CONNECT: Self = unsafe { Self::new_unchecked((i16::MAX as u16) + 2) };
pub const DISCONNECT: Self = unsafe { Self::new_unchecked((i16::MAX as u16) + 3) };
pub const SERVER_HELLO: Self = unsafe { Self::new_unchecked((i16::MAX as u16) + 4) };
pub const EMPTY: Self = unsafe { Self::new_unchecked(u16::MAX) };
#[inline]
pub const fn new(id: u16) -> Option<Self> {
let Some(value) = NonZeroU16::new(id) else {
return None;
};
Some(Self(value))
}
#[inline]
pub const fn get(&self) -> u16 {
self.0.get()
}
#[inline]
pub const unsafe fn new_unchecked(id: u16) -> Self {
Self(unsafe { NonZeroU16::new_unchecked(id) })
}
}
pub trait Decodable {
type Type<'de>: Decode<'de, Binary, Global>;
#[doc(hidden)]
fn __do_not_implement_decodable();
}
pub trait Endpoint
where
Self: 'static,
for<'de> Self: Decodable<Type<'de> = Self::Response<'de>>,
{
const ID: MessageId;
type Response<'de>: Decode<'de, Binary, Global>;
#[doc(hidden)]
fn __do_not_implement_endpoint();
}
pub trait Broadcast
where
Self: 'static,
{
const ID: MessageId;
#[doc(hidden)]
fn __do_not_implement_broadcast();
}
pub trait BroadcastWithEvent
where
Self: Broadcast,
for<'de> Self: Decodable<Type<'de> = Self::Event<'de>>,
{
type Event<'de>: Event<Broadcast = Self> + Decode<'de, Binary, Global>
where
Self: 'de;
#[doc(hidden)]
fn __do_not_implement_broadcast_with_event();
}
pub trait Request
where
Self: Encode<Binary>,
{
type Endpoint: Endpoint;
#[doc(hidden)]
fn __do_not_implement_request();
}
pub trait Event
where
Self: Encode<Binary>,
{
type Broadcast: Broadcast;
#[doc(hidden)]
fn __do_not_implement_event();
}
#[derive(Debug, Clone, Copy, Encode, Decode)]
#[doc(hidden)]
#[musli(packed)]
pub struct Connect;
#[derive(Debug, Clone, Encode, Decode)]
#[doc(hidden)]
#[musli(packed)]
pub struct ResponseHeader {
pub serial: u32,
pub broadcast: u16,
pub error: u16,
pub channel: ChannelId,
}
#[derive(Debug, Clone, Encode, Decode)]
#[doc(hidden)]
#[musli(packed)]
pub struct ErrorMessage<'de> {
pub message: &'de str,
}
#[derive(Debug, Clone, Copy, Encode, Decode)]
#[doc(hidden)]
#[musli(packed)]
pub struct RequestHeader {
pub serial: u32,
pub id: u16,
pub channel: ChannelId,
}