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
//! An opaque handle used to read, modify or remove an element from an [RwStore](crate::RwStore)
//! once it has been inserted.
//!
//! When debug assertions are enabled, IDs will consume more memory to track the store that created
//! them.
//!
//! # Example
//!
//! ```
//! # use read_write_store::RwStore;
//! let store = RwStore::new();
//! let id_a = store.insert(42);
//! let id_b = store.insert(42);
//! ```

use std::fmt;
use std::fmt::{Debug, Formatter};
use std::ptr::NonNull;

use crate::rwstore_id::RwStoreId;

/// An opaque handle used to read, modify or remove an element from an [RwStore](crate::RwStore)
/// once it has been inserted. See the [module-level documentation](crate::id) for more.
#[derive(Copy, Clone)]
pub struct Id {
    ordinal: u32,
    bucket_id: u32,
    slot_address: NonNull<()>,
    store_id: RwStoreId,
}

impl Id {
    pub(crate) fn new<T>(ordinal: u32, bucket_id: u32, slot: &T, store_id: RwStoreId) -> Self {
        Self {
            ordinal,
            bucket_id,
            slot_address: NonNull::from(slot).cast(),
            store_id,
        }
    }

    pub(crate) fn ordinal(&self) -> u32 {
        self.ordinal
    }

    pub(crate) fn bucket_id(&self) -> u32 {
        self.bucket_id
    }

    pub(crate) fn slot<T>(&self) -> NonNull<T> {
        self.slot_address.cast()
    }

    pub(crate) fn store_id(&self) -> RwStoreId {
        self.store_id
    }
}

impl Debug for Id {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.debug_tuple("Id")
            .field(&self.ordinal)
            .field(&self.bucket_id)
            .field(&self.slot_address)
            .finish()
    }
}

unsafe impl Send for Id {}

unsafe impl Sync for Id {}

#[cfg(test)]
mod test {
    use std::panic::{RefUnwindSafe, UnwindSafe};

    use crate::RwStore;

    #[test]
    fn implements_sync() {
        let store = RwStore::new();
        let id = store.insert(0);
        &id as &dyn Sync;
    }

    #[test]
    fn implements_send() {
        let store = RwStore::new();
        let id = store.insert(0);
        &id as &dyn Send;
    }

    #[test]
    fn implements_unwind_safe() {
        let store = RwStore::new();
        let id = store.insert(0);
        &id as &dyn UnwindSafe;
    }

    #[test]
    fn implements_ref_unwind_safe() {
        let store = RwStore::new();
        let id = store.insert(0);
        &id as &dyn RefUnwindSafe;
    }
}