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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#![deny(missing_docs)]

//! Hashable wrappers for reference countings.

//!

//! Provides hashable wrappers for 

//! [`Rc<T>`](https://doc.rust-lang.org/std/rc/struct.Rc.html) and

//! [`Weak<T>`](https://doc.rust-lang.org/std/rc/struct.Weak.html) 

//! references with the types [`HashableRc<T>`](struct.HashableRc.html)

//! and [`HashableWeak<T>`](struct.HashableWeak.html), respectively. 

//! This allows use of both strong and weak reference countings in 

//! hash-based data structures, such as 

//! [`HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html)

//! or

//! [`HashSet`](https://doc.rust-lang.org/std/collections/struct.HashSet.html).

//!

//! # Quick Start

//!

//! The most common use cases are wrapping 

//! [`Rc<T>`](https://doc.rust-lang.org/std/rc/struct.Rc.html) or 

//! [`Weak<T>`](https://doc.rust-lang.org/std/rc/struct.Weak.html) in

//! [`HashableRc<T>`](struct.HashableRc.html) or 

//! [`HashableWeak<T>`](struct.HashableWeak.html) respectively to be

//! contained in a hash-based container. An example of using both types

//! as keys in a 

//! [`HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html)

//! follows.

//!

//! ```

//! use std::collections::HashMap;

//! use std::rc::{Rc, Weak};

//!

//! use hashable_rc::{HashableRc, HashableWeak};

//!

//! // Create a strong reference counting for an object.

//! let rc: Rc<u32> = Rc::new(42);

//!

//! // Use the strong reference as a key for a HashMap.

//! let mut strong_map = HashMap::new();

//! strong_map.insert(HashableRc::new(rc.clone()), "foo");

//! assert_eq!(strong_map[&HashableRc::new(rc.clone())], "foo");

//!

//! // Create a weak reference counting for the same object as above.

//! let weak: Weak<u32> = Rc::downgrade(&rc);

//!

//! // Use the weak reference as a key for a HashMap.

//! let mut weak_map = HashMap::new();

//! weak_map.insert(HashableWeak::new(weak.clone()), "bar");

//! assert_eq!(weak_map[&HashableWeak::new(weak.clone())], "bar");

//! ```

//!

//! Insertion into other hash-based containers (such as a 

//! [`HashSet`](https://doc.rust-lang.org/std/collections/struct.HashSet.html))

//! follows similarly.


use std::hash::{Hash, Hasher};
use std::rc::{Rc, Weak};

fn hash_rc<T, H: Hasher>(rc: Rc<T>, state: &mut H) {
    let raw_ptr = Rc::into_raw(rc);
    raw_ptr.hash(state);
    // Convert back to Rc to prevent memory leak.

    let _ = unsafe {Rc::from_raw(raw_ptr)};
}

/// A hashable wrapper around the 

/// [`Rc<T>`](https://doc.rust-lang.org/std/rc/struct.Rc.html) type.

///

/// A hash of a [`HashableRc<T>`](struct.HashableRc.html) is taken from

/// the underlying pointer. Therefore, two separate objects that may be

/// considered equal will, when contained in a

/// [`HashableRc<T>`](struct.HashableRc.html), almost always have 

/// different hashed values. For example, the following holds:

///

/// ```

/// use std::collections::hash_map::DefaultHasher;

/// use std::hash::{Hash, Hasher};

/// use std::rc::Rc;

///

/// use hashable_rc::HashableRc;

///

/// fn hash<H: Hash>(value: &H) -> u64 {

///     let mut state = DefaultHasher::new();

///     value.hash(&mut state);

///     state.finish()

/// }

///

/// // While the underlying values are considered equal, the hash values

/// // will be different, due to being separate allocated objects with 

/// // different underlying pointers.

/// let rc1 = Rc::new(42);

/// let rc2 = Rc::new(42);

/// 

/// // The hashes of the two reference countings are different.

/// assert_ne!(hash(&HashableRc::new(rc1.clone())), 

///            hash(&HashableRc::new(rc2.clone())));

///

/// // Contrastingly, the hashes of clone reference countings pointing to 

/// // the same object are the equal.

/// assert_eq!(hash(&HashableRc::new(rc1.clone())), 

///            hash(&HashableRc::new(rc1.clone())));

