iona 0.3.2

A high-performance, memory mirror circular buffer
Documentation
//! `IonaBuffer` is a high-performance, virtual memory-mirror implementation of a circular buffer,
//! which guarantees slices up to the capacity of the buffer are contiguous in memory. Wrapped reads
//! wrap to the same physical memory seamlessly.
//!
//! ```
//! use iona::IonaBuffer;
//!
//! let mut buffer: IonaBuffer<usize> = match IonaBuffer::with_capacity(512) {
//!     Ok(buffer) => buffer,
//!     Err(_) => panic!("Unable to allocate the buffer"),
//! };
//!
//! buffer.fill(0);
//!
//! buffer.iter_mut().enumerate().for_each(|(i, value)| *value = i);
//!
//! buffer.push_back(512); // this is now at the physical address 0
//! buffer.push_back(513); // this is now at the physical address 1
//!
//! // No allocation/ concatenation needed when reading from the end of the physical buffer (the
//! // value `511`) to the next two values that were pushed to the back!
//! assert_eq!(buffer.get_from(509).to(3), Some([511,512,513].as_slice()));
//! ```
//!
//! ```text
//! VIRTUAL ADDRESS SPACE
//! ┌─────────────────────────────────┐
//! │                                 │
//! │   Page A  [0x0000 - 0x0FFF]     │──────────┐
//! │                                 │          │
//! ├─────────────────────────────────┤          ▼
//! │                                 │   ┌──────────────────┐
//! │   Page B  [0x1000 - 0x1FFF]     │──►│  PHYSICAL MEMORY │
//! │   (mirror)                      │   │                  │
//! └─────────────────────────────────┘   │  [ 0 ]  data[0]  │
//!                                       │  [ 1 ]  data[1]  │
//!                                       │  [ 2 ]  data[2]  │
//!                                       │  ...             │
//!                                       │  [ N ]  data[N]  │
//!                                       └──────────────────┘
//!
//!
//! KEY BENEFIT: A contiguous read/write spanning the page boundary
//! never needs to wrap — the mirror handles it transparently.
//! The following
//!
//!   Paage A                                           Page B
//! |                                                 |
//! | write ptr   read ptr                            | Read and write pointers never point to Page
//! |     │           │                               | B addresses, but slices span from Page A to
//! |     ▼           ▼                               | Page B.
//! [ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 0 | 1 | 2 | .. ]
//!                   ╰─────────────────────────────────────╯
//!                    contiguous memcpy, no wrap logic!
//! ```
//!
//! # Trade-Offs
//!
//!   - **Increased memory use**: we double the used virtual memory space, but still only have a
//!     single instance of physical memory backing the buffer. Moreover, this implementation
//!     requires that the buffer is mapped to page size, which is typically 4KiB. So if
//!     `size_of::<T>()` is small, the buffer will be relatively large and inefficient with memory
//!     use. The buffer also grows in size by powers of 2, so if 4KiB isn't large enough, the next
//!     buffer size, on most machines, will be 8KiB.
//!
//! # Indexing
//!
//! `IonaBuffer` implements the [Index](https://doc.rust-lang.org/std/ops/trait.Index.html) trait,
//! allowing you to access value by indexes:
//!
//! ```
//! # use iona::IonaBuffer;
//! #
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut buffer = IonaBuffer::try_from([0,2,4,6])?;
//!
//! assert_eq!(buffer[1], 2);
//! # Ok(())
//! # }
//!
//! ```
//!
//! However, indexing into a location outside of the `IonaBuffer` will panic! i.e.:
//!
//! ```should_panic
//! # use iona::IonaBuffer;
//! #
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut buffer = IonaBuffer::try_from([0,2,4,6])?;
//!
//! println!("{}", buffer[5]); // This will panic!
//! # Ok(())
//! # }
mod iona;

pub use iona::IonaBuffer;