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;