/// ```

///

/// Similarly, equality of [`HashableRc<T>`](struct.HashableRc.html)

/// objects is done by evaluating pointer equality (using 

/// [`ptr_eq()`](https://doc.rust-lang.org/std/rc/struct.Rc.html#method.ptr_eq)).

/// The equality is not from the value itself, but from the pointer.

///

/// ```

/// use std::rc::Rc;

///

/// use hashable_rc::HashableRc;

///

/// // Again, the values contained are equal, but the underlying pointers

/// // are different.

/// let rc1 = Rc::new(42);

/// let rc2 = Rc::new(42);

///

/// // Therefore, two HashableRc wrappers containing these reference 

/// // counters are not equal.

/// assert_ne!(HashableRc::new(rc1.clone()),

///            HashableRc::new(rc2.clone()));

///

/// // But HashableRc holding the same underlying object are equal.

/// assert_eq!(HashableRc::new(rc1.clone()),

///            HashableRc::new(rc1.clone()));

/// ```

#[derive(Debug, Eq)]
pub struct HashableRc<T> {
    value: Rc<T>,
}

impl <T> HashableRc<T> {
    /// Constructs a new [`HashableRc<T>`](struct.HashableRc.html) 

    /// wrapping an 

    /// [`Rc<T>`](https://doc.rust-lang.org/std/rc/struct.Rc.html).

    pub fn new(value: Rc<T>) -> Self {
        HashableRc {value}
    }

    /// Returns a clone of the wrapped `Rc<T>` without consuming `self`.

    pub fn get_cloned(&self) -> Rc<T> {
        self.value.clone()
    }
}

impl <T> Hash for HashableRc<T> {
    /// Generate a hash value for the 

    /// [`HashableRc<T>`](struct.HashableRc.html).

    ///

    /// This hash value is based on the underlying pointer. Two unique 

    /// objects will most likely have different hashes, even if their 

    /// values are the same.

    fn hash<H>(&self, state: &mut H) where H: Hasher {
        hash_rc(self.value.clone(), state);
    }
}

impl <T> PartialEq for HashableRc<T> {
    /// Equality for two [`HashableRc<T>`](struct.HashableRc.html) 

    /// objects.

    ///

    /// Equality is determined by pointer equality, rather than value 

    /// equality. Objects are only considered equal if they point to 

    /// the same object.

    fn eq(&self, other: &Self) -> bool {
        Rc::ptr_eq(&self.value, &other.value)
    }
}

/// A hashable wrapper around the 

/// [`Weak<T>`](https://doc.rust-lang.org/std/rc/struct.Weak.html)

/// type.

///

/// A hash of a [`HashableWeak<T>`](struct.HashableWeak.html) is taken

/// from the underlying pointer. Therefore, two separate objects that

/// may be considered equal will, when contained in a

/// [`HashableWeak<T>`](struct.HashableWeak.html), almost always have

/// different hashed values. For example, the following holds:

///

/// ```

/// use std::collections::hash_map::DefaultHasher;

/// use std::hash::{Hash, Hasher};

/// use std::rc::Rc;

///

/// use hashable_rc::HashableWeak;

///

/// fn hash<H: Hash>(value: &H) -> u64 {

///     let mut state = DefaultHasher::new();

///     value.hash(&mut state);

///     state.finish()

/// }

///

/// // While the underlying values are considered equal, the hash values

/// // will be different, due to being separate allocated objects with 

/// // different underlying pointers.

/// let rc1 = Rc::new(42);

/// let rc2 = Rc::new(42);

/// 

/// // The hashes of the two reference countings are different.

/// assert_ne!(hash(&HashableWeak::new(Rc::downgrade(&rc1))), 

///            hash(&HashableWeak::new(Rc::downgrade(&rc2))));

///

/// // Contrastingly, the hashes of clone reference countings pointing to 

/// // the same object are the equal.

/// assert_eq!(hash(&HashableWeak::new(Rc::downgrade(&rc1))), 

///            hash(&HashableWeak::new(Rc::downgrade(&rc1))));

/// ```

///

/// Similarly, equality of 

/// [`HashableWeak<T>`](struct.HashableWeak.html) objects is done by

/// evaluating pointer equality (using 

/// [`ptr_eq()`](https://doc.rust-lang.org/std/rc/struct.Weak.html#method.ptr_eq)).

