starnix_uapi/
arc_key.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use ref_cast::RefCast;
6use std::borrow::Borrow;
7use std::cmp::Ordering;
8use std::hash::{Hash, Hasher};
9use std::ops::Deref;
10use std::sync::{Arc, Weak};
11
12/// A wrapper around Arc with Hash implemented based on Arc::as_ptr.
13#[derive(RefCast)]
14#[repr(transparent)]
15pub struct ArcKey<T>(pub Arc<T>);
16impl<T> PartialEq for ArcKey<T> {
17    fn eq(&self, other: &Self) -> bool {
18        Arc::ptr_eq(&self.0, &other.0)
19    }
20}
21impl<T> Eq for ArcKey<T> {}
22impl<T> PartialOrd for ArcKey<T> {
23    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
24        Some(self.cmp(other))
25    }
26}
27impl<T> Ord for ArcKey<T> {
28    fn cmp(&self, other: &Self) -> Ordering {
29        Arc::as_ptr(&self.0).cmp(&Arc::as_ptr(&other.0))
30    }
31}
32impl<T> Hash for ArcKey<T> {
33    fn hash<H: Hasher>(&self, state: &mut H) {
34        Arc::as_ptr(&self.0).hash(state);
35    }
36}
37impl<T> Clone for ArcKey<T> {
38    fn clone(&self) -> Self {
39        Self(Arc::clone(&self.0))
40    }
41}
42impl<T> Deref for ArcKey<T> {
43    type Target = Arc<T>;
44    fn deref(&self) -> &Self::Target {
45        &self.0
46    }
47}
48
49impl<T: std::fmt::Debug> std::fmt::Debug for ArcKey<T> {
50    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51        self.0.fmt(f)
52    }
53}
54
55/// A wrapper around Weak with Hash implemented based on Weak::as_ptr.
56pub struct WeakKey<T>(pub Weak<T>, PtrKey<T>);
57impl<T> WeakKey<T> {
58    pub fn from(arc: &Arc<T>) -> Self {
59        Self(Arc::downgrade(arc), Arc::as_ptr(arc).into())
60    }
61}
62impl<T> Clone for WeakKey<T> {
63    fn clone(&self) -> Self {
64        Self(self.0.clone(), self.1.clone())
65    }
66}
67impl<T> PartialEq<Weak<T>> for WeakKey<T> {
68    fn eq(&self, other: &Weak<T>) -> bool {
69        Weak::ptr_eq(&self.0, other)
70    }
71}
72impl<T> PartialEq for WeakKey<T> {
73    fn eq(&self, other: &Self) -> bool {
74        *self == other.0
75    }
76}
77impl<T> Eq for WeakKey<T> {}
78impl<T> PartialOrd for WeakKey<T> {
79    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
80        Some(self.cmp(other))
81    }
82}
83impl<T> Ord for WeakKey<T> {
84    fn cmp(&self, other: &Self) -> Ordering {
85        Weak::as_ptr(&self.0).cmp(&Weak::as_ptr(&other.0))
86    }
87}
88impl<T> Hash for WeakKey<T> {
89    fn hash<H: Hasher>(&self, state: &mut H) {
90        Weak::as_ptr(&self.0).hash(state);
91    }
92}
93impl<T> Borrow<PtrKey<T>> for WeakKey<T> {
94    fn borrow(&self) -> &PtrKey<T> {
95        &self.1
96    }
97}
98
99impl<T: std::fmt::Debug> std::fmt::Debug for WeakKey<T> {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        self.0.fmt(f)
102    }
103}
104
105pub struct PtrKey<T>(*const T);
106impl<T> From<*const T> for PtrKey<T> {
107    fn from(ptr: *const T) -> Self {
108        Self(ptr)
109    }
110}
111impl<T> Clone for PtrKey<T> {
112    fn clone(&self) -> Self {
113        Self(self.0)
114    }
115}
116impl<T> PartialEq for PtrKey<T> {
117    fn eq(&self, other: &Self) -> bool {
118        self.0 == other.0
119    }
120}
121impl<T> Eq for PtrKey<T> {}
122impl<T> Hash for PtrKey<T> {
123    fn hash<H: Hasher>(&self, state: &mut H) {
124        self.0.hash(state)
125    }
126}
127#[allow(clippy::undocumented_unsafe_blocks, reason = "Force documented unsafe blocks in Starnix")]
128unsafe impl<T> Sync for PtrKey<T> {}
129#[allow(clippy::undocumented_unsafe_blocks, reason = "Force documented unsafe blocks in Starnix")]
130unsafe impl<T> Send for PtrKey<T> {}
131
132impl<T: std::fmt::Debug> std::fmt::Debug for PtrKey<T> {
133    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134        self.0.fmt(f)
135    }
136}