Skip to main content

musli_web/
api.rs

1//! Shared traits for defining API types.
2
3use core::fmt;
4use core::num::NonZeroU16;
5
6use musli::alloc::Global;
7use musli::mode::Binary;
8use musli::{Decode, Encode};
9
10#[doc(inline)]
11pub use musli_web_macros::define;
12
13/// A trait for constructing identifiers.
14pub trait Id
15where
16    Self: 'static + Sized + fmt::Debug,
17{
18    /// Get the raw message identifier for this type.
19    fn id(&self) -> MessageId;
20
21    /// Construct an identifier from a raw message identifier.
22    fn from_id(id: MessageId) -> Self;
23
24    #[doc(hidden)]
25    fn __do_not_implement_id();
26}
27
28/// A raw identifier for a message.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode)]
30#[repr(transparent)]
31#[musli(transparent)]
32pub struct MessageId(NonZeroU16);
33
34impl fmt::Display for MessageId {
35    #[inline]
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        self.0.fmt(f)
38    }
39}
40
41impl MessageId {
42    /// The message id for [`ErrorMessage`].
43    pub const ERROR_MESSAGE: Self = unsafe { Self::new_unchecked((i16::MAX as u16) + 1) };
44
45    /// The message id for an empty packet constructed using [`Packet::empty`]
46    /// or [`RawPacket::empty`].
47    ///
48    /// [`Packet::empty`]: crate::web::Packet::empty
49    /// [`RawPacket::empty`]: crate::web::RawPacket::empty
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use musli_web::api::MessageId;
55    /// use musli_web::web::{RawPacket, Packet};
56    ///
57    /// let packet = RawPacket::empty();
58    /// assert_eq!(packet.id(), MessageId::EMPTY);
59    ///
60    /// let packet = Packet::<()>::empty();
61    /// assert_eq!(packet.id(), MessageId::EMPTY);
62    /// ```
63    pub const EMPTY: Self = unsafe { Self::new_unchecked(u16::MAX) };
64
65    /// Construct a raw message id.
66    #[inline]
67    pub const fn new(id: u16) -> Option<Self> {
68        let Some(value) = NonZeroU16::new(id) else {
69            return None;
70        };
71
72        Some(Self(value))
73    }
74
75    /// Get a raw message identifier.
76    #[inline]
77    pub const fn get(&self) -> u16 {
78        self.0.get()
79    }
80
81    /// Construct a new message ID.
82    ///
83    /// # Safety
84    ///
85    /// The caller must ensure that the provided `id` is non-zero.
86    #[inline]
87    pub const unsafe fn new_unchecked(id: u16) -> Self {
88        Self(unsafe { NonZeroU16::new_unchecked(id) })
89    }
90}
91
92/// A trait implemented for types which can be decoded into something.
93///
94/// Do not implement manually, instead use the [`define!`] macro.
95pub trait Decodable {
96    /// The decodable type related to this.
97    type Type<'de>: Decode<'de, Binary, Global>;
98
99    #[doc(hidden)]
100    fn __do_not_implement_decodable();
101}
102
103/// An endpoint marker trait.
104///
105/// Do not implement manually, instead use the [`define!`] macro.
106pub trait Endpoint
107where
108    Self: 'static,
109    for<'de> Self: Decodable<Type<'de> = Self::Response<'de>>,
110{
111    /// The kind of the endpoint.
112    const ID: MessageId;
113
114    /// The primary response type related to the endpoint.
115    type Response<'de>: Decode<'de, Binary, Global>;
116
117    #[doc(hidden)]
118    fn __do_not_implement_endpoint();
119}
120
121/// The marker trait used for broadcasts.
122///
123/// Do not implement manually, instead use the [`define!`] macro.
124pub trait Broadcast
125where
126    Self: 'static,
127{
128    /// The kind of the broadcast.
129    const ID: MessageId;
130
131    #[doc(hidden)]
132    fn __do_not_implement_broadcast();
133}
134
135/// Trait implemented for broadcasts which have a primary event.
136pub trait BroadcastWithEvent
137where
138    Self: Broadcast,
139    for<'de> Self: Decodable<Type<'de> = Self::Event<'de>>,
140{
141    /// The event type related to the broadcast.
142    type Event<'de>: Event<Broadcast = Self> + Decode<'de, Binary, Global>
143    where
144        Self: 'de;
145
146    #[doc(hidden)]
147    fn __do_not_implement_broadcast_with_event();
148}
149
150/// A marker indicating a request type.
151///
152/// Do not implement manually, instead use the [`define!`] macro.
153pub trait Request
154where
155    Self: Encode<Binary>,
156{
157    /// The endpoint related to the request.
158    type Endpoint: Endpoint;
159
160    #[doc(hidden)]
161    fn __do_not_implement_request();
162}
163
164/// The event of a broadcast.
165///
166/// Do not implement manually, instead use the [`define!`] macro.
167pub trait Event
168where
169    Self: Encode<Binary>,
170{
171    /// The endpoint related to the broadcast.
172    type Broadcast: Broadcast;
173
174    #[doc(hidden)]
175    fn __do_not_implement_event();
176}
177
178/// A request header.
179#[derive(Debug, Clone, Copy, Encode, Decode)]
180#[doc(hidden)]
181#[musli(packed)]
182pub struct RequestHeader {
183    /// The serial of the request.
184    pub serial: u32,
185    /// The kind of the request.
186    pub id: u16,
187}
188
189/// The header of a response.
190#[derive(Debug, Clone, Encode, Decode)]
191#[doc(hidden)]
192#[musli(packed)]
193pub struct ResponseHeader {
194    /// The serial request this is a response to.
195    pub serial: u32,
196    /// This is a broadcast over the specified type. If this is non-empty the
197    /// serial is 0.
198    pub broadcast: u16,
199    /// If non-zero, the response contains an error of the given type.
200    pub error: u16,
201}
202
203/// An error response.
204#[derive(Debug, Clone, Encode, Decode)]
205#[doc(hidden)]
206#[musli(packed)]
207pub struct ErrorMessage<'de> {
208    /// The error message.
209    pub message: &'de str,
210}