1
1
//! This file is a port of only the necessary features from <https://github.com/chris-morgan/anymap> version 1.0.0-beta.2 for use within rust-analyzer.
2
+ //!
2
3
//! Copyright © 2014–2022 Chris Morgan.
3
4
//! COPYING: <https://github.com/chris-morgan/anymap/blob/master/COPYING>
4
5
//! Note that the license is changed from Blue Oak Model 1.0.0 or MIT or Apache-2.0 to MIT OR Apache-2.0
20
21
21
22
use core:: hash:: Hasher ;
22
23
23
- /// A hasher designed to eke a little more speed out, given `TypeId`’ s known characteristics.
24
+ /// A hasher designed to eke a little more speed out, given `TypeId`' s known characteristics.
24
25
///
25
- /// Specifically, this is a no-op hasher that expects to be fed a u64’ s worth of
26
+ /// Specifically, this is a no-op hasher that expects to be fed a u64' s worth of
26
27
/// randomly-distributed bits. It works well for `TypeId` (eliminating start-up time, so that my
27
- /// get_missing benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so
28
- /// that my insert_and_get_on_260_types benchmark is ~12μs instead of ~21.5μs), but will
28
+ /// ` get_missing` benchmark is ~30ns rather than ~900ns, and being a good deal faster after that, so
29
+ /// that my ` insert_and_get_on_260_types` benchmark is ~12μs instead of ~21.5μs), but will
29
30
/// panic in debug mode and always emit zeros in release mode for any other sorts of inputs, so
30
- /// yeah, don’ t use it! 😀
31
+ /// yeah, don' t use it! 😀
31
32
#[ derive( Default ) ]
32
33
pub struct TypeIdHasher {
33
34
value : u64 ,
@@ -36,9 +37,9 @@ pub struct TypeIdHasher {
36
37
impl Hasher for TypeIdHasher {
37
38
#[ inline]
38
39
fn write ( & mut self , bytes : & [ u8 ] ) {
39
- // This expects to receive exactly one 64-bit value, and there’ s no realistic chance of
40
- // that changing, but I don’ t want to depend on something that isn’ t expressly part of the
41
- // contract for safety. But I’ m OK with release builds putting everything in one bucket
40
+ // This expects to receive exactly one 64-bit value, and there' s no realistic chance of
41
+ // that changing, but I don' t want to depend on something that isn' t expressly part of the
42
+ // contract for safety. But I' m OK with release builds putting everything in one bucket
42
43
// if it *did* change (and debug builds panicking).
43
44
debug_assert_eq ! ( bytes. len( ) , 8 ) ;
44
45
let _ = bytes. try_into ( ) . map ( |array| self . value = u64:: from_ne_bytes ( array) ) ;
@@ -59,7 +60,7 @@ use ::std::collections::hash_map;
59
60
/// Raw access to the underlying `HashMap`.
60
61
///
61
62
/// This alias is provided for convenience because of the ugly third generic parameter.
62
- #[ allow ( clippy:: disallowed_types) ] // Uses a custom hasher
63
+ #[ expect ( clippy:: disallowed_types, reason = " Uses a custom hasher" ) ]
63
64
pub type RawMap < A > = hash_map:: HashMap < TypeId , Box < A > , BuildHasherDefault < TypeIdHasher > > ;
64
65
65
66
/// A collection containing zero or one values for any given type and allowing convenient,
@@ -73,19 +74,20 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId
73
74
///
74
75
/// Cumulatively, there are thus six forms of map:
75
76
///
76
- /// - <code> [Map]< dyn [core::any::Any]></code> ,
77
+ /// - ` [Map]< dyn [core::any::Any]>` ,
77
78
/// also spelled [`AnyMap`] for convenience.
78
- /// - <code> [Map]< dyn [core::any::Any] + Send></code>
79
- /// - <code> [Map]< dyn [core::any::Any] + Send + Sync></code>
79
+ /// - ` [Map]< dyn [core::any::Any] + Send>`
80
+ /// - ` [Map]< dyn [core::any::Any] + Send + Sync>`
80
81
///
81
82
/// ## Example
82
83
///
83
- /// (Here using the [`AnyMap`] convenience alias; the first line could use
84
- /// <code>[anymap::Map][Map]::<[core::any::Any]>::new()</code> instead if desired.)
84
+ /// (Here, the [`AnyMap`] convenience alias is used;
85
+ /// the first line could use `[anymap::Map][Map]::<[core::any::Any]>::new()`
86
+ /// instead if desired.)
85
87
///
86
88
/// ```
87
89
/// # use stdx::anymap;
88
- # [ doc = " let mut data = anymap::AnyMap::new();" ]
90
+ /// let mut data = anymap::AnyMap::new();
89
91
/// assert_eq!(data.get(), None::<&i32>);
90
92
/// ```
91
93
///
@@ -95,29 +97,31 @@ pub struct Map<A: ?Sized + Downcast = dyn Any> {
95
97
raw : RawMap < A > ,
96
98
}
97
99
98
- /// The most common type of `Map`: just using `Any`; <code> [Map]< dyn [Any]></code> .
100
+ /// The most common type of `Map`: just using `Any`; ` [Map]< dyn [Any]>` .
99
101
///
100
102
/// Why is this a separate type alias rather than a default value for `Map<A>`?
101
- /// `Map::new()` doesn’ t seem to be happy to infer that it should go with the default
102
- /// value. It’ s a bit sad, really. Ah well, I guess this approach will do.
103
+ /// `Map::new()` doesn' t seem to be happy to infer that it should go with the default
104
+ /// value. It' s a bit sad, really. Ah well, I guess this approach will do.
103
105
pub type AnyMap = Map < dyn Any > ;
104
106
impl < A : ?Sized + Downcast > Default for Map < A > {
105
107
#[ inline]
106
- fn default ( ) -> Map < A > {
107
- Map :: new ( )
108
+ fn default ( ) -> Self {
109
+ Self :: new ( )
108
110
}
109
111
}
110
112
111
113
impl < A : ?Sized + Downcast > Map < A > {
112
114
/// Create an empty collection.
113
115
#[ inline]
114
- pub fn new ( ) -> Map < A > {
115
- Map { raw : RawMap :: with_hasher ( Default :: default ( ) ) }
116
+ #[ must_use]
117
+ pub fn new ( ) -> Self {
118
+ Self { raw : RawMap :: with_hasher ( BuildHasherDefault :: default ( ) ) }
116
119
}
117
120
118
121
/// Returns a reference to the value stored in the collection for the type `T`,
119
122
/// if it exists.
120
123
#[ inline]
124
+ #[ must_use]
121
125
pub fn get < T : IntoBox < A > > ( & self ) -> Option < & T > {
122
126
self . raw . get ( & TypeId :: of :: < T > ( ) ) . map ( |any| unsafe { any. downcast_ref_unchecked :: < T > ( ) } )
123
127
}
@@ -137,51 +141,52 @@ impl<A: ?Sized + Downcast> Map<A> {
137
141
}
138
142
139
143
/// A view into a single occupied location in an `Map`.
140
- pub struct OccupiedEntry < ' a , A : ?Sized + Downcast , V : ' a > {
141
- inner : hash_map:: OccupiedEntry < ' a , TypeId , Box < A > > ,
144
+ pub struct OccupiedEntry < ' map , A : ?Sized + Downcast , V : ' map > {
145
+ inner : hash_map:: OccupiedEntry < ' map , TypeId , Box < A > > ,
142
146
type_ : PhantomData < V > ,
143
147
}
144
148
145
149
/// A view into a single empty location in an `Map`.
146
- pub struct VacantEntry < ' a , A : ?Sized + Downcast , V : ' a > {
147
- inner : hash_map:: VacantEntry < ' a , TypeId , Box < A > > ,
150
+ pub struct VacantEntry < ' map , A : ?Sized + Downcast , V : ' map > {
151
+ inner : hash_map:: VacantEntry < ' map , TypeId , Box < A > > ,
148
152
type_ : PhantomData < V > ,
149
153
}
150
154
151
155
/// A view into a single location in an `Map`, which may be vacant or occupied.
152
- pub enum Entry < ' a , A : ?Sized + Downcast , V > {
156
+ pub enum Entry < ' map , A : ?Sized + Downcast , V > {
153
157
/// An occupied Entry
154
- Occupied ( OccupiedEntry < ' a , A , V > ) ,
158
+ Occupied ( OccupiedEntry < ' map , A , V > ) ,
155
159
/// A vacant Entry
156
- Vacant ( VacantEntry < ' a , A , V > ) ,
160
+ Vacant ( VacantEntry < ' map , A , V > ) ,
157
161
}
158
162
159
- impl < ' a , A : ?Sized + Downcast , V : IntoBox < A > > Entry < ' a , A , V > {
163
+ impl < ' map , A : ?Sized + Downcast , V : IntoBox < A > > Entry < ' map , A , V > {
160
164
/// Ensures a value is in the entry by inserting the result of the default function if
161
165
/// empty, and returns a mutable reference to the value in the entry.
162
166
#[ inline]
163
- pub fn or_insert_with < F : FnOnce ( ) -> V > ( self , default : F ) -> & ' a mut V {
167
+ pub fn or_insert_with < F : FnOnce ( ) -> V > ( self , default : F ) -> & ' map mut V {
164
168
match self {
165
169
Entry :: Occupied ( inner) => inner. into_mut ( ) ,
166
170
Entry :: Vacant ( inner) => inner. insert ( default ( ) ) ,
167
171
}
168
172
}
169
173
}
170
174
171
- impl < ' a , A : ?Sized + Downcast , V : IntoBox < A > > OccupiedEntry < ' a , A , V > {
172
- /// Converts the OccupiedEntry into a mutable reference to the value in the entry
175
+ impl < ' map , A : ?Sized + Downcast , V : IntoBox < A > > OccupiedEntry < ' map , A , V > {
176
+ /// Converts the ` OccupiedEntry` into a mutable reference to the value in the entry
173
177
/// with a lifetime bound to the collection itself
174
178
#[ inline]
175
- pub fn into_mut ( self ) -> & ' a mut V {
179
+ #[ must_use]
180
+ pub fn into_mut ( self ) -> & ' map mut V {
176
181
unsafe { self . inner . into_mut ( ) . downcast_mut_unchecked ( ) }
177
182
}
178
183
}
179
184
180
- impl < ' a , A : ?Sized + Downcast , V : IntoBox < A > > VacantEntry < ' a , A , V > {
181
- /// Sets the value of the entry with the VacantEntry's key,
185
+ impl < ' map , A : ?Sized + Downcast , V : IntoBox < A > > VacantEntry < ' map , A , V > {
186
+ /// Sets the value of the entry with the ` VacantEntry` 's key,
182
187
/// and returns a mutable reference to it
183
188
#[ inline]
184
- pub fn insert ( self , value : V ) -> & ' a mut V {
189
+ pub fn insert ( self , value : V ) -> & ' map mut V {
185
190
unsafe { self . inner . insert ( value. into_box ( ) ) . downcast_mut_unchecked ( ) }
186
191
}
187
192
}
@@ -206,14 +211,13 @@ mod tests {
206
211
#[ test]
207
212
fn type_id_hasher ( ) {
208
213
use core:: any:: TypeId ;
209
- use core:: hash:: Hash ;
214
+ use core:: hash:: Hash as _ ;
210
215
fn verify_hashing_with ( type_id : TypeId ) {
211
216
let mut hasher = TypeIdHasher :: default ( ) ;
212
217
type_id. hash ( & mut hasher) ;
213
- // SAFETY: u64 is valid for all bit patterns.
214
- let _ = hasher. finish ( ) ;
218
+ _ = hasher. finish ( ) ;
215
219
}
216
- // Pick a variety of types, just to demonstrate it’ s all sane. Normal, zero-sized, unsized, &c.
220
+ // Pick a variety of types, just to demonstrate it' s all sane. Normal, zero-sized, unsized, &c.
217
221
verify_hashing_with ( TypeId :: of :: < usize > ( ) ) ;
218
222
verify_hashing_with ( TypeId :: of :: < ( ) > ( ) ) ;
219
223
verify_hashing_with ( TypeId :: of :: < str > ( ) ) ;
@@ -225,34 +229,34 @@ mod tests {
225
229
/// Methods for downcasting from an `Any`-like trait object.
226
230
///
227
231
/// This should only be implemented on trait objects for subtraits of `Any`, though you can
228
- /// implement it for other types and it’ll work fine, so long as your implementation is correct.
232
+ /// implement it for other types and it will work fine, so long as your implementation is correct.
229
233
pub trait Downcast {
230
234
/// Gets the `TypeId` of `self`.
231
235
fn type_id ( & self ) -> TypeId ;
232
236
233
237
// Note the bound through these downcast methods is 'static, rather than the inexpressible
234
238
// concept of Self-but-as-a-trait (where Self is `dyn Trait`). This is sufficient, exceeding
235
- // TypeId’ s requirements. Sure, you *can* do CloneAny.downcast_unchecked::<NotClone>() and the
236
- // type system won’ t protect you, but that doesn’ t introduce any unsafety: the method is
239
+ // TypeId' s requirements. Sure, you *can* do CloneAny.downcast_unchecked::<NotClone>() and the
240
+ // type system won' t protect you, but that doesn' t introduce any unsafety: the method is
237
241
// already unsafe because you can specify the wrong type, and if this were exposing safe
238
242
// downcasting, CloneAny.downcast::<NotClone>() would just return an error, which is just as
239
243
// correct.
240
244
//
241
- // Now in theory we could also add T: ?Sized, but that doesn’ t play nicely with the common
242
- // implementation, so I’ m doing without it.
245
+ // Now in theory we could also add T: ?Sized, but that doesn' t play nicely with the common
246
+ // implementation, so I' m doing without it.
243
247
244
248
/// Downcast from `&Any` to `&T`, without checking the type matches.
245
249
///
246
250
/// # Safety
247
251
///
248
- /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour *.
252
+ /// The caller must ensure that `T` matches the trait object, on pain of *undefined behavior *.
249
253
unsafe fn downcast_ref_unchecked < T : ' static > ( & self ) -> & T ;
250
254
251
255
/// Downcast from `&mut Any` to `&mut T`, without checking the type matches.
252
256
///
253
257
/// # Safety
254
258
///
255
- /// The caller must ensure that `T` matches the trait object, on pain of *undefined behaviour *.
259
+ /// The caller must ensure that `T` matches the trait object, on pain of *undefined behavior *.
256
260
unsafe fn downcast_mut_unchecked < T : ' static > ( & mut self ) -> & mut T ;
257
261
}
258
262
@@ -272,12 +276,12 @@ macro_rules! implement {
272
276
273
277
#[ inline]
274
278
unsafe fn downcast_ref_unchecked<T : ' static >( & self ) -> & T {
275
- unsafe { & * ( self as * const Self as * const T ) }
279
+ unsafe { & * std :: ptr :: from_ref :: < Self > ( self ) . cast :: < T > ( ) }
276
280
}
277
281
278
282
#[ inline]
279
283
unsafe fn downcast_mut_unchecked<T : ' static >( & mut self ) -> & mut T {
280
- unsafe { & mut * ( self as * mut Self as * mut T ) }
284
+ unsafe { & mut * std :: ptr :: from_mut :: < Self > ( self ) . cast :: < T > ( ) }
281
285
}
282
286
}
283
287
0 commit comments