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); } */