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
use crate::{io::*, *};

impl<T, const N: usize> Fixed for [T; N] {
    fn size() -> u64 {
        std::mem::size_of::<Self>() as u64 // abi assumption
    }
}

impl<T: Decode + Fixed, const N: usize> Decode for [T; N] {
    fn decode<R: Read + Seek + IO>(reader: &mut R) -> Result<Self, R::Error> {
        array_init::try_array_init(|_| T::decode(reader))
    }
}

impl<T: Encode + Fixed, const N: usize> Encode for [T; N] {
    fn encode<W: Write + Seek + IO>(&self, writer: &mut W) -> Result<(), W::Error> {
        for e in self {
            e.encode(writer)?;
        }

        Ok(())
    }
}

pub struct ArrFrame<'a, R, T, const N: usize> {
    stream: &'a mut R,
    offset: u64,
    pd: PhantomData<T>,
}

impl<'a, R: Read + Seek + IO, T: Fixed + Decode, const N: usize> ArrFrame<'a, R, T, N> {
    pub fn get(&mut self, index: u64) -> Result<T, R::Error> {
        if index >= (N as u64) {
            panic!("index out of bounds: {index} >= {N}");
        }

        self.stream
            .seek(SeekFrom::Start(self.offset + index * T::size()))?;
        T::decode(self.stream)
    }
}

impl<'a, W: Write + Seek + IO, T: Fixed + Encode, const N: usize> ArrFrame<'a, W, T, N> {
    pub fn set(&mut self, index: u64, elem: T) -> Result<(), W::Error> {
        if index >= (N as u64) {
            panic!("index out of bounds: {index} >= {N}");
        }

        self.stream
            .seek(SeekFrom::Start(self.offset + index * T::size()))?;
        elem.encode(self.stream)
    }
}

impl<'a, R, T, const N: usize> Frame<R> for ArrFrame<'a, R, T, N> {
    fn stream(&mut self) -> &mut R {
        self.stream
    }

    fn offset(&self) -> u64 {
        self.offset
    }
}

impl<'a, R: 'a + IO, T: 'a + Fixed + Encode + Decode, const N: usize> ApplyLayout<'a, R>
    for [T; N]
{
    type Frame = ArrFrame<'a, R, T, N>;

    fn apply_layout(stream: &'a mut R, offset: u64) -> Result<Self::Frame, R::Error> {
        Ok(ArrFrame {
            stream,
            offset,
            pd: PhantomData,
        })
    }
}