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
use core::marker::PhantomData;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
static MASTER_KEY_EXISTS: AtomicBool = AtomicBool::new(false);
pub mod bidirected;
pub mod directed;
pub mod undirected;
/// The master key.
/// Only one instance of this type can exist at any time.
///
/// A master key can be used to derive a [DataKey] or a [ChannelKey],
/// but only at most one derived key can exist simultaneously,
/// and specifically not both a data key and a channel key at the same time.
pub struct MasterKey {
/// For debug purposes, multiple master keys can be created.
/// To prevent them from interfering with the "real" master key, we mark them as "unlimited".
unlimited: bool,
}
impl MasterKey {
/// Creates a new master key.
/// If there already is an existing master key, this function **panics**.
pub fn create() -> Self {
// Assert that the master key does not exist
// and set it as existing.
// Using `Ordering::Relaxed` is fine here, since if the result is `true`,
// we anyways panic, and if the result is `false`, nothing happens.
assert!(!MASTER_KEY_EXISTS.swap(true, Ordering::Relaxed));
// Return a new master key.
Self { unlimited: false }
}
/// Creates a new master key without checking if there already is one.
///
/// # Safety
///
/// This violates the "only one master key" constraint imposed by this crate and
/// thus may lead to undefined behavior when a channel is accessed by its
/// channel key and some data key at the same time.
///
/// Use this only for testing and debugging purposes.
pub unsafe fn create_unlimited() -> Self {
Self { unlimited: true }
}
/// Get a unique data key from this master key.
/// The data key mutably borrows from the master key, hence there can be no other keys at the same time.
pub fn get_data_key(&mut self) -> DataKey<'_> {
DataKey {
scope: Default::default(),
}
}
/// Get a unique channel key from this master key.
/// The channel key mutably borrows from the master key, hence there can be no other keys at the same time.
pub fn get_channel_key(&mut self) -> ChannelKey<'_> {
ChannelKey {
scope: Default::default(),
}
}
}
impl Drop for MasterKey {
/// After dropping a master key, a new one can be created again.
fn drop(&mut self) {
if !self.unlimited {
// Assert that the master key exists
// and set it as not existing.
// Using `Ordering::Relaxed` is fine here, since if the result is `true`,
// we anyways panic, and if the result is `false`, nothing happens.
assert!(MASTER_KEY_EXISTS.swap(false, Ordering::Relaxed));
}
}
}
/// The key used for accessing a data pointer, such as a [`ReadOnlyDataPointer`](directed::ReadOnlyDataPointer), a [`WritableDataPointer`](directed::WritableDataPointer), or a [`DataPointer`](undirected::UndirectedDataPointer).
/// Only one can simultaneously exist at any point, and only if there is no channel key.
pub struct DataKey<'master_key> {
scope: PhantomData<&'master_key mut MasterKey>,
}
/// The key used for accessing a channel pointer, such as a [`DirectedChannelPointer`](directed::DirectedChannelPointer) or an [`UndirectedChannelPointer`](undirected::UndirectedChannelPointer).
/// Only one can simultaneously exist at any point, and only if there is no data key.
pub struct ChannelKey<'master_key> {
scope: PhantomData<&'master_key mut MasterKey>,
}
impl<'master_key> DataKey<'master_key> {
/// Convert this data key into a channel key.
/// This consumes the data key, ensuring that there is never both a channel key and a data key.
pub fn into_channel_key(self) -> ChannelKey<'master_key> {
ChannelKey { scope: self.scope }
}
}
impl<'master_key> ChannelKey<'master_key> {
/// Convert this channel key into a data key.
/// This consumes the channel key, ensuring that there is never both a channel key and a data key.
pub fn into_data_key(self) -> DataKey<'master_key> {
DataKey { scope: self.scope }
}
}