/// The equality is not from the value itself, but from the pointer.

///

/// ```

/// use std::rc::Rc;

///

/// use hashable_rc::HashableWeak;

///

/// // Again, the values contained are equal, but the underlying pointers

/// // are different.

/// let rc1 = Rc::new(42);

/// let rc2 = Rc::new(42);

///

/// // Therefore, two HashableWeak wrappers containing these reference

/// // counters are not equal.

/// assert_ne!(HashableWeak::new(Rc::downgrade(&rc1)),

///            HashableWeak::new(Rc::downgrade(&rc2)));

///

/// // But HashableWeak holding the same underlying object are equal.

/// assert_eq!(HashableWeak::new(Rc::downgrade(&rc1)),

///            HashableWeak::new(Rc::downgrade(&rc1)));

/// ```

///

/// Since 

/// [`Weak<T>`](https://doc.rust-lang.org/std/rc/struct.Weak.html) is a

/// weak reference, the underlying value is not guaranteed to exist. A 

/// [`Weak<T>`](https://doc.rust-lang.org/std/rc/struct.Weak.html) that

/// is empty can still be wrapped in a

/// [`HashableWeak<T>`](struct.HashableWeak.html).

///

/// ```

/// use std::collections::hash_map::DefaultHasher;

/// use std::hash::{Hash, Hasher};

/// use std::rc::{Rc, Weak};

///

/// use hashable_rc::HashableWeak;

///

/// fn hash<H: Hash>(value: &H) -> u64 {

///     let mut state = DefaultHasher::new();

///     value.hash(&mut state);

///     state.finish()

/// }

/// 

/// let weak: Weak<i32> = Weak::new();

/// let rc = Rc::new(0);

///

/// // Hashing still works for a HashableWeak pointing to no value. It will

/// // hash differently than HashableWeak objects containing values, and

/// // will hash the same as other empty HashableWeak objects.

/// assert_ne!(hash(&HashableWeak::new(weak.clone())), 

///            hash(&HashableWeak::new(Rc::downgrade(&rc))));

/// assert_eq!(hash(&HashableWeak::new(weak.clone())), 

///            hash(&HashableWeak::new(weak.clone())));

///

/// // Empty HashableWeak objects are also not equal to assigned 

/// // HashableWeak objects, while being equal to other empty HashableWeak

/// // objects.

/// assert_ne!(HashableWeak::new(weak.clone()), 

///            HashableWeak::new(Rc::downgrade(&rc)));

/// assert_eq!(HashableWeak::new(weak.clone()), 

///            HashableWeak::new(weak.clone()));

/// ```

#[derive(Debug)]
pub struct HashableWeak<T> {
    value: Weak<T>,
}

impl <T> HashableWeak<T> {
    /// Constructs a new [`HashableWeak<T>`](struct.HashableWeak.html)

    /// wrapping a

    /// [`Weak<T>`](https://doc.rust-lang.org/std/rc/struct.Weak.html).

    pub fn new(value: Weak<T>) -> Self {
        HashableWeak {value}
    }


}

impl <T> Hash for HashableWeak<T> {
    /// Generate a hash value for the 

    /// [`HashableWeak<T>`](struct.HashableWeak.html).

    ///

    /// This hash value is based on the underlying pointer. Two unique 

    /// objects will most likely have different hashes, even if their 

    /// values are the same.

    ///

    /// If no value is pointed to, the Hasher state remains unaltered.

    fn hash<H>(&self, state: &mut H) where H: Hasher {
        let upgraded_weak: Option<Rc<T>> = self.value.clone().upgrade();
        match upgraded_weak {
            None => {}
            Some(rc) => {
                hash_rc(rc, state);
            }
        }
    }
}

impl <T> PartialEq for HashableWeak<T> {
    /// Equality for two [`HashableWeak<T>`](struct.HashableWeak.html)

    /// objects.

    ///

    /// Equality is determined by pointer equality, rather than value 

    /// equality. Objects are only considered equal if they point to 

    /// the same object (or if both point to no object).

    fn eq(&self, other: &Self) -> bool {
        Weak::ptr_eq(&self.value, &other.value)
    }
}

impl <T> Eq for HashableWeak<T> {}

