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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#![no_std]
#![cfg_attr(feature = "fatal-warnings", deny(warnings))]
// Note: If you change this remember to update `README.md`. To do so run `cargo rdme`.
//! `archery` is a rust library that offers a way to abstraction over
//! [`Rc`](::alloc::rc::Rc) and
//! [`Arc`](::alloc::sync::Arc) smart pointers.
//! This allows you to create data structures where the pointer type is parameterizable, so you can
//! [avoid the overhead of `Arc`](::alloc::sync::Arc#thread-safety)
//! when you don’t need to share data across threads.
//!
//! In languages that supports
//! [higher-kinded polymorphism](https://en.wikipedia.org/wiki/Type_class#Higher-kinded_polymorphism)
//! this would be simple to achieve without any library, but
//! [rust does not support that yet](https://github.com/rust-lang/rfcs/issues/324).
//! To mimic higher-kinded polymorphism `archery` implements the approach suggested by
//! Joshua Liebow-Feeser in
//! “[Rust has higher kinded types already… sort of](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/)”.
//! While [other approaches](#alternative-approaches) exist, they seem to always offer poor
//! ergonomics for the user.
//!
//! # Setup
//!
//! To use `archery` add the following to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! archery = "<version>"
//! ```
//!
//! # Using `archery`
//!
//! `archery` defines a [`SharedPointer`](crate::shared_pointer::SharedPointer)
//! that receives the [kind of pointer](crate::shared_pointer::kind::SharedPointerKind)
//! as a type parameter. This gives you a convenient and ergonomic way to abstract the pointer
//! type away.
//!
//! ## Example
//!
//! Declare a data structure with the pointer kind as a type parameter bounded by
//! [`SharedPointerKind`](crate::shared_pointer::kind::SharedPointerKind):
//!
//! ```rust
//! use archery::*;
//!
//! struct KeyValuePair<K, V, P: SharedPointerKind> {
//! pub key: SharedPointer<K, P>,
//! pub value: SharedPointer<V, P>,
//! }
//!
//! impl<K, V, P: SharedPointerKind> KeyValuePair<K, V, P> {
//! fn new(key: K, value: V) -> KeyValuePair<K, V, P> {
//! KeyValuePair {
//! key: SharedPointer::new(key),
//! value: SharedPointer::new(value),
//! }
//! }
//! }
//! ```
//!
//! To use it just plug-in the kind of pointer you want:
//!
//! ```rust
//! # use archery::*;
//! #
//! # struct KeyValuePair<K, V, P: SharedPointerKind> {
//! # pub key: SharedPointer<K, P>,
//! # pub value: SharedPointer<V, P>,
//! # }
//! #
//! # impl<K, V, P: SharedPointerKind> KeyValuePair<K, V, P> {
//! # fn new(key: K, value: V) -> KeyValuePair<K, V, P> {
//! # KeyValuePair {
//! # key: SharedPointer::new(key),
//! # value: SharedPointer::new(value),
//! # }
//! # }
//! # }
//! #
//! let pair: KeyValuePair<_, _, RcK> =
//! KeyValuePair::new("António Variações", 1944);
//!
//! assert_eq!(*pair.value, 1944);
//! ```
//!
//! ## `triomphe::Arc`
//!
//! You can also use [`triomphe::Arc`](https://docs.rs/triomphe/latest/triomphe/struct.Arc.html)
//! as the backing implementation of a [`SharedPointer`](crate::shared_pointer::SharedPointer).
//! This is generally faster than [`std::sync::Arc`](::alloc::sync::Arc).
//! Read [`triomphe`’s crate documentation](https://docs.rs/triomphe/latest/triomphe/) to learn more
//! about it.
//!
//! To use it you need to enable the `triomphe` feature in `archery`. Use `ArcTK` as the pointer
//! kind in [`SharedPointer`](crate::shared_pointer::SharedPointer).
//!
//! ## Serialization
//!
//! We support serialization through [serde](https://crates.io/crates/serde). To use it
//! enable the `serde` feature. To do so change the archery dependency in your `Cargo.toml` to
//!
//! ```toml
//! [dependencies]
//! archery = { version = "<version>", features = ["serde"] }
//! ```
//! # Limitations
//!
//! Currently it is not possible to have unsized types inside a
//! [`SharedPointer`](crate::shared_pointer::SharedPointer). As a workaround you can put the
//! unsized type inside a [`Box`](::alloc::boxed::Box).
//!
//! # Alternative approaches
//!
//! An alternative to the approach taken by `archery` is to use traits with associated types to encode
//! type-level functions. This has been suggested
//! [multiple](https://github.com/orium/rpds/issues/7#issuecomment-362635901)
//! [times](https://joshlf.com/post/2018/10/18/rust-higher-kinded-types-already/#comment-4160863400),
//! but offers ugly ergonomics (see
//! [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L153)
//! and [here](https://github.com/Marwes/rpds/blob/e482d5abbaa6c876d7c624e497affe7299bbeece/src/sequence/vector/mod.rs#L249)).
extern crate alloc;
#[cfg(test)]
#[macro_use]
extern crate std;
pub mod shared_pointer;
pub use shared_pointer::SharedPointer;
pub use shared_pointer::kind::SharedPointerKind;
#[doc(no_inline)]
pub use shared_pointer::kind::ArcK;
#[cfg(feature = "triomphe")]
#[doc(no_inline)]
pub use shared_pointer::kind::ArcTK;
#[doc(no_inline)]
pub use shared_pointer::kind::RcK;