archery/lib.rs
1#![no_std]
2#![cfg_attr(feature = "fatal-warnings", deny(warnings))]
3// Note: If you change this remember to update `README.md`. To do so run `cargo rdme`.
4//! `archery` is a rust library that offers a way to abstraction over
5//! [`Rc`](::alloc::rc::Rc) and
6//! [`Arc`](::alloc::sync::Arc) smart pointers.
7//! This allows you to create data structures where the pointer type is parameterizable, so you can
8//! [avoid the overhead of `Arc`](::alloc::sync::Arc#thread-safety)
9//! when you don’t need to share data across threads.
10//!
11//! In languages that supports
12//! [higher-kinded polymorphism](https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism)
13//! this would be simple to achieve without any library, but
14//! [rust does not support that yet](https://github.com/rust-lang/rfcs/issues/324).
15//! To mimic higher-kinded polymorphism `archery` implements the approach suggested by
16//! Joshua Liebow-Feeser in
17//! “[Rust has higher kinded types already… sort of](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/)”.
18//! While [other approaches](#alternative-approaches) exist, they seem to always offer poor
19//! ergonomics for the user.
20//!
21//! # Setup
22//!
23//! To use `archery` add the following to your `Cargo.toml`:
24//!
25//! ```toml
26//! [dependencies]
27//! archery = "<version>"
28//! ```
29//!
30//! # Using `archery`
31//!
32//! `archery` defines a [`SharedPointer`](crate::shared_pointer::SharedPointer)
33//! that receives the [kind of pointer](crate::shared_pointer::kind::SharedPointerKind)
34//! as a type parameter. This gives you a convenient and ergonomic way to abstract the pointer
35//! type away.
36//!
37//! ## Example
38//!
39//! Declare a data structure with the pointer kind as a type parameter bounded by
40//! [`SharedPointerKind`](crate::shared_pointer::kind::SharedPointerKind):
41//!
42//! ```rust
43//! use archery::*;
44//!
45//! struct KeyValuePair<K, V, P: SharedPointerKind> {
46//! pub key: SharedPointer<K, P>,
47//! pub value: SharedPointer<V, P>,
48//! }
49//!
50//! impl<K, V, P: SharedPointerKind> KeyValuePair<K, V, P> {
51//! fn new(key: K, value: V) -> KeyValuePair<K, V, P> {
52//! KeyValuePair {
53//! key: SharedPointer::new(key),
54//! value: SharedPointer::new(value),
55//! }
56//! }
57//! }
58//! ```
59//!
60//! To use it just plug-in the kind of pointer you want:
61//!
62//! ```rust
63//! # use archery::*;
64//! #
65//! # struct KeyValuePair<K, V, P: SharedPointerKind> {
66//! # pub key: SharedPointer<K, P>,
67//! # pub value: SharedPointer<V, P>,
68//! # }
69//! #
70//! # impl<K, V, P: SharedPointerKind> KeyValuePair<K, V, P> {
71//! # fn new(key: K, value: V) -> KeyValuePair<K, V, P> {
72//! # KeyValuePair {
73//! # key: SharedPointer::new(key),
74//! # value: SharedPointer::new(value),
75//! # }
76//! # }
77//! # }
78//! #
79//! let pair: KeyValuePair<_, _, RcK> =
80//! KeyValuePair::new("António Variações", 1944);
81//!
82//! assert_eq!(*pair.value, 1944);
83//! ```
84//!
85//! ## `triomphe::Arc`
86//!
87//! You can also use [`triomphe::Arc`](https://docs.rs/triomphe/latest/triomphe/struct.Arc.html)
88//! as the backing implementation of a [`SharedPointer`](crate::shared_pointer::SharedPointer).
89//! This is generally faster than [`std::sync::Arc`](::alloc::sync::Arc).
90//! Read [`triomphe`’s crate documentation](https://docs.rs/triomphe/latest/triomphe/) to learn more
91//! about it.
92//!
93//! To use it you need to enable the `triomphe` feature in `archery`. Use `ArcTK` as the pointer
94//! kind in [`SharedPointer`](crate::shared_pointer::SharedPointer).
95//!
96//! ## Serialization
97//!
98//! We support serialization through [serde](https://crates.io/crates/serde). To use it
99//! enable the `serde` feature. To do so change the archery dependency in your `Cargo.toml` to
100//!
101//! ```toml
102//! [dependencies]
103//! archery = { version = "<version>", features = ["serde"] }
104//! ```
105//! # Limitations
106//!
107//! Currently it is not possible to have unsized types inside a
108//! [`SharedPointer`](crate::shared_pointer::SharedPointer). As a workaround you can put the
109//! unsized type inside a [`Box`](::alloc::boxed::Box).
110//!
111//! # Alternative approaches
112//!
113//! An alternative to the approach taken by `archery` is to use traits with associated types to encode
114//! type-level functions. This has been suggested
115//! [multiple](https://github.com/orium/rpds/issues/7#issuecomment-362635901)
116//! [times](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/#comment-4160863400),
117//! but offers ugly ergonomics (see
118//! [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L153)
119//! and [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L249)).
120
121extern crate alloc;
122
123#[cfg(test)]
124#[macro_use]
125extern crate std;
126
127pub mod shared_pointer;
128
129pub use shared_pointer::SharedPointer;
130
131pub use shared_pointer::kind::SharedPointerKind;
132
133#[doc(no_inline)]
134pub use shared_pointer::kind::ArcK;
135#[cfg(feature = "triomphe")]
136#[doc(no_inline)]
137pub use shared_pointer::kind::ArcTK;
138#[doc(no_inline)]
139pub use shared_pointer::kind::RcK;