owned_singleton/lib.rs
1//! Owned singletons
2//!
3//! An owned singleton is a proxy (struct) that grants exclusive access to a `static mut` variable.
4//!
5//! # Features
6//!
7//! Owned singletons are smaller than `&'static mut` references; they are zero sized types.
8//!
9//! Doesn't sound useful enough to you? The `Singleton` abstraction can be used to implement
10//! [statically allocated memory pools whose handles are a single byte in size and are automatically
11//! deallocated on `drop`.][alloc-singleton]
12//!
13//! [alloc-singleton]: https://crates.io/crates/alloc-singleton
14//!
15//! # Examples
16//!
17//! The `Singleton` attribute creates a proxy (`struct`) for the given `static mut` variable and
18//! implements the `Singleton`, `Deref`, `DerefMut` and `StableDeref`s traits for it.
19//!
20//! ```
21//! use owned_singleton::Singleton;
22//!
23//! #[Singleton]
24//! static mut FOO: u32 = 0;
25//!
26//! let mut foo = unsafe { FOO::new() };
27//! assert_eq!(*foo, 0);
28//! *foo += 1;
29//! assert_eq!(*foo, 1);
30//!
31//! let bar: &'static mut u32 = foo.unwrap();
32//! assert_eq!(*bar, 1);
33//! ```
34//!
35//! The `Singleton` attribute doesn't implement the `Send` or `Sync` traits by default; this results
36//! in a proxy struct that does *not* implement `Send` or `Sync`. To opt into the `Send` and `Sync`
37//! traits add the `Send` and `Sync` arguments to the `Singleton` attribute.
38//!
39//! ```
40//! use owned_singleton::Singleton;
41//!
42//! #[Singleton(Send, Sync)]
43//! static mut FOO: u32 = 0;
44//!
45//! fn is_send<T>() where T: Send {}
46//! fn is_sync<T>() where T: Sync {}
47//!
48//! is_send::<FOO>();
49//! is_sync::<FOO>();
50//! ```
51//!
52//! Using `Singleton` on a `static` variable results in `DerefMut` not being implemented for the
53//! proxy struct. However, the proxy struct will still be a handle to a `static mut` variable so
54//! there's *no* `Sync` requirement on the type of the `static mut` variable.
55//!
56//! ```
57//! use std::marker::PhantomData;
58//!
59//! use owned_singleton::Singleton;
60//!
61//! // `PhantomData<*const ()>` does not implement `Send` or `Sync`
62//! #[Singleton]
63//! static FOO: PhantomData<*const ()> = PhantomData;
64//! ```
65
66#![deny(missing_docs)]
67#![deny(warnings)]
68#![no_std]
69
70extern crate owned_singleton_macros;
71extern crate stable_deref_trait;
72
73pub use owned_singleton_macros::Singleton;
74use stable_deref_trait::StableDeref;
75
76#[doc(hidden)]
77pub mod export;
78
79/// An owned singleton: a proxy (handle) for a `static mut` variable
80pub unsafe trait Singleton: StableDeref {
81 /// The type of the `static mut` variable behind this proxy
82 type Type;
83
84 /// Creates a new singleton
85 ///
86 /// # Unsafety
87 ///
88 /// It's UB to create more than one instance of this singleton
89 unsafe fn new() -> Self;
90
91 /// Returns a pointer to the `static mut` variable behind this proxy
92 fn get() -> *mut Self::Type;
93
94 /// Consumes this singleton and returns a `&'static mut` reference to the variable behind it
95 fn unwrap(self) -> &'static mut Self::Type
96 where
97 Self: Sized,
98 {
99 unsafe { &mut *Self::get() }
100 }
101}