Skip to main content

diny/
lib.rs

1#![feature(generic_associated_types)]
2
3#![cfg_attr(not(feature = "std"), no_std)]
4#![cfg_attr(not(feature = "unsafe_speed"), forbid(unsafe_code))]
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7#![deny(missing_docs)]
8
9//! An asynchronous, alloc-free, serialization framework written in 100% safe™ Rust.
10//!
11//! ### EXPERIMENTAL
12//! - `diny` currently requires the nightly Rust toolchain >= 1.56.0 for [GAT](https://github.com/rust-lang/rust/issues/44265) support.
13//! - `diny` is still in active design--the API is incomplete and prone to change without notice and without backward compatibility.
14//! - no_std support is largely ceremonial at this point as the futures-io _traits_ currently require std.
15//! 
16//! That being said, it _is_ ready for experimentation and design feedback.
17//! # Usage
18//!
19//! Add a dependency on `diny` and a serializer [format](backend::Format) in `Cargo.toml`:
20//!
21//! ```toml
22//! [dependencies]
23//! diny = { version = "0.2", features = ["derive"] }
24//! diny_test = "0.2"
25//! ```
26//!
27//! Enable [GAT](https://rust-lang.github.io/rfcs/1598-generic_associated_types.html)
28//! support in your project's module file (e.g. main.rs, lib.rs):
29//!
30//! ```
31//! #![feature(generic_associated_types)]
32//! ```
33//!
34//! Derive [AsyncSerialization] support for the desired data types, or derive just
35//! [AsyncSerialize] or [AsyncDeserialize] to limit the support to one-way transfers.
36//! 
37//! The [Serialize] and [Deserialize] objects returned from the [serializer](serializer::serializer)
38//! and [deserializer](deserializer::deserializer) methods implement sinks and streams (respectively)
39//! and are the simplest way to serialize and deserialize objects that implement [AsyncSerialization].
40//!
41//! ```
42//! # #![feature(generic_associated_types)]
43//! # extern crate futures;
44//! # extern crate diny_core;
45//! # extern crate diny_test;
46//! #
47//! use futures::{executor::block_on, SinkExt, StreamExt};
48//!
49//! #[derive(diny::AsyncSerialization)]
50//! pub struct Point {
51//!     x: i32,
52//!     y: i32,
53//! }
54//! 
55//! # fn main() {
56//! let point = Point { x: 1, y: 2 };
57//! 
58//! // A format can be any implementation of
59//! // diny::backend::{FormatSerialize + FormatDeserialize}.
60//! let format = diny_test::format();
61//! 
62//! // A writer can be any implementation of futures::io::AsyncWrite.
63//! // This example is using a Vec for simplicity.
64//! let writer = vec!();
65//! 
66//! // A sink is constructible for any implementor of diny::AsyncSerialize
67//! let mut sink = diny::serializer(format, writer).into_sink();
68//! block_on(sink.send(point)).unwrap();
69//! 
70//! // Sinks can be destructed back into the inner serializer
71//! let diny::Serializer { format, writer } = sink.try_into_inner().unwrap();
72//! 
73//! // A reader can be any implementation of futures::io::AsyncBufRead.
74//! // This example is using a utility module to convert the bytes
75//! // written to the vec into an async reader.
76//! let reader = diny::util::AsyncSliceReader::from(&writer[..]);
77//! 
78//! // A stream is constructible for any implementor of diny::AsyncDeserialize
79//! let mut stream = diny::deserializer(format, reader).into_stream();
80//! let _: Point = block_on(stream.next()).unwrap();
81//! # }
82//! ```
83//! 
84//! The [Serializer] and [Deserializer] objects expose `serialize` and
85//! `deserialize` methods respecively, which can be used to interleave
86//! different [serializable](AsyncSerialization) objects over
87//! the same channel.  This has the added benefit of serializing by
88//! reference instead of by value.
89//! 
90//! ```
91//! # #![feature(generic_associated_types)]
92//! # extern crate futures;
93//! # extern crate diny_core;
94//! # extern crate diny_test;
95//! #
96//! # use futures::executor::block_on;
97//! # use diny_test::format;
98//! #
99//! # #[derive(diny::AsyncSerialization)]
100//! # pub struct Point {
101//! #     x: i32,
102//! #     y: i32,
103//! # }
104//! #
105//! # fn main() {
106//! let point = Point { x: 1, y: 2 };
107//! let slope: i32 = 3;
108//!
109//! # let writer = vec!();
110//! # let format = format();
111//! #
112//! let mut serializer = diny::serializer(format, writer);
113//! # let diny::Serializer { format: _, writer } = 
114//! block_on(async {
115//!     serializer.serialize(&point).await?;
116//!     serializer.serialize(&slope).await?;
117//! #   let _ =
118//!     serializer.flush().await
119//! #   ?;
120//! #   let res: Result<diny::Serializer<diny_test::Formatter, Vec<u8>>, <diny_test::Formatter as diny::backend::Format>::Error> = Ok(serializer);
121//! #   res
122//! }).unwrap();
123//! 
124//! # let reader = diny::util::AsyncSliceReader::from(&writer[..]);
125//! let mut deserializer = diny::deserializer(format, reader);
126//! block_on(async {
127//!     deserializer.deserialize::<Point>().await?;
128//!     deserializer.deserialize::<i32>().await
129//! }).unwrap();
130//! # }
131//! ```
132//!
133//! The [AsyncSerialize] and [AsyncDeserialize] traits can be used directly without
134//! building an intermediate [Serializer] or [Deserializer] object.
135//! 
136//! ```
137//! # #![feature(generic_associated_types)]
138//! # extern crate futures;
139//! # extern crate diny_core;
140//! # extern crate diny_test;
141//! #
142//! # use futures::executor::block_on;
143//! use futures::io::AsyncWriteExt;
144//! use diny::{AsyncDeserialize, AsyncSerialize};
145//! # use diny_test::format;
146//!
147//! # #[derive(diny::AsyncSerialization)]
148//! # pub struct Point {
149//! #     x: i32,
150//! #     y: i32,
151//! # }
152//! #
153//! # fn main() {
154//! let point = Point { x: 1, y: 2 };
155//!
156//! # let format = format();
157//! #
158//! # let mut writer = vec!();
159//! let write = point.serialize(&format, &mut writer);
160//! block_on(write).unwrap();
161//! block_on(writer.flush()).unwrap();
162//! 
163//! # let mut reader = diny::util::AsyncSliceReader::from(&writer[..]);
164//! let read = Point::deserialize(&format, &mut reader);
165//! block_on(read).unwrap();
166//! # }
167//! ```
168//! 
169//! Additionally, an object's underlying [Encoder](backend::Encodable::Encoder)
170//! and [Decoder](backend::Decodable::Decoder) can be easily incorporated into
171//! custom futures.  See the [Serialize] and [Deserialize] implementations
172//! for an example of how to embed them.
173//! 
174//! An example of using the `async-compat` crate to interoperate with the
175//! `tokio` runtime is provided in the examples directory.
176//!
177//! ## Features
178//!
179//! By default, `diny` builds with (and currently requires) Rust's standard library.  Importantly,
180//! the `derive` proc macros are _not_ built by default, and need to be enabled to
181//! become available.
182//!
183//! | Feature        | Description                                                         | Default                       |
184//! |----------------|---------------------------------------------------------------------|:-----------------------------:|
185//! | `derive`       | Support for deriving [AsyncSerialize] and [AsyncDeserialize] traits | <font size="5">&#9744;</font> |
186//! | `unsafe_speed` | Permit using unsafe code to improve performance                     | <font size="5">&#9744;</font> |
187//! | `std`          | Support for Rust's standard library                                 | <font size="5">&#9745;</font> |
188//! | `alloc`        | Support for memory allocation without full `std` support            | <font size="5">&#9744;</font> |
189//! | `test`         | Build the diny_test formatter and re-export it to diny::test        | <font size="5">&#9744;</font> |
190//!
191#[cfg(all(not(feature = "std"), feature = "alloc"))]
192extern crate alloc;
193
194// Re-export everything from the core module for convenience
195pub use diny_core::*;
196
197// If the test serializer is enabled, pull it in as the 'test' module locally.
198#[cfg(feature = "test")]
199#[doc(hidden)]
200pub mod test {
201    pub use diny_test::*;
202}