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
use alloc::vec::Vec;

use core::fmt::{self, Formatter};

use crate::{
    archetype::{Archetype, CellMutGuard, Slice, Slot},
    system::{Access, AccessKind},
    util::PtrMut,
    Component, ComponentValue, Fetch, FetchItem,
};

use super::{FetchAccessData, FetchPrepareData, PreparedFetch};

#[derive(Debug, Clone)]
/// Mutable component fetch
/// See [crate::Component::as_mut]
pub struct Mutable<T>(pub(crate) Component<T>);

impl<'w, T> Fetch<'w> for Mutable<T>
where
    T: ComponentValue,
{
    const MUTABLE: bool = true;

    type Prepared = WriteComponent<'w, T>;

    #[inline]
    fn prepare(&self, data: FetchPrepareData<'w>) -> Option<Self::Prepared> {
        let guard = data.arch.borrow_mut(self.0.key())?;

        Some(WriteComponent {
            guard,
            arch: data.arch,
            tick: data.new_tick,
        })
    }

    #[inline]
    fn filter_arch(&self, arch: &Archetype) -> bool {
        arch.has(self.0.key())
    }

    #[inline]
    fn access(&self, data: FetchAccessData, dst: &mut Vec<Access>) {
        if data.arch.has(self.0.key()) {
            dst.extend_from_slice(&[Access {
                kind: AccessKind::Archetype {
                    id: data.arch_id,
                    component: self.0.key(),
                },
                mutable: true,
            }])
        }
    }

    fn describe(&self, f: &mut Formatter) -> fmt::Result {
        f.write_str("mut ")?;
        f.write_str(self.0.name())
    }

    fn searcher(&self, searcher: &mut crate::ArchetypeSearcher) {
        searcher.add_required(self.0.key())
    }
}

impl<'q, T: ComponentValue> FetchItem<'q> for Mutable<T> {
    type Item = &'q mut T;
}

#[doc(hidden)]
pub struct WriteComponent<'a, T> {
    guard: CellMutGuard<'a, [T]>,
    arch: &'a Archetype,
    tick: u32,
}

impl<'w, 'q, T: 'q + ComponentValue> PreparedFetch<'q> for WriteComponent<'w, T> {
    type Item = &'q mut T;
    type Chunk = PtrMut<'q, T>;

    unsafe fn create_chunk(&'q mut self, slots: Slice) -> Self::Chunk {
        self.guard
            .set_modified(&self.arch.entities[slots.as_range()], slots, self.tick);

        // Convert directly into a non-overlapping subslice without reading the whole slice
        PtrMut::new((self.guard.storage().as_ptr() as *mut T).add(slots.start))
    }

    #[inline]
    // See: <https://godbolt.org/z/8fWa136b9>
    unsafe fn fetch_next(chunk: &mut Self::Chunk, _: Slot) -> Self::Item {
        let old = chunk.as_ptr();
        chunk.advance(1);
        &mut *old
    }
}