summaryrefslogtreecommitdiff
path: root/ecs/src
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src')
-rw-r--r--ecs/src/actions.rs4
-rw-r--r--ecs/src/component.rs170
-rw-r--r--ecs/src/component/storage/archetype.rs1
-rw-r--r--ecs/src/entity.rs35
-rw-r--r--ecs/src/event/component.rs6
-rw-r--r--ecs/src/lib.rs140
-rw-r--r--ecs/src/pair.rs2
-rw-r--r--ecs/src/query.rs49
-rw-r--r--ecs/src/query/flexible.rs4
-rw-r--r--ecs/src/query/term.rs23
-rw-r--r--ecs/src/util/array_vec.rs14
11 files changed, 257 insertions, 191 deletions
diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs
index e0efeda..3dd8755 100644
--- a/ecs/src/actions.rs
+++ b/ecs/src/actions.rs
@@ -23,7 +23,7 @@ impl<'world> Actions<'world>
.push(Action::Spawn(components.into_parts_array().into()));
}
- /// Queues up despawning a entity at the end of the current tick.
+ /// Queues up despawning a entity at the end of the **next** tick.
pub fn despawn(&mut self, entity_uid: Uid)
{
debug_assert_eq!(entity_uid.kind(), UidKind::Entity);
@@ -48,7 +48,7 @@ impl<'world> Actions<'world>
));
}
- /// Queues up removing component(s) from a entity at the end of the current tick.
+ /// Queues up removing component(s) from a entity at the end of the **next** tick.
pub fn remove_components(
&mut self,
entity_uid: Uid,
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index a0ed752..5a8cd0b 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -1,8 +1,9 @@
use std::any::{type_name, Any};
-use std::error::Error;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
+use ecs_macros::Component;
+use hashbrown::HashSet;
use seq_macro::seq;
use crate::lock::{
@@ -15,7 +16,7 @@ use crate::lock::{
use crate::system::Input as SystemInput;
use crate::uid::Uid;
use crate::util::Array;
-use crate::{EntityComponentRef, World};
+use crate::EntityComponentRef;
pub mod local;
@@ -23,14 +24,6 @@ pub(crate) mod storage;
pub trait Component: SystemInput + Any
{
- type HandleMut<'component>: HandleFromEntityComponentRef<'component>
- where
- Self: Sized;
-
- type Handle<'component>: HandleFromEntityComponentRef<'component>
- where
- Self: Sized;
-
/// Returns the ID of this component.
fn id() -> Uid
where
@@ -77,46 +70,31 @@ pub trait Sequence
fn into_parts_array(self) -> Self::PartsArray;
}
-/// [`Component`] metadata.
-#[derive(Debug, Clone)]
-#[non_exhaustive]
-pub struct Metadata
-{
- pub id: Uid,
-}
-
-impl Metadata
+#[derive(Debug)]
+pub struct Handle<'a, ComponentData: 'static>
{
- #[must_use]
- pub fn of<ComponentT: Component>() -> Self
- {
- Self { id: ComponentT::id() }
- }
+ inner: MappedReadGuard<'a, ComponentData>,
}
-pub trait HandleFromEntityComponentRef<'comp>: Sized
+impl<'comp, ComponentData: 'static> Handle<'comp, ComponentData>
{
- type Error: Error;
-
/// Creates a new handle instance from a [`EntityComponentRef`].
///
/// # Errors
- /// See the implementation's [`Self::Error`] type.
- fn from_entity_component_ref(
- entity_component_ref: Option<EntityComponentRef<'comp>>,
- world: &'comp World,
- ) -> Result<Self, Self::Error>;
-}
-
-#[derive(Debug)]
-pub struct Handle<'a, ComponentData: 'static>
-{
- inner: MappedReadGuard<'a, ComponentData>,
-}
+ /// Will return `Err` if acquiring the component's lock fails.
+ pub fn from_entity_component_ref(
+ entity_component_ref: EntityComponentRef<'comp>,
+ ) -> Result<Self, HandleError>
+ {
+ Ok(Self::new(
+ entity_component_ref
+ .component()
+ .read_nonblock()
+ .map_err(AcquireLockError)?,
+ ))
+ }
-impl<'a, ComponentData: 'static> Handle<'a, ComponentData>
-{
- pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Any>>) -> Self
+ pub(crate) fn new(inner: ReadGuard<'comp, Box<dyn Any>>) -> Self
{
Self {
inner: inner.map(|component| {
@@ -133,28 +111,6 @@ impl<'a, ComponentData: 'static> Handle<'a, ComponentData>
}
}
-impl<'comp, ComponentData: 'static> HandleFromEntityComponentRef<'comp>
- for Handle<'comp, ComponentData>
-{
- type Error = HandleError;
-
- fn from_entity_component_ref(
- entity_component_ref: Option<EntityComponentRef<'comp>>,
- _world: &'comp World,
- ) -> Result<Self, Self::Error>
- {
- let entity_comp =
- entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?;
-
- Ok(Self::new(
- entity_comp
- .component()
- .read_nonblock()
- .map_err(AcquireComponentLockFailed)?,
- ))
- }
-}
-
impl<ComponentData: 'static> Deref for Handle<'_, ComponentData>
{
type Target = ComponentData;
@@ -171,9 +127,25 @@ pub struct HandleMut<'a, ComponentData: 'static>
inner: MappedWriteGuard<'a, ComponentData>,
}
-impl<'a, ComponentData: 'static> HandleMut<'a, ComponentData>
+impl<'comp, ComponentData: 'static> HandleMut<'comp, ComponentData>
{
- pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Any>>) -> Self
+ /// Creates a new handle instance from a [`EntityComponentRef`].
+ ///
+ /// # Errors
+ /// Will return `Err` if acquiring the component's lock fails.
+ pub fn from_entity_component_ref(
+ entity_component_ref: EntityComponentRef<'comp>,
+ ) -> Result<Self, HandleError>
+ {
+ Ok(Self::new(
+ entity_component_ref
+ .component()
+ .write_nonblock()
+ .map_err(AcquireLockError)?,
+ ))
+ }
+
+ pub(crate) fn new(inner: WriteGuard<'comp, Box<dyn Any>>) -> Self
{
Self {
inner: inner.map(|component| {
@@ -190,28 +162,6 @@ impl<'a, ComponentData: 'static> HandleMut<'a, ComponentData>
}
}
-impl<'comp, ComponentData: 'static> HandleFromEntityComponentRef<'comp>
- for HandleMut<'comp, ComponentData>
-{
- type Error = HandleError;
-
- fn from_entity_component_ref(
- entity_component_ref: Option<EntityComponentRef<'comp>>,
- _world: &'comp World,
- ) -> Result<Self, Self::Error>
- {
- let entity_comp =
- entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?;
-
- Ok(Self::new(
- entity_comp
- .component()
- .write_nonblock()
- .map_err(AcquireComponentLockFailed)?,
- ))
- }
-}
-
impl<ComponentData: 'static> Deref for HandleMut<'_, ComponentData>
{
type Target = ComponentData;
@@ -234,15 +184,12 @@ impl<ComponentData: 'static> DerefMut for HandleMut<'_, ComponentData>
pub enum HandleError
{
#[error(transparent)]
- AcquireComponentLockFailed(#[from] AcquireComponentLockFailed),
-
- #[error("Component does not exist")]
- ComponentDoesNotExist,
+ AcquireLockFailed(#[from] AcquireLockError),
}
#[derive(Debug, thiserror::Error)]
-#[error(transparent)]
-pub struct AcquireComponentLockFailed(LockError);
+#[error("Failed to acquire component lock")]
+pub struct AcquireLockError(#[source] LockError);
macro_rules! inner {
($c: tt) => {
@@ -366,3 +313,38 @@ impl Default for PartsBuilder
Self { name: "(unspecified)" }
}
}
+
+/// Pending component removals for a entity.
+#[derive(Debug, Clone, Component)]
+pub struct Removals
+{
+ component_ids: HashSet<Uid>,
+}
+
+impl Removals
+{
+ pub fn contains<ComponentT: Component>(&self) -> bool
+ {
+ self.contains_id(ComponentT::id())
+ }
+
+ pub fn contains_id(&self, component_id: Uid) -> bool
+ {
+ self.component_ids.contains(&component_id)
+ }
+
+ pub(crate) fn add_ids(&mut self, ids: impl IntoIterator<Item = Uid>)
+ {
+ self.component_ids.extend(ids)
+ }
+}
+
+impl FromIterator<Uid> for Removals
+{
+ fn from_iter<T: IntoIterator<Item = Uid>>(iter: T) -> Self
+ {
+ Self {
+ component_ids: iter.into_iter().collect(),
+ }
+ }
+}
diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs
index a88e0e8..bb29701 100644
--- a/ecs/src/component/storage/archetype.rs
+++ b/ecs/src/component/storage/archetype.rs
@@ -332,6 +332,7 @@ impl EntityComponent
}
}
+ #[allow(dead_code)]
pub fn id(&self) -> Uid
{
self.id
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index 562f7ea..bab3d61 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -10,7 +10,6 @@ use crate::component::storage::archetype::{
use crate::component::{
Component,
Handle as ComponentHandle,
- HandleFromEntityComponentRef,
HandleMut as ComponentHandleMut,
};
use crate::uid::{Kind as UidKind, Uid};
@@ -20,7 +19,6 @@ use crate::{EntityComponentRef, World};
#[derive(Debug)]
pub struct Handle<'a>
{
- world: &'a World,
archetype: &'a Archetype,
entity: &'a ArchetypeEntity,
}
@@ -50,13 +48,12 @@ impl<'a> Handle<'a>
let component = self.get_matching_components(ComponentT::id()).next()?;
Some(
- ComponentHandle::from_entity_component_ref(Some(component), self.world)
- .unwrap_or_else(|err| {
- panic!(
- "Taking component {} lock failed: {err}",
- type_name::<ComponentT>()
- );
- }),
+ ComponentHandle::from_entity_component_ref(component).unwrap_or_else(|err| {
+ panic!(
+ "Taking component {} lock failed: {err}",
+ type_name::<ComponentT>()
+ );
+ }),
)
}
@@ -77,13 +74,14 @@ impl<'a> Handle<'a>
let component = self.get_matching_components(ComponentT::id()).next()?;
Some(
- ComponentHandleMut::from_entity_component_ref(Some(component), self.world)
- .unwrap_or_else(|err| {
+ ComponentHandleMut::from_entity_component_ref(component).unwrap_or_else(
+ |err| {
panic!(
"Taking component {} lock failed: {err}",
type_name::<ComponentT>()
);
- }),
+ },
+ ),
)
}
@@ -98,13 +96,14 @@ impl<'a> Handle<'a>
}
}
- pub(crate) fn new(
- world: &'a World,
- archetype: &'a Archetype,
- entity: &'a ArchetypeEntity,
- ) -> Self
+ pub fn component_ids(&self) -> impl Iterator<Item = Uid> + '_
+ {
+ self.archetype.component_ids_sorted()
+ }
+
+ pub(crate) fn new(archetype: &'a Archetype, entity: &'a ArchetypeEntity) -> Self
{
- Self { world, archetype, entity }
+ Self { archetype, entity }
}
}
diff --git a/ecs/src/event/component.rs b/ecs/src/event/component.rs
index ef09480..72a78a3 100644
--- a/ecs/src/event/component.rs
+++ b/ecs/src/event/component.rs
@@ -10,9 +10,3 @@ use crate::Component;
/// b) The target component is added to a entity.
#[derive(Debug, Component)]
pub struct Added(Infallible);
-
-/// Pair relation for events emitted when:
-/// a) The target component is removed from a entity.
-/// b) A entity with the target component is despawned.
-#[derive(Debug, Component)]
-pub struct Removed(Infallible);
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 53abc6b..07b1cba 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -15,14 +15,13 @@ use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComp
use crate::component::storage::Storage as ComponentStorage;
use crate::component::{
Component,
+ IntoParts,
Parts as ComponentParts,
+ Removals as ComponentRemovals,
Sequence as ComponentSequence,
};
-use crate::entity::CREATE_STATIC_ENTITIES;
-use crate::event::component::{
- Added as ComponentAddedEvent,
- Removed as ComponentRemovedEvent,
-};
+use crate::entity::{Handle as EntityHandle, CREATE_STATIC_ENTITIES};
+use crate::event::component::Added as ComponentAddedEvent;
use crate::extension::{Collector as ExtensionCollector, Extension};
use crate::lock::Lock;
use crate::pair::{ChildOf, DependsOn, Pair};
@@ -209,8 +208,12 @@ impl World
self.data.component_storage.create_imaginary_archetypes();
+ let prev_pending_removals = std::mem::take(&mut self.data.pending_removals);
+
self.perform_queued_actions();
+ self.perform_removals(prev_pending_removals);
+
if self.stop.load(Ordering::Relaxed) {
return StepResult::Stop;
}
@@ -355,6 +358,8 @@ impl World
let mut has_swapped_active_queue = false;
+ // TODO: Figure out a good way to handle situations where there are multiple
+ // AddComponents/RemoveComponents actions that affect the same entity.
for action in active_action_queue.drain(..) {
match action {
Action::Spawn(components) => {
@@ -382,24 +387,12 @@ impl World
}
}
Action::Despawn(entity_uid) => {
- let removed_entity =
- match self.data.component_storage.remove_entity(entity_uid) {
- Ok(components) => components,
- Err(err) => {
- tracing::error!("Failed to despawn entity: {err}");
- return;
- }
- };
-
- if !has_swapped_active_queue {
- self.swap_event_queue(&mut has_swapped_active_queue);
- }
-
- for removed_ent_comp in removed_entity.components() {
- self.emit_event_by_id::<ComponentRemovedEvent>(
- removed_ent_comp.id(),
- );
- }
+ Self::schedule_removal(
+ &mut self.data.component_storage,
+ &mut self.data.pending_removals,
+ entity_uid,
+ PendingRemoval::Entity,
+ );
}
Action::AddComponents(entity_uid, components) => {
let added_component_ids = Self::add_entity_components(
@@ -417,19 +410,12 @@ impl World
}
}
Action::RemoveComponents(entity_uid, component_ids) => {
- let removed_component_ids = Self::remove_entity_components(
- entity_uid,
- component_ids,
+ Self::schedule_removal(
&mut self.data.component_storage,
+ &mut self.data.pending_removals,
+ entity_uid,
+ PendingRemoval::Components(component_ids),
);
-
- if !has_swapped_active_queue {
- self.swap_event_queue(&mut has_swapped_active_queue);
- }
-
- for comp_id in removed_component_ids {
- self.emit_event_by_id::<ComponentRemovedEvent>(comp_id);
- }
}
Action::Stop => {
self.stop.store(true, Ordering::Relaxed);
@@ -438,6 +424,66 @@ impl World
}
}
+ fn perform_removals(&mut self, removals: Vec<(Uid, PendingRemoval)>)
+ {
+ for (entity_id, removal) in removals {
+ match removal {
+ PendingRemoval::Components(component_ids) => {
+ Self::remove_entity_components(
+ entity_id,
+ component_ids.into_iter().chain([ComponentRemovals::id()]),
+ &mut self.data.component_storage,
+ );
+ }
+ PendingRemoval::Entity => {
+ if let Err(err) = self.data.component_storage.remove_entity(entity_id)
+ {
+ tracing::error!("Failed to remove entity {entity_id}: {err}");
+ }
+ }
+ }
+ }
+ }
+
+ #[tracing::instrument(skip(component_storage, pending_removals))]
+ fn schedule_removal(
+ component_storage: &mut ComponentStorage,
+ pending_removals: &mut Vec<(Uid, PendingRemoval)>,
+ entity_uid: Uid,
+ removal: PendingRemoval,
+ )
+ {
+ let Some(ent_handle) = Self::get_entity(component_storage, entity_uid) else {
+ tracing::warn!("Cannot schedule removal. Entity does not exist");
+ return;
+ };
+
+ let component_ids = match removal {
+ PendingRemoval::Components(ref component_ids) => component_ids,
+ PendingRemoval::Entity => &ent_handle.component_ids().collect::<Vec<_>>(),
+ };
+
+ let Some(mut component_removals) = ent_handle.get_mut::<ComponentRemovals>()
+ else {
+ Self::add_entity_components(
+ entity_uid,
+ [ComponentRemovals::from_iter(component_ids.iter().copied())
+ .into_parts()],
+ component_storage,
+ );
+
+ pending_removals.push((entity_uid, removal));
+
+ return;
+ };
+
+ component_removals.add_ids(component_ids.iter().copied());
+
+ drop(component_removals);
+
+ pending_removals.push((entity_uid, removal));
+ }
+
fn add_entity_components(
entity_uid: Uid,
components: impl IntoIterator<Item = ComponentParts>,
@@ -521,6 +567,21 @@ impl World
*has_swapped_active_queue = true;
}
+
+ fn get_entity(
+ component_storage: &mut ComponentStorage,
+ entity_uid: Uid,
+ ) -> Option<EntityHandle<'_>>
+ {
+ let archetype = component_storage.get_entity_archetype(entity_uid)?;
+
+ Some(EntityHandle::new(
+ archetype,
+ archetype
+ .get_entity_by_id(entity_uid)
+ .expect("Not possible"),
+ ))
+ }
}
impl Default for World
@@ -542,11 +603,12 @@ pub enum StepResult
}
#[derive(Debug)]
-pub struct WorldData
+struct WorldData
{
component_storage: ComponentStorage,
sole_storage: SoleStorage,
action_queue: Rc<ActionQueue>,
+ pending_removals: Vec<(Uid, PendingRemoval)>,
}
impl Default for WorldData
@@ -557,11 +619,19 @@ impl Default for WorldData
component_storage: ComponentStorage::default(),
sole_storage: SoleStorage::default(),
action_queue: Rc::new(ActionQueue::default()),
+ pending_removals: Vec::new(),
}
}
}
#[derive(Debug)]
+enum PendingRemoval
+{
+ Components(Vec<Uid>),
+ Entity,
+}
+
+#[derive(Debug)]
pub struct EntityComponentRef<'a>
{
component_id: Uid,
diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs
index 2055d5e..4ff4995 100644
--- a/ecs/src/pair.rs
+++ b/ecs/src/pair.rs
@@ -140,7 +140,7 @@ impl Handle<'_>
unreachable!();
};
- Some(EntityHandle::new(self.world, archetype, archetype_entity))
+ Some(EntityHandle::new(archetype, archetype_entity))
}
}
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index 7e10c5b..ccb7add 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -6,7 +6,6 @@ use seq_macro::seq;
use crate::component::{
Component,
Handle as ComponentHandle,
- HandleFromEntityComponentRef,
HandleMut as ComponentHandleMut,
};
use crate::entity::Handle as EntityHandle;
@@ -342,18 +341,26 @@ impl<ComponentT: Component> TermWithField for &ComponentT
fn get_field<'world>(
entity_handle: &EntityHandle<'world>,
- world: &'world World,
+ _world: &'world World,
) -> Self::Field<'world>
{
assert_eq!(ComponentT::id().kind(), UidKind::Component);
- Self::Field::from_entity_component_ref(
- entity_handle
- .get_matching_components(ComponentT::id())
- .next(),
- world,
- )
- .unwrap_or_else(|err| {
+ let Some(component) = entity_handle
+ .get_matching_components(ComponentT::id())
+ .next()
+ else {
+ panic!(
+ concat!(
+ "Component {} was not found in entity {}. There ",
+ "is most likely a bug in the entity querying"
+ ),
+ type_name::<ComponentT>(),
+ entity_handle.uid()
+ );
+ };
+
+ Self::Field::from_entity_component_ref(component).unwrap_or_else(|err| {
panic!(
"Creating handle to component {} failed: {err}",
type_name::<ComponentT>()
@@ -375,18 +382,26 @@ impl<ComponentT: Component> TermWithField for &mut ComponentT
fn get_field<'world>(
entity_handle: &EntityHandle<'world>,
- world: &'world World,
+ _world: &'world World,
) -> Self::Field<'world>
{
assert_eq!(ComponentT::id().kind(), UidKind::Component);
- Self::Field::from_entity_component_ref(
- entity_handle
- .get_matching_components(ComponentT::id())
- .next(),
- world,
- )
- .unwrap_or_else(|err| {
+ let Some(component) = entity_handle
+ .get_matching_components(ComponentT::id())
+ .next()
+ else {
+ panic!(
+ concat!(
+ "Component {} was not found in entity {}. There ",
+ "is most likely a bug in the entity querying"
+ ),
+ type_name::<ComponentT>(),
+ entity_handle.uid()
+ );
+ };
+
+ Self::Field::from_entity_component_ref(component).unwrap_or_else(|err| {
panic!(
"Creating handle to component {} failed: {err}",
type_name::<ComponentT>()
diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs
index 6d65ee0..add30b0 100644
--- a/ecs/src/query/flexible.rs
+++ b/ecs/src/query/flexible.rs
@@ -22,7 +22,6 @@ impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>
pub fn iter(&self) -> Iter<'_>
{
Iter {
- world: self.world,
iter: self
.world
.data
@@ -59,7 +58,6 @@ impl<'query, const MAX_TERM_CNT: usize> IntoIterator for &'query Query<'_, MAX_T
pub struct Iter<'query>
{
- world: &'query World,
iter: QueryEntityIter<'query>,
}
@@ -71,7 +69,7 @@ impl<'query> Iterator for Iter<'query>
{
let (archetype, entity) = self.iter.next()?;
- Some(EntityHandle::new(self.world, archetype, entity))
+ Some(EntityHandle::new(archetype, entity))
}
}
diff --git a/ecs/src/query/term.rs b/ecs/src/query/term.rs
index 2e1ecca..9c772da 100644
--- a/ecs/src/query/term.rs
+++ b/ecs/src/query/term.rs
@@ -4,7 +4,6 @@ use std::marker::PhantomData;
use crate::component::{
Component,
Handle as ComponentHandle,
- HandleFromEntityComponentRef,
HandleMut as ComponentHandleMut,
};
use crate::query::{
@@ -65,17 +64,14 @@ impl<ComponentT: Component> TermWithField for Option<&ComponentT>
fn get_field<'world>(
entity_handle: &crate::entity::Handle<'world>,
- world: &'world crate::World,
+ _world: &'world crate::World,
) -> Self::Field<'world>
{
Some(
ComponentHandle::<'world, ComponentT>::from_entity_component_ref(
- Some(
- entity_handle
- .get_matching_components(ComponentT::id())
- .next()?,
- ),
- world,
+ entity_handle
+ .get_matching_components(ComponentT::id())
+ .next()?,
)
.unwrap_or_else(|err| {
panic!(
@@ -99,17 +95,14 @@ impl<ComponentT: Component> TermWithField for Option<&mut ComponentT>
fn get_field<'world>(
entity_handle: &crate::entity::Handle<'world>,
- world: &'world crate::World,
+ _world: &'world crate::World,
) -> Self::Field<'world>
{
Some(
ComponentHandleMut::<'world, ComponentT>::from_entity_component_ref(
- Some(
- entity_handle
- .get_matching_components(ComponentT::id())
- .next()?,
- ),
- world,
+ entity_handle
+ .get_matching_components(ComponentT::id())
+ .next()?,
)
.unwrap_or_else(|err| {
panic!(
diff --git a/ecs/src/util/array_vec.rs b/ecs/src/util/array_vec.rs
index 13a0349..a37b1f9 100644
--- a/ecs/src/util/array_vec.rs
+++ b/ecs/src/util/array_vec.rs
@@ -115,3 +115,17 @@ impl<Item, const CAPACITY: usize> Default for ArrayVec<Item, CAPACITY>
}
}
}
+
+impl<Item, const CAPACITY: usize> Drop for ArrayVec<Item, CAPACITY>
+{
+ fn drop(&mut self)
+ {
+ for item in &mut self.items[..self.len] {
+ // SAFETY: The items from index 0 to the length index will always be
+ // initialized and satisfy all the invariants of the Item type.
+ unsafe {
+ item.assume_init_drop();
+ }
+ }
+ }
+}