swap_channel/
lib.rs

1use core::marker::PhantomData;
2use std::sync::atomic::AtomicBool;
3use std::sync::atomic::Ordering;
4
5static MASTER_KEY_EXISTS: AtomicBool = AtomicBool::new(false);
6
7pub mod directed;
8pub mod undirected;
9
10/// The master key.
11/// Only one instance of this type can exist at any time.
12///
13/// A master key can be used to derive a [DataKey] or a [ChannelKey],
14/// but only at most one derived key can exist simultaneously,
15/// and specifically not both a data key and a channel key at the same time.
16pub struct MasterKey {
17    /// For debug purposes, multiple master keys can be created.
18    /// To prevent them from interfering with the "real" master key, we mark them as "unlimited".
19    unlimited: bool,
20}
21
22impl MasterKey {
23    /// Creates a new master key.
24    /// If there already is an existing master key, this function **panics**.
25    pub fn create() -> Self {
26        // Assert that the master key does not exist
27        // and set it as existing.
28        // Using `Ordering::Relaxed` is fine here, since if the result is `true`,
29        // we anyways panic, and if the result is `false`, nothing happens.
30        assert!(!MASTER_KEY_EXISTS.swap(true, Ordering::Relaxed));
31
32        // Return a new master key.
33        Self { unlimited: false }
34    }
35
36    /// Creates a new master key without checking if there already is one.
37    ///
38    /// # Safety
39    ///
40    /// This violates the "only one master key" constraint imposed by this crate and
41    /// thus may lead to undefined behavior when a channel is accessed by its
42    /// channel key and some data key at the same time.
43    ///
44    /// Use this only for testing and debugging purposes.
45    pub unsafe fn create_unlimited() -> Self {
46        Self { unlimited: true }
47    }
48
49    /// Get a unique data key from this master key.
50    /// The data key mutably borrows from the master key, hence there can be no other keys at the same time.
51    pub fn get_data_key(&mut self) -> DataKey<'_> {
52        DataKey {
53            scope: Default::default(),
54        }
55    }
56
57    /// Get a unique channel key from this master key.
58    /// The channel key mutably borrows from the master key, hence there can be no other keys at the same time.
59    pub fn get_channel_key(&mut self) -> ChannelKey<'_> {
60        ChannelKey {
61            scope: Default::default(),
62        }
63    }
64}
65
66impl Drop for MasterKey {
67    /// After dropping a master key, a new one can be created again.
68    fn drop(&mut self) {
69        if !self.unlimited {
70            // Assert that the master key exists
71            // and set it as not existing.
72            // Using `Ordering::Relaxed` is fine here, since if the result is `true`,
73            // we anyways panic, and if the result is `false`, nothing happens.
74            assert!(MASTER_KEY_EXISTS.swap(false, Ordering::Relaxed));
75        }
76    }
77}
78
79/// The key used for accessing a data pointer, such as a [`ReadOnlyDataPointer`](directed::ReadOnlyDataPointer), a [`WriteOnlyDataPointer`](directed::WriteOnlyDataPointer), or a [`DataPointer`](undirected::UndirectedDataPointer).
80/// Only one can simultaneously exist at any point, and only if there is no channel key.
81pub struct DataKey<'master_key> {
82    scope: PhantomData<&'master_key mut MasterKey>,
83}
84
85/// The key used for accessing a channel pointer, such as a [`DirectedChannelPointer`](directed::DirectedChannelPointer) or an [`UndirectedChannelPointer`](undirected::UndirectedChannelPointer).
86/// Only one can simultaneously exist at any point, and only if there is no data key.
87pub struct ChannelKey<'master_key> {
88    scope: PhantomData<&'master_key mut MasterKey>,
89}
90
91impl<'master_key> DataKey<'master_key> {
92    /// Convert this data key into a channel key.
93    /// This consumes the data key, ensuring that there is never both a channel key and a data key.
94    pub fn into_channel_key(self) -> ChannelKey<'master_key> {
95        ChannelKey { scope: self.scope }
96    }
97}
98
99impl<'master_key> ChannelKey<'master_key> {
100    /// Convert this channel key into a data key.
101    /// This consumes the channel key, ensuring that there is never both a channel key and a data key.
102    pub fn into_data_key(self) -> DataKey<'master_key> {
103        DataKey { scope: self.scope }
104    }
105}