use crate::error::PfcpError;
use crate::ie::{Ie, IeType};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UsageInformation {
pub flags: u8,
}
impl UsageInformation {
pub fn new(flags: u8) -> Self {
Self { flags }
}
pub fn new_with_flags(bef: bool, aft: bool, uae: bool, ube: bool) -> Self {
let mut flags = 0u8;
if bef {
flags |= 0x01;
}
if aft {
flags |= 0x02;
}
if uae {
flags |= 0x04;
}
if ube {
flags |= 0x08;
}
Self { flags }
}
pub fn has_bef(&self) -> bool {
(self.flags & 0x01) != 0
}
pub fn has_aft(&self) -> bool {
(self.flags & 0x02) != 0
}
pub fn has_uae(&self) -> bool {
(self.flags & 0x04) != 0
}
pub fn has_ube(&self) -> bool {
(self.flags & 0x08) != 0
}
pub fn set_bef_flag(&mut self) {
self.flags |= 0x01;
}
pub fn set_aft_flag(&mut self) {
self.flags |= 0x02;
}
pub fn set_uae_flag(&mut self) {
self.flags |= 0x04;
}
pub fn set_ube_flag(&mut self) {
self.flags |= 0x08;
}
pub fn marshal_len(&self) -> usize {
1 }
pub fn marshal(&self) -> Vec<u8> {
vec![self.flags]
}
pub fn marshal_to(&self, buf: &mut Vec<u8>) {
buf.push(self.flags);
}
pub fn unmarshal(data: &[u8]) -> Result<Self, PfcpError> {
if data.is_empty() {
return Err(PfcpError::invalid_length(
"Usage Information",
IeType::UsageInformation,
1,
0,
));
}
let flags = data[0];
Ok(Self { flags })
}
pub fn to_ie(&self) -> Ie {
Ie::new(IeType::UsageInformation, self.marshal())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_usage_information_new() {
let ui = UsageInformation::new(0x0F);
assert_eq!(ui.flags, 0x0F);
assert!(ui.has_bef());
assert!(ui.has_aft());
assert!(ui.has_uae());
assert!(ui.has_ube());
}
#[test]
fn test_usage_information_new_with_flags() {
let ui = UsageInformation::new_with_flags(true, false, true, false);
assert_eq!(ui.flags, 0x05); assert!(ui.has_bef());
assert!(!ui.has_aft());
assert!(ui.has_uae());
assert!(!ui.has_ube());
}
#[test]
fn test_usage_information_flag_methods() {
let ui = UsageInformation::new(0x0A); assert!(!ui.has_bef());
assert!(ui.has_aft());
assert!(!ui.has_uae());
assert!(ui.has_ube());
}
#[test]
fn test_usage_information_set_flag_methods() {
let mut ui = UsageInformation::new(0x00);
ui.set_bef_flag();
assert!(ui.has_bef());
assert_eq!(ui.flags, 0x01);
ui.set_aft_flag();
assert!(ui.has_aft());
assert_eq!(ui.flags, 0x03);
ui.set_uae_flag();
assert!(ui.has_uae());
assert_eq!(ui.flags, 0x07);
ui.set_ube_flag();
assert!(ui.has_ube());
assert_eq!(ui.flags, 0x0F);
}
#[test]
fn test_usage_information_marshal_unmarshal() {
let ui = UsageInformation::new(0x0F);
let data = ui.marshal();
assert_eq!(data.len(), 1);
assert_eq!(data[0], 0x0F);
let unmarshaled = UsageInformation::unmarshal(&data).unwrap();
assert_eq!(ui, unmarshaled);
}
#[test]
fn test_usage_information_marshal_unmarshal_zero() {
let ui = UsageInformation::new(0x00);
let data = ui.marshal();
let unmarshaled = UsageInformation::unmarshal(&data).unwrap();
assert_eq!(ui, unmarshaled);
assert_eq!(unmarshaled.flags, 0x00);
}
#[test]
fn test_usage_information_to_ie() {
let ui = UsageInformation::new(0x05);
let ie = ui.to_ie();
assert_eq!(ie.ie_type, IeType::UsageInformation);
}
#[test]
fn test_usage_information_unmarshal_empty_data() {
let data = [];
let result = UsageInformation::unmarshal(&data);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(matches!(err, PfcpError::InvalidLength { .. }));
}
#[test]
fn test_usage_information_marshal_len() {
let ui = UsageInformation::new(42);
assert_eq!(ui.marshal_len(), 1);
}
#[test]
fn test_usage_information_round_trip_all_flags() {
let test_values = [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
0x0E, 0x0F,
];
for &value in &test_values {
let ui = UsageInformation::new(value);
let data = ui.marshal();
let unmarshaled = UsageInformation::unmarshal(&data).unwrap();
assert_eq!(ui, unmarshaled);
}
}
#[test]
fn test_usage_information_individual_flags() {
let ui_bef = UsageInformation::new_with_flags(true, false, false, false);
assert_eq!(ui_bef.flags, 0x01);
assert!(ui_bef.has_bef());
let ui_aft = UsageInformation::new_with_flags(false, true, false, false);
assert_eq!(ui_aft.flags, 0x02);
assert!(ui_aft.has_aft());
let ui_uae = UsageInformation::new_with_flags(false, false, true, false);
assert_eq!(ui_uae.flags, 0x04);
assert!(ui_uae.has_uae());
let ui_ube = UsageInformation::new_with_flags(false, false, false, true);
assert_eq!(ui_ube.flags, 0x08);
assert!(ui_ube.has_ube());
}
}