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
use std::{
    mem,
    ops::{Deref, DerefMut},
};

use zerocopy::{ByteSlice, ByteSliceMut, LayoutVerified};

pub use crate::ccsds::tc::transfer_frame::*;

pub const TRAILER_SIZE: usize = 2;

pub struct Builder<B> {
    bare: B,
}

impl<B> Builder<B>
where
    B: ByteSliceMut,
{
    pub fn new(bytes: B) -> Option<Self> {
        if bytes.len() < TRAILER_SIZE {
            None
        } else {
            Some(Self { bare: bytes })
        }
    }

    pub fn bare_mut(&mut self) -> Option<BareBuilder<&mut [u8]>> {
        let bare_len = self.bare.len();
        BareBuilder::new(&mut self.bare[..bare_len - TRAILER_SIZE])
    }

    pub fn finish(mut self, bare_len: usize) -> usize {
        let frame_len = bare_len + TRAILER_SIZE;
        assert!(frame_len <= self.bare.len());
        let bare_bytes = &self.bare[..bare_len];
        let fecw = FECF_CRC.checksum(bare_bytes);
        let fecw_bytes = &mut self.bare[bare_len..][..TRAILER_SIZE];
        fecw_bytes.copy_from_slice(&fecw.to_be_bytes());
        frame_len
    }
}

pub struct BareBuilder<B> {
    primary_header: LayoutVerified<B, PrimaryHeader>,
    data_field: B,
}

impl<B> BareBuilder<B>
where
    B: ByteSlice,
{
    fn new(bytes: B) -> Option<Self> {
        let (primary_header, data_field) = LayoutVerified::new_unaligned_from_prefix(bytes)?;
        Some(Self {
            primary_header,
            data_field,
        })
    }
}

impl<B> BareBuilder<B>
where
    B: ByteSliceMut,
{
    pub fn use_default(&mut self) {
        self.set_version_number(0);
        self.set_bypass_flag(true); // Type-Bx
        self.set_control_command_flag(false); // Type-xD
        self.set_vcid(0);
    }

    pub fn data_field_mut(&mut self) -> &mut B {
        &mut self.data_field
    }

    pub fn finish(mut self, data_field_len: usize) -> usize {
        let bare_len = mem::size_of::<PrimaryHeader>() + data_field_len;
        let frame_len = bare_len + TRAILER_SIZE;
        self.set_frame_length_in_bytes(frame_len);
        bare_len
    }
}

impl<B> Deref for BareBuilder<B>
where
    B: ByteSlice,
{
    type Target = PrimaryHeader;

    fn deref(&self) -> &Self::Target {
        &self.primary_header
    }
}

impl<B> DerefMut for BareBuilder<B>
where
    B: ByteSliceMut,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.primary_header
    }
}