archery/ 0000775 0001750 0001750 00000000000 14717116335 013177 5 ustar jamespage jamespage archery/README.md 0000644 0001750 0001750 00000012225 14717116335 014456 0 ustar jamespage jamespage [](https://github.com/orium/archery/actions?query=workflow%3ACI)
[](https://codecov.io/gh/orium/archery)
[](https://deps.rs/repo/github/orium/archery)
[](https://crates.io/crates/archery)
[](https://crates.io/crates/archery)
[](https://github.com/orium/archery/stargazers)
[](https://docs.rs/archery/)
[](./LICENSE.md)
# `archery`
`archery` is a rust library that offers a way to abstraction over
[`Rc`](https://doc.rust-lang.org/stable/alloc/rc/struct.Rc.html) and
[`Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html) smart pointers.
This allows you to create data structures where the pointer type is parameterizable, so you can
[avoid the overhead of `Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html#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 = ""
```
## Using `archery`
`archery` defines a [`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html)
that receives the [kind of pointer](https://docs.rs/archery/latest/archery/shared_pointer/kind/trait.SharedPointerKind.html)
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`](https://docs.rs/archery/latest/archery/shared_pointer/kind/trait.SharedPointerKind.html):
```rust
use archery::*;
struct KeyValuePair {
pub key: SharedPointer,
pub value: SharedPointer,
}
impl KeyValuePair {
fn new(key: K, value: V) -> KeyValuePair {
KeyValuePair {
key: SharedPointer::new(key),
value: SharedPointer::new(value),
}
}
}
```
To use it just plug-in the kind of pointer you want:
```rust
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`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html).
This is generally faster than [`std::sync::Arc`](https://doc.rust-lang.org/stable/alloc/sync/struct.Arc.html).
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`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html).
### 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 = "", features = ["serde"] }
```
## Limitations
Currently it is not possible to have unsized types inside a
[`SharedPointer`](https://docs.rs/archery/latest/archery/shared_pointer/struct.SharedPointer.html). As a workaround you can put the
unsized type inside a [`Box`](https://doc.rust-lang.org/stable/alloc/boxed/struct.Box.html).
## 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)).
archery/Cargo.toml 0000644 0001750 0001750 00000004634 14717116335 015134 0 ustar jamespage jamespage # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.66.0"
name = "archery"
version = "1.2.1"
authors = ["Diogo Sousa "]
build = false
include = [
"/src/**/*.rs",
"/Cargo.toml",
"/LICENSE.md",
"/README.md",
"/release-notes.md",
]
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "Abstract over the atomicity of reference-counting pointers"
homepage = "https://github.com/orium/archery"
documentation = "https://docs.rs/archery"
readme = "README.md"
keywords = [
"rc",
"arc",
"reference-counting",
"no_std",
]
categories = [
"concurrency",
"memory-management",
"rust-patterns",
]
license = "MPL-2.0"
repository = "https://github.com/orium/archery"
[package.metadata.docs.rs]
features = [
"triomphe",
"serde",
]
[lib]
name = "archery"
path = "src/lib.rs"
bench = false
[dependencies.serde]
version = "1.0.204"
optional = true
default-features = false
[dependencies.triomphe]
version = "0.1.13"
optional = true
default-features = false
[dev-dependencies.bincode]
version = "1.3.3"
[dev-dependencies.criterion]
version = "0.5.1"
features = ["html_reports"]
[dev-dependencies.pretty_assertions]
version = "1.4.0"
[dev-dependencies.static_assertions]
version = "1.1.0"
[features]
fatal-warnings = []
serde = ["dep:serde"]
triomphe = ["dep:triomphe"]
[badges.codecov]
branch = "main"
repository = "orium/archery"
service = "github"
[lints.clippy]
explicit-deref-methods = "allow"
if-not-else = "allow"
inline-always = "allow"
match-bool = "allow"
missing-errors-doc = "allow"
missing-safety-doc = "allow"
module-name-repetitions = "allow"
partialeq-ne-impl = "allow"
similar-names = "allow"
single-match-else = "allow"
use-self = "allow"
wildcard-imports = "allow"
[lints.clippy.all]
level = "warn"
priority = -2
[lints.clippy.correctness]
level = "deny"
priority = -1
[lints.clippy.pedantic]
level = "warn"
priority = -2
[lints.rustdoc]
redundant-explicit-links = "allow"
archery/src/ 0000775 0001750 0001750 00000000000 14717116335 013766 5 ustar jamespage jamespage archery/src/shared_pointer/ 0000775 0001750 0001750 00000000000 14717116335 016774 5 ustar jamespage jamespage archery/src/shared_pointer/kind/ 0000775 0001750 0001750 00000000000 14717116335 017721 5 ustar jamespage jamespage archery/src/shared_pointer/kind/arct/ 0000775 0001750 0001750 00000000000 14717116335 020652 5 ustar jamespage jamespage archery/src/shared_pointer/kind/arct/test.rs 0000644 0001750 0001750 00000010564 14717116335 022203 0 ustar jamespage jamespage /* 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/.
*/
use super::*;
use pretty_assertions::assert_eq;
use static_assertions::assert_impl_all;
use std::cell::Cell;
use std::string::ToString;
type PointerKind = ArcTK;
assert_impl_all!(ArcTK: Send, Sync);
#[test]
fn test_from_box_t() {
let mut ptr = PointerKind::from_box(Box::new(42));
unsafe {
assert_eq!(ptr.deref::(), &42);
ptr.drop::();
}
}
#[test]
fn test_as_ptr() {
let mut x = PointerKind::new::<&'static str>("hello");
unsafe {
let mut y = PointerKind::clone::<&'static str>(&x);
let x_ptr: *const &'static str = PointerKind::as_ptr(&x);
assert_eq!(x_ptr, PointerKind::as_ptr(&y));
assert_eq!(*x_ptr, "hello");
x.drop::<&'static str>();
y.drop::<&'static str>();
}
}
#[test]
fn test_deref() {
let mut ptr_42 = PointerKind::new::(42);
let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello"));
unsafe {
assert_eq!(ptr_42.deref::(), &42);
assert_eq!(ptr_box_dyn_hello.deref::>().to_string(), "hello");
ptr_42.drop::();
ptr_box_dyn_hello.drop::>();
}
}
#[test]
fn test_try_unwrap() {
let ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.try_unwrap::().unwrap(), 42);
}
let ptr = PointerKind::new::(42);
unsafe {
let ptr_clone = ptr.clone::();
let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err();
let mut ptr = ptr.try_unwrap::().unwrap_err();
assert_eq!(ptr.deref::(), &42);
assert_eq!(ptr_clone.deref::(), &42);
ptr.drop::();
ptr_clone.drop::();
}
}
#[test]
fn test_get_mut() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.deref::(), &42);
*ptr.get_mut::().unwrap() += 1;
assert_eq!(ptr.deref::(), &43);
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr.get_mut::(), None);
assert_eq!(ptr_clone.get_mut::(), None);
ptr.drop::();
*ptr_clone.get_mut::().unwrap() += 1;
assert_eq!(ptr_clone.deref::(), &44);
ptr_clone.drop::();
}
}
#[test]
fn test_make_mut() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.deref::(), &42);
*ptr.make_mut::() += 1;
assert_eq!(ptr.deref::(), &43);
// Clone to force make_mut to clone the data.
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr_clone.deref::(), &43);
*ptr_clone.make_mut::() += 1;
assert_eq!(ptr.deref::(), &43);
assert_eq!(ptr_clone.deref::(), &44);
*ptr.make_mut::() *= 2;
assert_eq!(ptr.deref::(), &(2 * 43));
assert_eq!(ptr_clone.deref::(), &44);
ptr.drop::();
assert_eq!(ptr_clone.deref::(), &44);
ptr_clone.drop::();
}
}
#[test]
fn test_strong_count() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.strong_count::(), 1);
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr.strong_count::(), 2);
assert_eq!(ptr_clone.strong_count::(), 2);
ptr.drop::();
assert_eq!(ptr_clone.strong_count::(), 1);
ptr_clone.drop::();
}
}
#[test]
fn test_clone() {
let mut ptr = PointerKind::new::>(Cell::new(42));
unsafe {
let mut ptr_clone = ptr.clone::>();
assert_eq!(ptr.deref::>().get(), 42);
assert_eq!(ptr_clone.deref::>().get(), 42);
ptr_clone.deref::>().set(3);
assert_eq!(ptr.deref::>().get(), 3);
assert_eq!(ptr_clone.deref::>().get(), 3);
ptr.drop::>();
assert_eq!(ptr_clone.deref::>().get(), 3);
ptr_clone.drop::>();
}
}
#[test]
fn test_debug() {
let mut ptr = PointerKind::new::(42);
assert_eq!(format!("{:?}", ptr), "ArcTK");
unsafe {
ptr.drop::();
}
}
archery/src/shared_pointer/kind/arct/mod.rs 0000644 0001750 0001750 00000006724 14717116335 022006 0 ustar jamespage jamespage /* 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/.
*/
use crate::shared_pointer::kind::SharedPointerKind;
use alloc::boxed::Box;
use core::fmt;
use core::fmt::Debug;
use core::fmt::Formatter;
use core::mem;
use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::ops::DerefMut;
use core::ptr;
use triomphe::Arc;
type UntypedArc = Arc<()>;
/// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for
/// [`triomphe::Arc`](triomphe::Arc) pointers.
pub struct ArcTK {
/// We use [`ManuallyDrop`] here, so that we can drop it explicitly as
/// [`Arc`](triomphe::Arc). Not sure if it can be dropped as [`UntypedArc`], but it
/// seems to be playing with fire (even more than we already are).
inner: ManuallyDrop,
}
impl ArcTK {
#[inline(always)]
fn new_from_inner(arc: Arc) -> ArcTK {
ArcTK { inner: ManuallyDrop::new(unsafe { mem::transmute::, UntypedArc>(arc) }) }
}
#[inline(always)]
unsafe fn take_inner(self) -> Arc {
let arc: UntypedArc = ManuallyDrop::into_inner(self.inner);
mem::transmute(arc)
}
#[inline(always)]
unsafe fn as_inner_ref(&self) -> &Arc {
let arc_t: *const Arc = (self.inner.deref() as *const UntypedArc).cast::>();
// Static check to make sure we are not messing up the sizes.
// This could happen if we allowed for `T` to be unsized, because it would need to be
// represented as a wide pointer inside `Arc`.
// TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21
// gets fixed
let _ = mem::transmute::>;
&*arc_t
}
#[inline(always)]
unsafe fn as_inner_mut(&mut self) -> &mut Arc {
let arc_t: *mut Arc = (self.inner.deref_mut() as *mut UntypedArc).cast::>();
&mut *arc_t
}
}
unsafe impl SharedPointerKind for ArcTK {
#[inline(always)]
fn new(v: T) -> ArcTK {
ArcTK::new_from_inner(Arc::new(v))
}
#[inline(always)]
fn from_box(v: Box) -> ArcTK {
ArcTK::new_from_inner::(Arc::from(v))
}
#[inline(always)]
unsafe fn as_ptr(&self) -> *const T {
Arc::as_ptr(self.as_inner_ref())
}
#[inline(always)]
unsafe fn deref(&self) -> &T {
self.as_inner_ref::().as_ref()
}
#[inline(always)]
unsafe fn try_unwrap(self) -> Result {
Arc::try_unwrap(self.take_inner()).map_err(ArcTK::new_from_inner)
}
#[inline(always)]
unsafe fn get_mut(&mut self) -> Option<&mut T> {
Arc::get_mut(self.as_inner_mut())
}
#[inline(always)]
unsafe fn make_mut(&mut self) -> &mut T {
Arc::make_mut(self.as_inner_mut())
}
#[inline(always)]
unsafe fn strong_count(&self) -> usize {
Arc::count(self.as_inner_ref::())
}
#[inline(always)]
unsafe fn clone(&self) -> ArcTK {
ArcTK { inner: ManuallyDrop::new(Arc::clone(self.as_inner_ref())) }
}
#[inline(always)]
unsafe fn drop(&mut self) {
ptr::drop_in_place::>(self.as_inner_mut());
}
}
impl Debug for ArcTK {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str("ArcTK")
}
}
#[cfg(test)]
mod test;
archery/src/shared_pointer/kind/rc/ 0000775 0001750 0001750 00000000000 14717116335 020325 5 ustar jamespage jamespage archery/src/shared_pointer/kind/rc/test.rs 0000644 0001750 0001750 00000010552 14717116335 021653 0 ustar jamespage jamespage /* 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/.
*/
use super::*;
use std::cell::Cell;
use std::string::ToString;
type PointerKind = RcK;
#[test]
fn test_from_box_t() {
let mut ptr = PointerKind::from_box(Box::new(42));
unsafe {
assert_eq!(ptr.deref::(), &42);
ptr.drop::();
}
}
#[test]
fn test_as_ptr() {
let mut x = PointerKind::new::<&'static str>("hello from test_as_ptr");
unsafe {
let mut y = PointerKind::clone::<&'static str>(&x);
let x_ptr: *const &'static str = PointerKind::as_ptr(&x);
assert_eq!(x_ptr, PointerKind::as_ptr(&y));
assert_eq!(*x_ptr, "hello from test_as_ptr");
x.drop::<&'static str>();
y.drop::<&'static str>();
}
}
#[test]
fn test_deref() {
let mut ptr_42 = PointerKind::new::(42);
let mut ptr_box_dyn_hello =
PointerKind::new::>(Box::new("hello from test_deref"));
unsafe {
assert_eq!(ptr_42.deref::(), &42);
assert_eq!(
ptr_box_dyn_hello.deref::>().to_string(),
"hello from test_deref"
);
ptr_42.drop::();
ptr_box_dyn_hello.drop::>();
}
}
#[test]
fn test_try_unwrap() {
let ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.try_unwrap::().unwrap(), 42);
}
let ptr = PointerKind::new::(42);
unsafe {
let ptr_clone = ptr.clone::();
let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err();
let mut ptr = ptr.try_unwrap::().unwrap_err();
assert_eq!(ptr.deref::(), &42);
assert_eq!(ptr_clone.deref::(), &42);
ptr.drop::();
ptr_clone.drop::();
}
}
#[test]
fn test_get_mut() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.deref::(), &42);
*ptr.get_mut::().unwrap() += 1;
assert_eq!(ptr.deref::(), &43);
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr.get_mut::(), None);
assert_eq!(ptr_clone.get_mut::(), None);
ptr.drop::();
*ptr_clone.get_mut::().unwrap() += 1;
assert_eq!(ptr_clone.deref::(), &44);
ptr_clone.drop::();
}
}
#[test]
fn test_make_mut() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.deref::(), &42);
*ptr.make_mut::() += 1;
assert_eq!(ptr.deref::(), &43);
// Clone to force make_mut to clone the data.
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr_clone.deref::(), &43);
*ptr_clone.make_mut::() += 1;
assert_eq!(ptr.deref::(), &43);
assert_eq!(ptr_clone.deref::(), &44);
*ptr.make_mut::() *= 2;
assert_eq!(ptr.deref::(), &(2 * 43));
assert_eq!(ptr_clone.deref::(), &44);
ptr.drop::();
assert_eq!(ptr_clone.deref::(), &44);
ptr_clone.drop::();
}
}
#[test]
fn test_strong_count() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.strong_count::(), 1);
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr.strong_count::(), 2);
assert_eq!(ptr_clone.strong_count::(), 2);
ptr.drop::();
assert_eq!(ptr_clone.strong_count::(), 1);
ptr_clone.drop::();
}
}
#[test]
fn test_clone() {
let mut ptr = PointerKind::new::>(Cell::new(42));
unsafe {
let mut ptr_clone = ptr.clone::>();
assert_eq!(ptr.deref::>().get(), 42);
assert_eq!(ptr_clone.deref::>().get(), 42);
ptr_clone.deref::>().set(3);
assert_eq!(ptr.deref::>().get(), 3);
assert_eq!(ptr_clone.deref::>().get(), 3);
ptr.drop::>();
assert_eq!(ptr_clone.deref::>().get(), 3);
ptr_clone.drop::>();
}
}
#[test]
fn test_debug() {
let mut ptr = PointerKind::new::(42);
assert_eq!(format!("{ptr:?}"), "RcK");
unsafe {
ptr.drop::();
}
}
archery/src/shared_pointer/kind/rc/mod.rs 0000644 0001750 0001750 00000006652 14717116335 021461 0 ustar jamespage jamespage /* 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/.
*/
use crate::shared_pointer::kind::SharedPointerKind;
use alloc::boxed::Box;
use alloc::rc::Rc;
use core::fmt;
use core::fmt::Debug;
use core::fmt::Formatter;
use core::mem;
use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::ops::DerefMut;
use core::ptr;
type UntypedRc = Rc<()>;
/// [Type constructors](https://en.wikipedia.org/wiki/Type_constructor) for
/// [`Rc`] pointers.
pub struct RcK {
/// We use [`ManuallyDrop`] here, so that we can drop it explicitly as [`Rc`](alloc::rc::Rc).
/// Not sure if it can be dropped as [`UntypedRc`], but it seems to be playing with fire (even
/// more than we already are).
inner: ManuallyDrop,
}
impl RcK {
#[inline(always)]
fn new_from_inner(rc: Rc) -> RcK {
RcK { inner: ManuallyDrop::new(unsafe { mem::transmute::, UntypedRc>(rc) }) }
}
#[inline(always)]
unsafe fn take_inner(self) -> Rc {
let rc: UntypedRc = ManuallyDrop::into_inner(self.inner);
mem::transmute(rc)
}
#[inline(always)]
unsafe fn as_inner_ref(&self) -> &Rc {
let rc_t: *const Rc =
(self.inner.deref() as *const UntypedRc).cast::>();
// Static check to make sure we are not messing up the sizes.
// This could happen if we allowed for `T` to be unsized, because it would need to be
// represented as a wide pointer inside `Rc`.
// TODO Use static_assertion when https://github.com/nvzqz/static-assertions-rs/issues/21
// gets fixed
let _ = mem::transmute::>;
&*rc_t
}
#[inline(always)]
unsafe fn as_inner_mut(&mut self) -> &mut Rc {
let rc_t: *mut Rc =
(self.inner.deref_mut() as *mut UntypedRc).cast::>();
&mut *rc_t
}
}
unsafe impl SharedPointerKind for RcK {
#[inline(always)]
fn new(v: T) -> RcK {
RcK::new_from_inner(Rc::new(v))
}
#[inline(always)]
fn from_box(v: Box) -> RcK {
RcK::new_from_inner::(Rc::from(v))
}
#[inline(always)]
unsafe fn as_ptr(&self) -> *const T {
Rc::as_ptr(self.as_inner_ref())
}
#[inline(always)]
unsafe fn deref(&self) -> &T {
self.as_inner_ref::().as_ref()
}
#[inline(always)]
unsafe fn try_unwrap(self) -> Result {
Rc::try_unwrap(self.take_inner()).map_err(RcK::new_from_inner)
}
#[inline(always)]
unsafe fn get_mut(&mut self) -> Option<&mut T> {
Rc::get_mut(self.as_inner_mut())
}
#[inline(always)]
unsafe fn make_mut(&mut self) -> &mut T {
Rc::make_mut(self.as_inner_mut())
}
#[inline(always)]
unsafe fn strong_count(&self) -> usize {
Rc::strong_count(self.as_inner_ref::())
}
#[inline(always)]
unsafe fn clone(&self) -> RcK {
RcK { inner: ManuallyDrop::new(Rc::clone(self.as_inner_ref())) }
}
#[inline(always)]
unsafe fn drop(&mut self) {
ptr::drop_in_place::>(self.as_inner_mut());
}
}
impl Debug for RcK {
#[inline(always)]
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str("RcK")
}
}
#[cfg(test)]
mod test;
archery/src/shared_pointer/kind/arc/ 0000775 0001750 0001750 00000000000 14717116335 020466 5 ustar jamespage jamespage archery/src/shared_pointer/kind/arc/test.rs 0000644 0001750 0001750 00000010561 14717116335 022014 0 ustar jamespage jamespage /* 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/.
*/
use super::*;
use pretty_assertions::assert_eq;
use static_assertions::assert_impl_all;
use std::cell::Cell;
use std::string::ToString;
type PointerKind = ArcK;
assert_impl_all!(ArcK: Send, Sync);
#[test]
fn test_from_box_t() {
let mut ptr = PointerKind::from_box(Box::new(42));
unsafe {
assert_eq!(ptr.deref::(), &42);
ptr.drop::();
}
}
#[test]
fn test_as_ptr() {
let mut x = PointerKind::new::<&'static str>("hello");
unsafe {
let mut y = PointerKind::clone::<&'static str>(&x);
let x_ptr: *const &'static str = PointerKind::as_ptr(&x);
assert_eq!(x_ptr, PointerKind::as_ptr(&y));
assert_eq!(*x_ptr, "hello");
x.drop::<&'static str>();
y.drop::<&'static str>();
}
}
#[test]
fn test_deref() {
let mut ptr_42 = PointerKind::new::(42);
let mut ptr_box_dyn_hello = PointerKind::new::>(Box::new("hello"));
unsafe {
assert_eq!(ptr_42.deref::(), &42);
assert_eq!(ptr_box_dyn_hello.deref::>().to_string(), "hello");
ptr_42.drop::();
ptr_box_dyn_hello.drop::>();
}
}
#[test]
fn test_try_unwrap() {
let ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.try_unwrap::().unwrap(), 42);
}
let ptr = PointerKind::new::(42);
unsafe {
let ptr_clone = ptr.clone::();
let mut ptr_clone = ptr_clone.try_unwrap::().unwrap_err();
let mut ptr = ptr.try_unwrap::().unwrap_err();
assert_eq!(ptr.deref::(), &42);
assert_eq!(ptr_clone.deref::(), &42);
ptr.drop::();
ptr_clone.drop::();
}
}
#[test]
fn test_get_mut() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.deref::(), &42);
*ptr.get_mut::().unwrap() += 1;
assert_eq!(ptr.deref::(), &43);
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr.get_mut::(), None);
assert_eq!(ptr_clone.get_mut::(), None);
ptr.drop::();
*ptr_clone.get_mut::().unwrap() += 1;
assert_eq!(ptr_clone.deref::(), &44);
ptr_clone.drop::();
}
}
#[test]
fn test_make_mut() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.deref::(), &42);
*ptr.make_mut::() += 1;
assert_eq!(ptr.deref::(), &43);
// Clone to force make_mut to clone the data.
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr_clone.deref::(), &43);
*ptr_clone.make_mut::() += 1;
assert_eq!(ptr.deref::(), &43);
assert_eq!(ptr_clone.deref::(), &44);
*ptr.make_mut::() *= 2;
assert_eq!(ptr.deref::(), &(2 * 43));
assert_eq!(ptr_clone.deref::(), &44);
ptr.drop::();
assert_eq!(ptr_clone.deref::(), &44);
ptr_clone.drop::();
}
}
#[test]
fn test_strong_count() {
let mut ptr = PointerKind::new::(42);
unsafe {
assert_eq!(ptr.strong_count::(), 1);
let mut ptr_clone = ptr.clone::();
assert_eq!(ptr.strong_count::(), 2);
assert_eq!(ptr_clone.strong_count::(), 2);
ptr.drop::();
assert_eq!(ptr_clone.strong_count::(), 1);
ptr_clone.drop::();
}
}
#[test]
fn test_clone() {
let mut ptr = PointerKind::new::>(Cell::new(42));
unsafe {
let mut ptr_clone = ptr.clone:: | | | | | | | | | | | | | | | | | | | | |