npsd/
lib.rs

1//! # npsd (Network Payload Serializer / Deserializer)
2//!
3//! The `npsd` crate provides a flexible and efficient way to serialize and deserialize network payloads. 
4//! It supports converting Rust types into byte streams suitable for network transmission and reconstructing 
5//! those types from byte streams received over the network. This is particularly useful for networked 
6//! applications that require efficient and reliable data exchange.
7//!
8//! ## Features
9//! - Serialize and deserialize complex Rust types to and from byte streams.
10//! - Support for custom serialization contexts.
11//! - Middleware support for extensible processing during serialization/deserialization.
12//!
13//! ## Examples
14//! ### Sync Schema
15//! Requires the `sync` feature to be enabled.
16//! ```rust
17//! # #[cfg(feature = "sync")]
18//! use npsd::{Payload, Schema, Next, Info};
19//!
20//! # #[cfg(feature = "sync")]
21//! #[derive(Schema, Info, PartialEq, Debug)]
22//! enum Animal {
23//!     Dog,
24//!     Frog(String, Vec<isize>),
25//!     Cat { age: usize, name: String },
26//!     AntHive(Vec<String>),
27//! }
28//!
29//! # #[cfg(feature = "sync")]
30//! #[test]
31//! fn test_schema() {
32//!     // Create Middleware
33//!     let mut next = Next::default();
34//! 
35//!     // Create an instance of `Animal`.
36//!     let animal = Animal::Frog("Frog".to_string(), vec![12393818, -19383812, 11111, -1093838482]);
37//!
38//!     // Serialize the `animal` instance into a packet.
39//!     animal.into_packet(&mut (), &mut next).unwrap();
40//!
41//!     // Create a copy of serialized data if needed
42//!     let _serialized = next.serialized();
43//!
44//!     // Deserialize the packet back into an `Animal` instance.
45//!     let deserialized = Animal::from_packet(&mut (), &mut next).unwrap();
46//!
47//!     // Ensure the deserialized instance matches the original.
48//!     assert_eq!(deserialized, animal);
49//! }
50//! ```
51//!
52//! ### Async Schema
53//! Requires the `async` feature to be enabled.
54//! ```rust
55//! # #[cfg(feature = "async")]
56//! use npsd::{AsyncPayload, AsyncSchema, Next, Info};
57//!
58//! # #[cfg(feature = "async")]
59//! #[derive(AsyncSchema, Info, PartialEq, Debug)]
60//! enum Animal {
61//!     Dog,
62//!     Frog(String, Vec<isize>),
63//!     Cat { age: usize, name: String },
64//!     AntHive(Vec<String>),
65//! }
66//!
67//! # #[cfg(feature = "async")]
68//! #[tokio::test]
69//! async fn test_schema() {
70//!     // Create Middleware
71//!     let mut next = Next::default();
72//!
73//!     // Create an instance of `Animal`.
74//!     let animal = Animal::Frog("Frog".to_string(), vec![12393818, -19383812, 11111, -1093838482]);
75//!
76//!     // Serialize the `animal` instance into a packet.
77//!     animal.poll_into_packet(&mut (), &mut next).await.unwrap();
78//!
79//!     // Create a copy of serialized data if needed
80//!     let _serialized = next.serialized();
81//!
82//!     // Deserialize the packet back into an `Animal` instance.
83//!     let deserialized = Animal::poll_from_packet(&mut (), &mut next).await.unwrap();
84//!
85//!     // Ensure the deserialized instance matches the original.
86//!     assert_eq!(deserialized, animal);
87//! }
88//! ```
89//!
90//! ### Sync Bitmap
91//! Requires the `sync` feature to be enabled.
92//! ```rust
93//! # #[cfg(feature = "sync")]
94//! use npsd::{Payload, Bitmap, Next, Info};
95//!
96//! # #[cfg(feature = "sync")]
97//! #[derive(Bitmap, Info, PartialEq, Debug)]
98//! struct Flags {
99//!    a: bool,
100//!    b: bool,
101//!    c: bool,
102//! }
103//!
104//! # #[cfg(feature = "sync")]
105//! #[test]
106//! fn test_bitmap() {
107//!    // Create Middleware
108//!    let mut next = Next::default();
109//!
110//!    // Create an u8 bitmap of `Flags`.
111//!    let flags = Flags { a: true, b: false, c: true };
112//!
113//!    // Serialize the `Flags` into a packet.
114//!    flags.into_packet(&mut (), &mut next).unwrap();
115//!
116//!    // Create a copy of serialized data if needed
117//!    let _serialized = next.serialized();
118//!
119//!    // Deserialize the packet back into an `Flags`.
120//!    let deserialized = Flags::from_packet(&mut (), &mut next).unwrap();
121//!
122//!    // Ensure the deserialized matches the original.
123//!    assert_eq!(deserialized, flags);
124//! }
125//! ```
126//!
127//! ### Async Bitmap
128//! Requires the `async` feature to be enabled.
129//! ```rust
130//! # #[cfg(feature = "async")]
131//! use npsd::{AsyncPayload, AsyncBitmap, Next, Info};
132//!
133//! # #[cfg(feature = "async")]
134//! #[derive(AsyncBitmap, Info, PartialEq, Debug)]
135//! struct Flags {
136//!    a: bool,
137//!    b: bool,
138//!    c: bool,
139//! }
140//!
141//! # #[cfg(feature = "async")]
142//! #[tokio::test]
143//! async fn test_async_bitmap() {
144//!    // Create Middleware
145//!    let mut next = Next::default();
146//!
147//!    // Create an u8 bitmap of `Flags`.
148//!    let flags = Flags { a: true, b: false, c: true };
149//!
150//!    // Serialize the `Flags` into a packet.
151//!    flags.poll_into_packet(&mut (), &mut next).await.unwrap();
152//!
153//!    // Create a copy of serialized data if needed
154//!    let _serialized = next.serialized();
155//!
156//!    // Deserialize the packet back into an `Flags`.
157//!    let deserialized = Flags::poll_from_packet(&mut (), &mut next).await.unwrap();
158//!
159//!    // Ensure the deserialized matches the original.
160//!    assert_eq!(deserialized, flags);
161//! }
162//! ```
163
164
165/// The `Middleware` trait defines methods for converting types to and from payloads of bytes.
166///
167/// ### Methods
168///
169/// - `fn into_payload<C, T: IntoPayload<C>>(&mut self, value: &T, ctx: &mut C) -> Result<(), Error>`:
170///     - Converts a value into a payload of bytes. This method takes a value and a context, serializes the value into a byte stream, and writes the resulting bytes into the handler.
171/// - `fn from_payload<'a, C, T: FromPayload<'a, C>>(&mut self, ctx: &mut C) -> Result<T, Error>`:
172///     - Converts a payload of bytes back into a value. This method reads bytes from the handler, uses the context to interpret them, and reconstructs the original value.
173/// - `fn write<T>(&mut self, data: &[T]) -> Result<(), Error>`:
174///     - Writes raw data into the handler. This method takes a slice of data and appends it to the handler after ensuring that the size of the data elements is 1 byte.
175/// - `fn read<'a, T>(&'a mut self, nbytes: usize) -> Result<&'a [T], Error>`:
176///     - Reads raw data from the handler. This method reads a specified number of bytes from the handler, splits the handler's data accordingly, and returns a slice of the read data.
177/// - `fn read_mut<'a, T>(&'a mut self, nbytes: usize) -> Result<&'a mut [T], Error>`:
178///     - Reads raw data from the handler. This method reads a specified number of bytes from the handler, splits the handler's data accordingly, and returns a mutable slice of the read data.
179/// - `fn push<T: AnyBox<'a>>(&mut self, value: Box<T>) -> Result<&'a T, Error>`:
180///     - Pushes a boxed value into the handler, returning a reference to the stored value.
181/// - `fn push_mut<T: AnyBox<'a>>(&mut self, value: Box<T>) -> Result<&'a mut T, Error>`:
182///     - Pushes a boxed value into the handler, returning a mutable reference to the stored value.
183/// - `fn push_array<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> Result<&'a [T], Error>`:
184///     - Pushes a boxed array of values into the handler, returning a reference to the stored array.
185/// - `fn push_array_mut<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> Result<&'a mut [T], Error>`:
186///     - Pushes a boxed array of values into the handler, returning a mutable reference to the stored array.
187#[cfg(feature = "sync")]
188pub trait Middleware<'a> {
189    fn into_payload<C, T: IntoPayload<C>>(&mut self, value: &T, ctx: &mut C) -> Result<(), Error>;
190    fn from_payload<C, T: FromPayload<'a, C>>(&mut self, ctx: &mut C) -> Result<T, Error>;
191
192    fn write<T>(&mut self, data: &[T]) -> Result<(), Error>;
193    fn read<T>(&mut self, nbytes: usize) -> Result<&'a [T], Error>;
194    fn read_mut<T>(&mut self, nbytes: usize) -> Result<&'a mut [T], Error>;
195
196    fn push<T: AnyBox<'a>>(&mut self, value: Box<T>) -> Result<&'a T, Error>;
197    fn push_mut<T: AnyBox<'a>>(&mut self, value: Box<T>) -> Result<&'a mut T, Error>;
198    fn push_array<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> Result<&'a [T], Error>;
199    fn push_array_mut<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> Result<&'a mut [T], Error>;
200}
201
202/// The `AsyncMiddleware` trait defines asynchronous methods for converting types to and from payloads of bytes.
203///
204/// ### Methods
205/// - `fn poll_into_payload<'a, C, T: AsyncIntoPayload<C>>(&mut self, value: &T, ctx: &mut C) -> impl Future<Output = Result<(), Error>>`:
206///     - Polls the conversion of a value into a payload of bytes asynchronously.
207/// - `fn poll_from_payload<'a, C, T: AsyncFromPayload<'a, C>>(&mut self, ctx: &mut C) -> impl Future<Output = Result<T, Error>>`:
208///     - Polls the conversion of a payload of bytes back into a value asynchronously.
209/// - `fn poll_write<T>(&mut self, data: &[T]) -> impl Future<Output = Result<(), Error>>`:
210///     - Polls the asynchronous writing of raw data into the handler.
211/// - `fn poll_read<'a, T>(&'a mut self, nbytes: usize) -> impl Future<Output = Result<&'a [T], Error>>`:
212///     - Polls the asynchronous reading of raw data from the handler.
213/// - `fn poll_read_mut<'a, T>(&'a mut self, nbytes: usize) -> impl Future<Output = Result<&'a mut [T], Error>>`:
214///     - Polls the asynchronous reading of raw data from the handler, returning a mutable slice of the read data.
215/// - `fn poll_push<T: AnyBox<'a>>(&mut self, value: Box<T>) -> impl Future<Output = Result<&'a T, Error>>`:
216///     - Polls the asynchronous pushing of a boxed value into the handler, returning a reference to the stored value.
217/// - `fn poll_push_mut<T: AnyBox<'a>>(&mut self, value: Box<T>) -> impl Future<Output = Result<&'a mut T, Error>>`:
218///     - Polls the asynchronous pushing of a boxed value into the handler, returning a mutable reference to the stored value.
219/// - `fn poll_push_array<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> impl Future<Output = Result<&'a [T], Error>>`:
220///     - Polls the asynchronous pushing of a boxed array of values into the handler, returning a reference to the stored array.
221/// - `fn poll_push_array_mut<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> impl Future<Output = Result<&'a mut [T], Error>>`:
222///     - Polls the asynchronous pushing of a boxed array of values into the handler, returning a mutable reference to the stored array.
223#[cfg(feature = "async")]
224pub trait AsyncMiddleware<'a>: Send + Sync {
225    fn poll_into_payload<C: Send + Sync, T: AsyncIntoPayload<C>>(&mut self, value: &T, ctx: &mut C) -> impl Future<Output = Result<(), Error>>;
226    fn poll_from_payload<C: Send + Sync, T: AsyncFromPayload<'a, C>>(&mut self, ctx: &mut C) -> impl Future<Output = Result<T, Error>>;
227
228    fn poll_write<T>(&mut self, data: &[T]) -> impl Future<Output = Result<(), Error>>;
229    fn poll_read<T: 'a>(&mut self, nbytes: usize) -> impl Future<Output = Result<&'a [T], Error>>;
230    fn poll_read_mut<T: 'a>(&mut self, nbytes: usize) -> impl Future<Output = Result<&'a mut [T], Error>>;
231
232    fn poll_push<T: AnyBox<'a>>(&mut self, value: Box<T>) -> impl Future<Output = Result<&'a T, Error>>;
233    fn poll_push_mut<T: AnyBox<'a>>(&mut self, value: Box<T>) -> impl Future<Output = Result<&'a mut T, Error>>;
234    fn poll_push_array<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> impl Future<Output = Result<&'a [T], Error>>;
235    fn poll_push_array_mut<T: AnyBox<'a>>(&mut self, values: Box<[T]>) -> impl Future<Output = Result<&'a mut [T], Error>>;
236}
237
238/// The `IntoPayload` trait is used to convert a type into a payload of bytes.
239///
240/// ### Methods
241/// - `fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error>`:
242///     - Converts a value into a payload of bytes. This method takes the value, context, and middleware, serializes the value into a byte stream, and writes it into the handler.
243#[cfg(not(feature = "info"))]
244#[cfg(feature = "sync")]
245pub trait IntoPayload<C> {
246    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error>;
247}
248
249#[cfg(feature = "info")]
250#[cfg(feature = "sync")]
251pub trait IntoPayload<C>: PayloadInfo {
252    fn into_payload<'m, M: Middleware<'m>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error>;
253}
254
255/// The `AsyncIntoPayload` trait is used for asynchronous methods for converting types into payloads of bytes.
256///
257/// ### Methods
258/// - `fn poll_into_payload<'m, M: AsyncMiddleware<'m>>(&self, ctx: &mut C, next: &mut M) -> impl Future<Output = Result<(), Error>>`:
259///     - Polls the conversion of a value into a payload of bytes asynchronously.
260#[cfg(not(feature = "info"))]
261#[cfg(feature = "async")]
262pub trait AsyncIntoPayload<C: Send + Sync>: Send + Sync {
263    fn poll_into_payload<'m, M: AsyncMiddleware<'m>>(&self, ctx: &mut C, next: &mut M) -> impl Future<Output = Result<(), Error>>;
264}
265
266#[cfg(feature = "info")]
267#[cfg(feature = "async")]
268pub trait AsyncIntoPayload<C: Send + Sync>: PayloadInfo + Send + Sync {
269    fn poll_into_payload<'m, M: AsyncMiddleware<'m>>(&self, ctx: &mut C, next: &mut M) -> impl Future<Output = Result<(), Error>>;
270}
271
272/// The `FromPayload` trait is used to convert a payload of bytes back into a type.
273/// 
274/// ### Methods
275/// - `fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error>`:
276///     - Converts a payload of bytes back into a value. This method reads bytes from the handler, uses the context and middleware to interpret them, and reconstructs the original value.
277#[cfg(not(feature = "info"))]
278#[cfg(feature = "sync")]
279pub trait FromPayload<'a, C>: Sized {
280    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error>;
281}
282
283#[cfg(feature = "info")]
284#[cfg(feature = "sync")]
285pub trait FromPayload<'a, C>: PayloadInfo + Sized {
286    fn from_payload<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error>;
287}
288
289/// The `AsyncFromPayload` trait is used for asynchronous methods for converting payloads of bytes back into types.
290///
291/// ### Methods
292/// - `fn poll_from_payload<'m, M: AsyncMiddleware<'a>>(ctx: &mut C, next: &mut M) -> impl Future<Output = Result<Self, Error>>`:
293///     - Polls the conversion of a payload of bytes back into a value asynchronously.
294#[cfg(not(feature = "info"))]
295#[cfg(feature = "async")]
296pub trait AsyncFromPayload<'a, C: Send + Sync>: Sized + Send + Sync {
297    fn poll_from_payload<M: AsyncMiddleware<'a>>(ctx: &mut C, next: &mut M) -> impl Future<Output = Result<Self, Error>>;
298}
299
300#[cfg(feature = "info")]
301#[cfg(feature = "async")]
302pub trait AsyncFromPayload<'a, C: Send + Sync>: PayloadInfo + Sized + Send + Sync {
303    fn poll_from_payload<M: AsyncMiddleware<'a>>(ctx: &mut C, next: &mut M) -> impl Future<Output = Result<Self, Error>>;
304}
305
306/// The `Payload` trait combines `IntoPayload` and `FromPayload` to facilitate complete serialization and deserialization of types.
307///
308/// ### Methods
309/// - `fn into_packet<'b, M: Middleware<'b>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error>`:
310///     - Serializes a value into a buffer. This method takes the value, context, and an initial buffer capacity, serializes the value, and returns the resulting byte buffer.
311/// - `fn from_packet<'m, M: Middleware<'m>>(ctx: &mut C, next: &mut M) -> Result<Self, Error>`:
312///     - Deserializes a buffer into a value. This method takes a context and a buffer containing the serialized data, and returns the deserialized value.
313#[cfg(feature = "sync")]
314pub trait Payload<'a, C>: IntoPayload<C> + FromPayload<'a, C> + Sized {
315    fn into_packet<'b, M: Middleware<'b>>(&self, ctx: &mut C, next: &mut M) -> Result<(), Error> {
316        next.into_payload(self, ctx)
317    }
318
319    #[inline(always)]
320    fn from_packet<M: Middleware<'a>>(ctx: &mut C, next: &mut M) -> Result<Self, Error> {
321        next.from_payload(ctx)
322    }
323}
324
325/// The `AsyncPayload` trait combines `AsyncIntoPayload` and `AsyncFromPayload` to asynchronous methods for complete serialization and deserialization of types.
326///
327/// ### Methods
328/// - `fn poll_into_packet<'m, M: AsyncMiddleware<'m>>(&self, ctx: &mut C, next: &mut M) -> impl Future<Output = Result<(), Error>>`:
329///     - Initiates the asynchronous conversion of a value into a packet.
330/// - `fn poll_from_packet<'m, M: AsyncMiddleware<'m>>(ctx: &mut C, next: &mut M) -> impl Future<Output = Result<Self, Error>>`:
331///     - Initiates the asynchronous deserialization of a packet into a value.
332#[cfg(feature = "async")]
333pub trait AsyncPayload<'a, C: Send + Sync>: AsyncIntoPayload<C> + AsyncFromPayload<'a, C> + 'a + Send + Sync + Sized {
334    fn poll_into_packet<'b, M: AsyncMiddleware<'b>>(&self, ctx: &mut C, next: &mut M) -> impl Future<Output = Result<(), Error>> {
335        next.poll_into_payload(self, ctx)
336    }
337
338    #[inline(always)]
339    fn poll_from_packet<M: AsyncMiddleware<'a>>(ctx: &mut C, next: &mut M) -> impl Future<Output = Result<Self, Error>> {
340        next.poll_from_payload(ctx)
341    }
342}
343
344pub trait AnyBox<'a>: Send + Sync + 'a {}
345impl<'a, T: Send + Sync + 'a> AnyBox<'a> for T {}
346
347/// The `PayloadInfo` trait provides metadata about the payload.
348///
349/// ### Associated Constants
350/// - `const HASH: u64`: A constant hash value associated with the type.
351/// - `const TYPE: &'static str`: A string representing the type of the payload.
352/// - `const SIZE: Option<usize>`: An optional constant representing the size of the payload.
353pub trait PayloadInfo {
354    const HASH: u64 = PayloadConstHash(Self::TYPE.as_bytes());
355    const TYPE: &'static str = "Unknown";
356    const SIZE: Option<usize> = None;
357}
358
359pub mod middleware;
360pub mod error;
361pub mod info;
362pub mod features;
363
364#[cfg(feature = "crossbeam")]
365pub mod stack;
366
367#[cfg(feature = "crossbeam")]
368pub use stack::*;
369
370#[cfg(feature = "sync")]
371pub mod payload;
372
373#[cfg(feature = "async")]
374pub mod poll_payload;
375
376#[cfg(feature = "async")]
377use core::future::Future;
378
379#[doc(hidden)]
380pub use xxhash_rust::const_xxh3::xxh3_64 as PayloadConstHash;
381#[doc(hidden)]
382pub use xxhash_rust::xxh3::xxh3_64 as PayloadHash;
383
384pub use error::*;
385pub use middleware::*;
386pub use npsd_schema::*;