#[cfg(test)]
mod tests {
    use crate::{HashableRc, HashableWeak};
    use std::collections::hash_map::DefaultHasher;
    use std::hash::{Hash, Hasher};
    use std::rc::{Rc, Weak};
    
    fn hash<H: Hash>(value: &H) -> u64 {
        let mut state = DefaultHasher::new();
        value.hash(&mut state);
        state.finish()
    }
    
    #[test]
    fn test_hashable_rc_hash() {
        let rc1 = Rc::new(42);
        let rc2 = Rc::new(42);
        
        assert_ne!(hash(&HashableRc::new(rc1.clone())), hash(&HashableRc::new(rc2.clone())));
        assert_eq!(hash(&HashableRc::new(rc1.clone())), hash(&HashableRc::new(rc1.clone())));
    }
    
    #[test]
    fn test_hashable_rc_eq() {
        let rc1 = Rc::new(42);
        let rc2 = Rc::new(42);
        
        assert_ne!(HashableRc::new(rc1.clone()), HashableRc::new(rc2.clone()));
        assert_eq!(HashableRc::new(rc1.clone()), HashableRc::new(rc1.clone()));
    }

    #[test]
    fn test_hashable_rc_get_clone() {
        let rc1 = Rc::new(42);
        let rc2 = Rc::new(42);
        let rc1_hashable = HashableRc::new(rc1.clone());

        assert_eq!(rc1_hashable.get_cloned(), rc1);
        assert_eq!(rc1_hashable.get_cloned(), rc2);
        // Round trip follows from above, but included for completeness.

        assert_eq!(HashableRc::new(rc1_hashable.get_cloned()), rc1_hashable);
        // Round trip the other direction.

        assert_eq!(*rc1_hashable.get_cloned(), 42);
    }
    
    #[test]
    fn test_hashable_rc_hash_does_not_memory_leak() {
        let rc = Rc::new(42);
        
        hash(&HashableRc::new(rc.clone()));
        
        assert_eq!(Rc::strong_count(&rc), 1);
        assert_eq!(Rc::weak_count(&rc), 0);
    }
    
    #[test]
    fn test_hashable_weak_hash() {
        let rc1 = Rc::new(42);
        let rc2 = Rc::new(42);
        
        assert_ne!(hash(&HashableWeak::new(Rc::downgrade(&rc1))), hash(&HashableWeak::new(Rc::downgrade(&rc2))));
        assert_eq!(hash(&HashableWeak::new(Rc::downgrade(&rc1))), hash(&HashableWeak::new(Rc::downgrade(&rc1))));
    }
    
    #[test]
    fn test_hashable_weak_eq() {
        let rc1 = Rc::new(42);
        let rc2 = Rc::new(42);
        
        assert_ne!(HashableWeak::new(Rc::downgrade(&rc1)), HashableWeak::new(Rc::downgrade(&rc2)));
        assert_eq!(HashableWeak::new(Rc::downgrade(&rc1)), HashableWeak::new(Rc::downgrade(&rc1)));
    }
    
    #[test]
    fn test_hashable_weak_hash_does_not_memory_leak() {
        let rc = Rc::new(42);
        let weak = Rc::downgrade(&rc);
        
        hash(&HashableWeak::new(weak.clone()));
        
        assert_eq!(Rc::strong_count(&rc), 1);
        assert_eq!(Rc::weak_count(&rc), 1);
    }
    
    #[test]
    fn test_hashable_weak_hash_no_value() {
        // Weak is an empty weak reference.

        let weak: Weak<i32> = Weak::new();
        let rc = Rc::new(0);
        
        assert_ne!(hash(&HashableWeak::new(weak.clone())), hash(&HashableWeak::new(Rc::downgrade(&rc))));
        assert_eq!(hash(&HashableWeak::new(weak.clone())), hash(&HashableWeak::new(weak.clone())));
    }
    
    #[test]
    fn test_hashable_weak_eq_no_value() {
        // Weak is an empty weak reference.

        let weak: Weak<i32> = Weak::new();
        let rc = Rc::new(0);
        
        assert_ne!(HashableWeak::new(weak.clone()), HashableWeak::new(Rc::downgrade(&rc)));
        assert_eq!(HashableWeak::new(weak.clone()), HashableWeak::new(weak.clone()));
    }
}