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
use bytes::{buf::UninitSlice, BufMut};
use heapless::FnvIndexMap;
use impeller::{
    ser_de::Frozen, Component, ComponentId, ComponentValue, ComponentValueDim, ConstComponent,
    EntityId, ValueRepr,
};
use tracing::warn;

use crate::{Componentize, Decomponentize};

pub struct Column<V: ValueRepr + Component + ConstComponent, const N: usize> {
    map: FnvIndexMap<EntityId, V, N>,
}

impl<V: ValueRepr + Component + ConstComponent, const N: usize> Column<V, N> {
    pub fn new() -> Self {
        Self {
            map: Default::default(),
        }
    }
}

impl<V: ValueRepr + Component + ConstComponent, const N: usize> Default for Column<V, N> {
    fn default() -> Self {
        Self::new()
    }
}

impl<V: ValueRepr + Component + ConstComponent, const N: usize> Decomponentize for Column<V, N> {
    fn apply_value<D: ComponentValueDim>(
        &mut self,
        component_id: ComponentId,
        entity_id: EntityId,
        value: ComponentValue<'_, D>,
    ) {
        if component_id != ComponentId::new(V::NAME) {
            return;
        }
        if let Some(val) = V::from_component_value(value) {
            if self.map.insert(entity_id, val).is_err() {
                warn!("column map full");
            }
        }
    }
}

impl<V: ValueRepr + Component + ConstComponent, const N: usize> Componentize for Column<V, N> {
    fn sink_columns(&self, output: &mut impl Decomponentize) {
        self.map.iter().for_each(|(id, value)| {
            let value = value.fixed_dim_component_value();
            output.apply_value(ComponentId::new(V::NAME), *id, value);
        });
    }
}

#[derive(Default)]
pub struct FixedBuffer<const N: usize>(pub heapless::Vec<u8, N>);

impl<const N: usize> AsRef<[u8]> for FixedBuffer<N> {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

impl<const N: usize> Frozen for FixedBuffer<N> {
    type Freezable = FixedBuffer<N>;

    fn freeze(val: Self::Freezable) -> Self {
        val
    }
}

unsafe impl<const N: usize> BufMut for FixedBuffer<N> {
    fn remaining_mut(&self) -> usize {
        N - self.0.len()
    }

    unsafe fn advance_mut(&mut self, cnt: usize) {
        let pos = self.0.len() + cnt;
        if pos >= N {
            panic!("Advance out of range");
        }
        self.0.set_len(pos);
    }

    fn chunk_mut(&mut self) -> &mut bytes::buf::UninitSlice {
        let len = self.0.len();

        let ptr = self.0.as_mut_ptr();
        unsafe { &mut UninitSlice::from_raw_parts_mut(ptr, N)[len..] }
    }
}