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
use super::primitives::{Id, Valid};

use std::any::Any;

// ++++++++++++++++++++ Id[Generation|Activation]Error ++++++++++++++++++++ 

#[derive(Debug, PartialEq, Eq)]
pub enum IdGenerationError {
    /// The id couldn't be activated because the maximum id count this id-type
    /// or this id-manager allows was reached.
    ///
    /// TODO: naming?
    MaximumIdCountReached(usize),
}

pub type IdGenerationResult<T> = Result<T, IdGenerationError>;

#[derive(Debug, PartialEq, Eq)]
pub enum IdActivationError<Slot> {
    /// The id couldn't be activated because the maximum id count this id-type
    /// or this id-manager allows was reached.
    ///
    /// TODO: naming?
    MaximumIdCountReached(usize),
    
    /// The id couldn't be activated because it already is. 
    AlreadyActivated,
    
    /// The id couldn't be activated because the internal slot (in the id-manager) it 
    /// would use is already occupied.
    /// 
    /// This can be the case for id-types which have an generation attached (`SafeIndex`).
    ///
    /// Example: You try to activate `a = {idx:200, gen:5}`, but `b = {idx:200, gen:4}` 
    /// is already active. If you want to force `a`s activation, you first need to 
    /// invalidate `b`.
    SlotOccupied(Slot),
}

impl<Slot> IdActivationError<Slot> {
    // TODO remove this?
    #[doc(hidden)]
    pub fn from_err<X>(err: IdActivationError<X>) -> Self {
        match err {
            IdActivationError::MaximumIdCountReached(max) => {
                IdActivationError::MaximumIdCountReached(max)
            }
            IdActivationError::AlreadyActivated => {
                IdActivationError::AlreadyActivated
            }
            _ => unreachable!()
        }
    }
}

pub type IdActivationResult<T, Slot> = Result<T, IdActivationError<Slot>>;

pub trait _PrimaryIdManager<'a> {
    type _Id: Id;

    type Iter: Iterator<Item = Valid<'a, Self::_Id>> + 'a;
}

pub trait PrimaryIdManager: Any + Sync + Send 
    where Self: for<'a> _PrimaryIdManager<'a, _Id = <Self as PrimaryIdManager>::Id>
{
    type Id: Id;

    fn len(&self) -> usize;

    fn maximum_id_count(&self) -> usize;

    /// Tests if `id` is usable.
    fn validate(&self, id: Self::Id) -> Option<Valid<Self::Id>>;                 

    /// Makes `id` unusable and returns `true`. 
    /// Returns `false` if `id` is already invalid.
    unsafe fn invalidate(&mut self, id: Self::Id) -> bool;

    /// Generates a new id.
    fn generate(&mut self) -> IdGenerationResult<Valid<Self::Id>>;

    fn activate(&mut self, id: Self::Id) -> IdActivationResult<Valid<Self::Id>, Self::Id>;

    unsafe fn clear(&mut self);

    fn iter<'a>(&'a self) -> <Self as _PrimaryIdManager<'a>>::Iter;
}

/* NOTE: old code
// ++++++++++++++++++++ IdManager-traits ++++++++++++++++++++ 

/// This is just to share some code between `PrimaryIdManager` and `SecondaryIdManager`.
pub trait IdManager: Any + Sync + Send {
    type Id: Id;

    fn len(&self) -> usize;

    fn maximum_id_count(&self) -> usize;
}

/// ...
///
/// If `Self` provides an iterator, its item should be `Valid<'a, Self::Id>`.
pub trait PrimaryIdManager: IdManager{
    /// Tests if `id` is usable.
    fn validate(&self, id: Self::Id) -> Option<Valid<Self::Id>>;

    /// Makes `id` unusable and returns `true`. 
    /// Returns `false` if `id` is already invalid.
    unsafe fn invalidate(&mut self, id: Self::Id) -> bool;

    /// Generates a new id.
    fn generate(&mut self) -> IdGenerationResult<Valid<Self::Id>>;

    fn activate(&mut self, id: Self::Id) -> IdActivationResult<Valid<Self::Id>, Self::Id>;

    /// TODO should this be `Valid<Self::Id>`?
    fn slot_of(&mut self, id: Self::Id) -> Option<Self::Id>;

    unsafe fn clear(&mut self);
}

/// This is just some interface-glue for `Composite[Multi]IdStore`.
/// You most likely won't use this trait directly. 
///
/// If `Self` provides an iterator, it will remain unused (at least by 
/// `Composite[Multi]IdStore`, that is).
pub trait SecondaryIdManager: IdManager{
    type PrimaryId: Id;

    /// Tests if `id` is usable and if so, returns the primary id it was 
    /// activated for.
    fn validate(&self, m_id: Self::Id) -> Option<Valid<Self::PrimaryId>>;

    /// Makes `id` unusable and returns the primary id it was activated for.
    /// Returns `None` if `id` is already invalid.
    ///
    /// The returned primary id is guaranteed to be valid until the borrow is released.
    fn invalidate(&mut self, id: Self::Id) -> Option<Valid<Self::PrimaryId>>;

    /// Generates a new id and activates it for `p_id`.
    ///
    /// Note that this method doesn't check if there's already a managed id activated for
    /// `p_id`. This can be intended behavior, see `CompositeMultiIdStore`.
    fn generate_for<'id>(
        &mut self, 
        p_id: Valid<'id, Self::PrimaryId>
    ) -> IdGenerationResult<Self::Id>;

    /// ...
    ///
    /// Note that this method doesn't check if there's already a managed id activated for
    /// `p_id`. This can be intended behavior, see `CompositeMultiIdStore`.
    fn activate_for<'id>(
        &mut self, 
        p_id: Valid<'id, Self::PrimaryId>,
        m_id: Self::Id,
    ) -> IdActivationResult<(), (Self::Id, Self::PrimaryId)>;

    /// TODO should this return `(Self::Id, Valid<Self::PrimaryId>)`?
    ///
    /// TODO should `id` be `usize`?
    fn slot_of(&mut self, id: Self::Id) -> Option<(Self::Id, Self::PrimaryId)>;

    fn clear(&mut self);
}
*/