use crate::error::{Error, ErrorList};
use bitflags::bitflags;
pub type BlockControlFlagsType = u8;
bitflags! {
pub struct BlockControlFlags: BlockControlFlagsType {
const BLOCK_REPLICATE = 0x01;
const BLOCK_STATUS_REPORT = 0x02;
const BLOCK_DELETE_BUNDLE = 0x04;
const BLOCK_REMOVE = 0x10;
const BLOCK_CFRESERVED_FIELDS = 0xF0;
}
}
pub trait BlockValidation {
fn flags(&self) -> BlockControlFlags;
fn validate(&self) -> Result<(), Error>
where
Self: Sized,
{
if self
.flags()
.contains(BlockControlFlags::BLOCK_CFRESERVED_FIELDS)
{
Err(Error::BlockControlFlagsError(
"Given flag contains reserved bits".to_string(),
))
} else {
Ok(())
}
}
fn contains(&self, flags: BlockControlFlags) -> bool
where
Self: Sized,
{
self.flags().contains(flags)
}
fn set(&mut self, flags: BlockControlFlags);
}
impl BlockValidation for BlockControlFlagsType {
fn flags(&self) -> BlockControlFlags {
BlockControlFlags::from_bits_truncate(*self)
}
fn set(&mut self, flags: BlockControlFlags)
where
Self: Sized,
{
*self = flags.bits();
}
}
pub type BundleControlFlagsType = u64;
bitflags! {
#[derive(Default)]
pub struct BundleControlFlags: BundleControlFlagsType {
const BUNDLE_STATUS_REQUEST_DELETION = 0x040000;
const BUNDLE_STATUS_REQUEST_DELIVERY = 0x020000;
const BUNDLE_STATUS_REQUEST_FORWARD = 0x010000;
const BUNDLE_STATUS_REQUEST_RECEPTION = 0x004000;
const BUNDLE_REQUEST_STATUS_TIME = 0x000040;
const BUNDLE_REQUEST_USER_APPLICATION_ACK = 0x000020;
const BUNDLE_MUST_NOT_FRAGMENTED = 0x000004;
const BUNDLE_ADMINISTRATIVE_RECORD_PAYLOAD = 0x000002;
const BUNDLE_IS_FRAGMENT = 0x000001;
const BUNDLE_CFRESERVED_FIELDS = 0xE218;
}
}
pub trait BundleValidation {
fn flags(&self) -> BundleControlFlags;
fn contains(&self, flags: BundleControlFlags) -> bool
where
Self: Sized,
{
self.flags().contains(flags)
}
fn set(&mut self, flags: BundleControlFlags);
fn validate(&self) -> Result<(), ErrorList>
where
Self: Sized,
{
let mut errors: ErrorList = Vec::new();
let flags = self.flags();
if flags.contains(BundleControlFlags::BUNDLE_CFRESERVED_FIELDS) {
errors.push(Error::BundleControlFlagsError(
"Given flag contains reserved bits".to_string(),
));
}
if flags.contains(BundleControlFlags::BUNDLE_IS_FRAGMENT)
&& flags.contains(BundleControlFlags::BUNDLE_MUST_NOT_FRAGMENTED)
{
errors.push(Error::BundleControlFlagsError(
"Both 'bundle is a fragment' and 'bundle must not be fragmented' flags are set"
.to_string(),
));
}
let admin_rec_check = !flags
.contains(BundleControlFlags::BUNDLE_ADMINISTRATIVE_RECORD_PAYLOAD)
|| (!flags.contains(BundleControlFlags::BUNDLE_STATUS_REQUEST_RECEPTION)
&& !flags.contains(BundleControlFlags::BUNDLE_STATUS_REQUEST_FORWARD)
&& !flags.contains(BundleControlFlags::BUNDLE_STATUS_REQUEST_DELIVERY)
&& !flags.contains(BundleControlFlags::BUNDLE_STATUS_REQUEST_DELETION));
if !admin_rec_check {
errors.push(Error::BundleControlFlagsError(
"\"payload is administrative record => no status report request flags\" failed"
.to_string(),
))
}
if !errors.is_empty() {
return Err(errors);
}
Ok(())
}
}
impl BundleValidation for BundleControlFlagsType {
fn flags(&self) -> BundleControlFlags {
BundleControlFlags::from_bits_truncate(*self)
}
fn set(&mut self, flags: BundleControlFlags)
where
Self: Sized,
{
*self = flags.bits();
}
}