hipstr/
lib.rs

1//! Yet another **string type** for Rust 🦀
2//!
3//! * no copy and `const` **literal wrapping**
4//! * no alloc **small strings** (_23 bytes_ on 64-bit platform)
5//! * no copy **owned slices**
6//! * a niche: `Option<HipStr>` and `HipStr` have the same size
7//! * **zero dependency**, except for optional `serde` support
8//!
9//! Also byte strings, OS strings, paths, too!
10//!
11//! # Examples
12//!
13//! ```rust
14//! use hipstr::HipStr;
15//!
16//! let simple_greetings = HipStr::borrowed("Hello world");
17//! let clone = simple_greetings.clone(); // no copy
18//! std::thread::spawn(move || { println!("{}", clone); });
19//!
20//! let user = "John";
21//! let greetings = HipStr::from(format!("Hello {}", user));
22//! let user = greetings.slice(6..); // no copy
23//! drop(greetings); // the slice is _owned_, it exists even if greetings disappear
24//!
25//! let chars = user.chars().count(); // "inherits" `&str` methods
26//! ```
27//!
28//! # Three Representations
29//!
30//! Each type has three distinct representations:
31//!
32//! - Borrowed slice
33//! - Inline sequence (up to [`HipByt::inline_capacity()`])
34//! - Shared reference (cheaply clonable) _and slice_ (sliceable)
35//!
36//! The shared reference can be thread-safe or not, depending on the backend.
37//!
38//! Most operations keep string **normalized**, that is, if the string is not
39//! borrowed, the inline representation is preferred when possible.
40//!
41//! ## ⚠️ Warning!
42//!
43//! The used representation of the empty string is **unspecified** and may
44//! change between patch versions! It may be _borrowed_ or _inlined_ but will
45//! never be allocated.
46//!
47//! # Three Backends
48//!
49//! The crate provides three backends:
50//!
51//! - `Arc` (atomic reference counting), formerly `ThreadSafe`
52//! - `Rc` (reference counting), formerly `Local`
53//! - `Unique` (unique reference)
54//!
55//! The last backend, `Unique`, is mostly an experiment in pushing what
56//! constitutes a hipstr backend and has **no practical use**.
57//!
58//! The crate root also provides some convenience type aliases, typically for
59//! strings:
60//!
61//! - `hipstr::HipStr` with the `Arc` backend,
62//! - `hipstr::LocalHipStr` with the `Rc` backend.
63//!
64//! # Platform Support
65//!
66//! This crate is only supported on platforms where:
67//!
68//! - pointers have the same memory size as `usize`,
69//! - pointer alignment requirement is strictly greater than **2**.
70//!
71//! For now, most common architectures are like that. However, `hipstr` will not
72//! work on new and future architectures relying on large tagged pointers (e.g.
73//! CHERI 128-bit pointers).
74//!
75//! # Features
76//!
77//! * `std` (default): uses `std` rather than `core` and `alloc`, and also
78//!   provides more trait implementations (for comparison, conversions)
79//! * `serde`: provides serialization/deserialization support with [`serde`](https://serde.rs)
80//! * `borsh`: provides serialization/deserialization support with [`borsh`](https://borsh.io)
81//! * `bstr`: provides compatibility with [BurntSushi's bstr
82//!   crate](https://github.com/BurntSushi/bstr) make `HipByt` deref to
83//!   [`&bstr::BStr`](bstr::BStr) rather than [`&[u8]`](slice)
84//! * `unstable`: do nothing, used to reveal unstable implementation details
85
86#![no_std]
87#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
88#![cfg_attr(docsrs, feature(doc_auto_cfg))]
89#![cfg_attr(docsrs, feature(doc_cfg))]
90#![warn(clippy::pedantic, clippy::nursery, clippy::cargo)]
91#![warn(unsafe_op_in_unsafe_fn)]
92
93extern crate alloc;
94#[cfg(feature = "std")]
95extern crate std;
96pub(crate) mod backend;
97pub mod bytes;
98pub(crate) mod macros;
99pub(crate) mod smart;
100pub mod string;
101
102#[cfg(feature = "std")]
103pub mod os_string;
104#[cfg(feature = "std")]
105pub mod path;
106
107#[cfg(test)]
108pub mod tests;
109
110pub use backend::*;
111
112/// Thread-safe shared byte sequence.
113pub type HipByt<'borrow> = bytes::HipByt<'borrow, Arc>;
114
115/// Thread-safe shared string.
116pub type HipStr<'borrow> = string::HipStr<'borrow, Arc>;
117
118/// Thread-safe shared string.
119#[cfg(feature = "std")]
120pub type HipOsStr<'borrow> = os_string::HipOsStr<'borrow, Arc>;
121
122/// Thread-safe shared path.
123#[cfg(feature = "std")]
124pub type HipPath<'borrow> = path::HipPath<'borrow, Arc>;
125
126/// Thread-local shared byte sequence.
127pub type LocalHipByt<'borrow> = bytes::HipByt<'borrow, Rc>;
128
129/// Thread-local shared string.
130pub type LocalHipStr<'borrow> = string::HipStr<'borrow, Rc>;
131
132/// Thread-local shared byte sequence.
133#[cfg(feature = "std")]
134pub type LocalHipOsStr<'borrow> = os_string::HipOsStr<'borrow, Rc>;
135
136/// Thread-local shared path.
137#[cfg(feature = "std")]
138pub type LocalHipPath<'borrow> = path::HipPath<'borrow, Rc>;