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}