1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Fixed-length, allocation and lock-free, async I/O oriented single-producer single-consumer
//! (SPSC) queues.
//!
//! # Overview
//! This library provides several fixed-length queues for different use-cases, based around the same
//! core:
//!  - [`asyncio`] is a generic async, thread-safe, lock-free queue using [futures]. Read
//!    operations can pause until data is available, and write operations can pause until space is
//!    returned. The queue can act as an efficient I/O buffer with [`futures::AsyncRead`] and
//!    [`futures::AsyncWrite`] implementations.
//!  - [`blocking`] is a generic thread-safe queue. Read operations can block until data is
//!    available, and write operations can block until space is returned. The queue can act as an
//!    efficient I/O buffer with [`io::Read`] and [`io::Write`] implementations.
//!  - [`nonblocking`] is a generic thread-safe, lock-free queue that is guaranteed to not block.
//!    It can act as an efficient I/O buffer when read and write speed is matched or no locks
//!    are available.
//!
//! All queues have separate `Reader` and `Writer` ends which can be sent across threads. Queues are
//! designed with bulk operations in mind, so can safely be used with large read and write
//! operations, such as in a byte array I/O context.
//!
//! The library also provides [`Ring`], a low-level atomic ring buffer building block used to
//! implement the various queues available.
//!
//! The library supports `no_std` with a reduced feature set, and is highly configurable. With the
//! default feature set, it does not require any dependencies.
//!
//! # Features
//!
//!  - `asyncio` - enables the [`asyncio`] queue, using the [`futures`] library. Requires [`alloc`].
//!  - `blocking` - enables the [`blocking`] queue. Requires [`std`] (as this queue uses locks).
//!  - `nonblocking` - enables the [`nonblocking`] queue. Requires [`alloc`].
//!  - `heap-buffer` - enables [`HeapBuffer`], which allocates queue storage on the heap. Requires [`alloc`].
//!  - `stack-buffer` - enables [`StackBuffer`], which allocates queue storage on the stack.
//!  - `std-io` - enables implementations for standard I/O traits ([`io::Read`], [`io::Write`], and
//!    [`futures::AsyncRead`] and [`futures::AsyncWrite`]). Requires [`std`].
//!
//! # Examples
//! ## Simple async example
//! ```
//! use futures::executor::block_on;
//! use futures::join;
//! use mini_io_queue::asyncio::queue;
//!
//! let (mut reader, mut writer) = queue(8);
//!
//! let write_loop = async {
//!     for i in 0..16 {
//!         writer.write_all(&[i]).await.unwrap();
//!     }
//! };
//!
//! let read_loop = async {
//!     for i in 0..16 {
//!         let mut buf = [0];
//!         reader.read_exact(&mut buf).await.unwrap();
//!
//!         assert_eq!(buf[0], i);
//!     }
//! };
//!
//! block_on(async { join!(write_loop, read_loop) });
//! ```
//!
//! ## Blocking queue with a custom ring
//! ```
//! use mini_io_queue::blocking::queue_from_parts;
//! use mini_io_queue::Ring;
//! use mini_io_queue::storage::{HeapBuffer, Storage};
//!
//! // Create a queue with half of the underlying buffer in the read side.
//! let ring = Ring::new(10);
//! ring.advance_right(5);
//!
//! let mut buffer = HeapBuffer::new(10);
//! buffer.slice_mut(0..5).copy_from_slice(&[1, 2, 3, 4, 5]);
//!
//! let (mut reader, _) = queue_from_parts(ring, buffer);
//!
//! for i in 1..=5 {
//!     let mut buf = [0];
//!     reader.read_exact(&mut buf).unwrap();
//!
//!     assert_eq!(buf[0], i);
//! }
//! ```
//!
//! [`io::Read`]: std::io::Read
//! [`io::Write`]: std::io::Write
//! [`HeapBuffer`]: storage::HeapBuffer
//! [`StackBuffer`]: storage::StackBuffer

#![cfg_attr(not(any(feature = "std")), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(rustdoc::private_intra_doc_links)]

extern crate core;

#[cfg(feature = "alloc")]
extern crate alloc;

mod region;
mod ring;
pub mod storage;

#[cfg(feature = "asyncio")]
#[cfg_attr(docsrs, doc(cfg(feature = "asyncio")))]
pub mod asyncio;

#[cfg(feature = "nonblocking")]
#[cfg_attr(docsrs, doc(cfg(feature = "nonblocking")))]
pub mod nonblocking;

#[cfg(feature = "blocking")]
#[cfg_attr(docsrs, doc(cfg(feature = "blocking")))]
pub mod blocking;

pub use self::region::*;
pub use self::ring::*;