use bitvec::prelude::*;
use crate::{OCTET, PRIMARY_HEADER_SIZE, MAX_DATA_SIZE, MAX_SP_SIZE};
use crate::pri_header::{Identification, SequenceControl, PrimaryHeader, SecHeaderFlag};
use crate::data::{DataField, SecondaryHeader, UserData};
use crate::errors::SPPError;
#[derive(Default)]
pub struct Builder<'a> {
id: Option<Identification>,
seq: Option<SequenceControl>,
sec_head: Option<&'a SecondaryHeader<'a>>,
user_data: Option<&'a UserData<'a>>,
idle: bool,
_aux: BitArr!(for MAX_DATA_SIZE + 48, in u8),
}
impl<'a> Builder<'a> {
fn new() -> Self {
Self { _aux: bitarr!(u8, LocalBits; 0; MAX_SP_SIZE), ..Default::default() }
}
pub fn idle(&mut self, set: bool) {
self.idle = set
}
pub fn identification(&mut self, id: Option<Identification>) {
self.id = id
}
pub fn sequence_control(&mut self, sequence_control: Option<SequenceControl>) {
self.seq = sequence_control
}
pub fn secondary_header(&mut self, sec_head: Option<&'a SecondaryHeader>) {
self.sec_head = sec_head
}
pub fn user_data(&mut self, user_data: Option<&'a UserData>) {
self.user_data = user_data
}
pub fn build(mut self) -> Result<SpacePacket<'a>, SPPError> {
let (id, seq) = match (&self.id, &self.seq) {
(None, None) => return Err(SPPError::MandatoryFieldNotPresent),
(None, _) => return Err(SPPError::MandatoryFieldNotPresent),
(_, None) => return Err(SPPError::MandatoryFieldNotPresent),
(id, seq) => (id.clone().unwrap(), seq.clone().unwrap()),
};
if self.idle {
let new_id = Identification::new_idle(id.packet_type.clone());
self.identification(Some(new_id));
}
let mut pri_head = PrimaryHeader::new(&id, &seq);
let mut data = DataField::new();
if let SecHeaderFlag::Present = id.sec_header_flag {
if self.sec_head.is_none() {
return Err(SPPError::SecondaryHeaderNotPresent);
} else if self.sec_head.as_ref().unwrap().len() < 1 {
return Err(SPPError::SecondaryHeaderNotPresent);
}
}
data.sec_header(self.sec_head);
data.user_data(self.user_data);
let final_lenght: usize = data.len() / OCTET;
if final_lenght > MAX_DATA_SIZE {
return Err(SPPError::MaxDataSizeExedded); }
pri_head.data_lenght(final_lenght);
let sp: SpacePacket<'_> = SpacePacket::new(pri_head, data, self._aux);
if sp.data_field.len() < OCTET {
return Err(SPPError::MinDataLen); }
Ok(sp)
}
}
#[derive(Debug)]
pub struct SpacePacket<'a> {
primary_header: PrimaryHeader,
data_field: DataField<'a>,
_aux: BitArr!(for MAX_DATA_SIZE + 48, in u8),
}
impl<'a> SpacePacket<'a> {
fn new(ph: PrimaryHeader, df: DataField<'a>, _aux: BitArr!(for MAX_SP_SIZE, in u8)) -> Self {
Self { primary_header: ph, data_field: df, _aux}
}
pub fn builder() -> Builder<'static> {
Builder::new()
}
pub fn to_bits(&mut self) -> &BitSlice<u8> {
self.primary_header.to_bits(&mut self._aux);
let mut l = 48;
self.data_field.to_bits(&mut (&mut l, &mut self._aux));
&self._aux[..l]
}
pub fn len(&self) -> usize {
self.data_field.len() + PRIMARY_HEADER_SIZE
}
}
pub struct OctetStringSpacePacket<'a> {
pub primary_header: PrimaryHeader,
pub data_field: &'a BitSlice<u8>,
}
impl<'a> OctetStringSpacePacket<'a> {
pub fn new_from_slice(s: &'a BitSlice<u8>) -> Self {
let primary_header = PrimaryHeader::new_from_slice(&s[..48]);
let dl = (primary_header.data_length.data[0].to_le()
+ primary_header.data_length.data[1].to_le())
* OCTET as u8;
let data_field = &s[48..48 + dl as usize];
Self { primary_header, data_field }
}
}