arc_slice/
lib.rs

1//! A utility library for working with shared slices of memory.
2//!
3//! This crate provides efficient shared buffer implementations [`ArcSlice`] and [`ArcSliceMut`].
4//!
5//! # Examples
6//!
7//! ```rust
8//! use arc_slice::{ArcSlice, ArcSliceMut};
9//!
10//! let mut bytes_mut: ArcSliceMut<[u8]> = ArcSliceMut::new();
11//! bytes_mut.extend_from_slice(b"Hello world");
12//!
13//! let mut bytes: ArcSlice<[u8]> = bytes_mut.freeze();
14//!
15//! let a: ArcSlice<[u8]> = bytes.subslice(0..5);
16//! assert_eq!(a, b"Hello");
17//!
18//! let b: ArcSlice<[u8]> = bytes.split_to(6);
19//! assert_eq!(bytes, b"world");
20//! assert_eq!(b, b"Hello ");
21//! ```
22//!
23//! Depending on its [layout], [`ArcSlice`] can also support arbitrary buffers, e.g. shared memory,
24//! and provides optional metadata that can be attached to the buffer.
25//!
26//! ```rust
27//! use std::{
28//!     fs::File,
29//!     path::{Path, PathBuf},
30//! };
31//!
32//! use arc_slice::{buffer::AsRefBuffer, layout::ArcLayout, ArcBytes};
33//! use memmap2::Mmap;
34//!
35//! # fn main() -> std::io::Result<()> {
36//! let path = Path::new("README.md").to_owned();
37//! # #[cfg(not(miri))]
38//! let file = File::open(&path)?;
39//! # #[cfg(not(miri))]
40//! let mmap = unsafe { Mmap::map(&file)? };
41//! # #[cfg(miri)]
42//! # let mmap = b"# arc-slice".to_vec();
43//!
44//! let buffer = AsRefBuffer(mmap);
45//! let bytes: ArcBytes<ArcLayout<true>> = ArcBytes::from_buffer_with_metadata(buffer, path);
46//! assert!(bytes.starts_with(b"# arc-slice"));
47//! assert_eq!(bytes.metadata::<PathBuf>().unwrap(), Path::new("README.md"));
48//! # Ok(())
49//! # }
50//! ```
51//!
52//! ## Features
53//!
54//! The crate provides the following optional features:
55//! - `abort-on-refcount-overflow` (default): abort on refcount overflow; when disabled,
56//!   the refcount saturates on overflow, leaking allocated memory (as in Linux kernel refcounting).
57//! - `bstr`: implement slice traits for [`bstr`](::bstr) crate, allowing usage of `ArcSlice<BStr>`.
58//! - `bytemuck`: use [`bytemuck::Zeroable`] as a bound for zero-initialization with
59//!   [`ArcSliceMut::zeroed`].
60//! - `bytes`: implement [`Buf`](::bytes::Buf) and [`BufMut`](::bytes::BufMut) traits for
61//!   [`ArcSlice`] and [`ArcSliceMut`].
62//! - `inlined`: enable [Small String Optimization] for [`ArcSlice`] via [`inlined::SmallArcSlice`].
63//! - `oom-handling` (default): enable global [out-of-memory handling] with infallible allocation
64//!   methods.
65//! - `portable-atomic`: use [`portable_atomic`] instead of [`core::sync::atomic`].
66//! - `portable-atomic-util`: implement traits for [`portable_atomic_util::Arc`] instead of
67//!   [`alloc::sync::Arc`].
68//! - `raw-buffer`: enable [`RawBuffer`](buffer::RawBuffer) and [`RawLayout`](layout::RawLayout).
69//! - `serde`: implement [`Serialize`](::serde::Serialize) and [`Deserialize`](::serde::Deserialize)
70//!   for [`ArcSlice`] and [`ArcSliceMut`].
71//! - `std`: enable various `std` trait implementations and link to the standard library crate.
72//!
73//! Additionally, the default [layout] can be overridden with these features:
74//! - `default-layout-any-buffer`: set [`ArcLayout`] `ANY_BUFFER` to `true`.
75//! - `default-layout-static`: set [`ArcLayout`] `STATIC` to `true`.
76//! - `default-layout-boxed-slice`: override default layout to
77//!   [`BoxedSliceLayout`](layout::BoxedSliceLayout).
78//! - `default-layout-vec`: override default layout to [`VecLayout`](layout::VecLayout).
79//! - `default-layout-raw`: override default layout to [`RawLayout`](layout::RawLayout).
80//! - `default-layout-mut-any-buffer`: set [`ArcLayout`] `ANY_BUFFER` to `true` for [`ArcSliceMut`].
81//! - `default-layout-mut-vec`: override default layout to [`VecLayout`](layout::VecLayout) for
82//!   [`ArcSliceMut`].
83//!
84//! [Small String Optimization]: https://cppdepend.com/blog/understanding-small-string-optimization-sso-in-stdstring/
85//! [out-of-memory handling]: alloc::alloc::handle_alloc_error
86//! [`ArcLayout`]: layout::ArcLayout
87#![deny(missing_docs)]
88#![deny(missing_debug_implementations)]
89#![cfg_attr(docsrs, feature(doc_auto_cfg))]
90#![no_std]
91extern crate alloc;
92
93#[doc(hidden)]
94pub mod __private;
95mod arc;
96mod atomic;
97#[cfg(feature = "bstr")]
98mod bstr;
99pub mod buffer;
100#[cfg(feature = "bytes")]
101mod bytes;
102pub mod error;
103#[cfg(feature = "inlined")]
104pub mod inlined;
105pub mod layout;
106mod macros;
107mod msrv;
108#[cfg(feature = "serde")]
109mod serde;
110mod slice;
111mod slice_mut;
112mod utils;
113mod vtable;
114
115pub use crate::{
116    slice::{ArcSlice, ArcSliceBorrow},
117    slice_mut::ArcSliceMut,
118};
119
120/// An alias for `ArcSlice<[u8], L>`.
121pub type ArcBytes<L = layout::DefaultLayout> = ArcSlice<[u8], L>;
122/// An alias for `ArcSliceBorrow<[u8], L>`.
123pub type ArcBytesBorrow<'a, L = layout::DefaultLayout> = ArcSliceBorrow<'a, [u8], L>;
124/// An alias for `ArcSliceMut<[u8], L>`.
125pub type ArcBytesMut<L = layout::DefaultLayoutMut, const UNIQUE: bool = true> =
126    ArcSliceMut<[u8], L, UNIQUE>;
127/// An alias for `ArcSlice<str, L>`.
128pub type ArcStr<L = layout::DefaultLayout> = ArcSlice<str, L>;
129/// An alias for `ArcSliceBorrow<str, L>`.
130pub type ArcStrBorrow<'a, L = layout::DefaultLayout> = ArcSliceBorrow<'a, str, L>;
131/// An alias for `ArcSliceMut<str, L>`.
132pub type ArcStrMut<L = layout::DefaultLayoutMut, const UNIQUE: bool = true> =
133    ArcSliceMut<str, L, UNIQUE>;