use crate::error::PfcpError;
use crate::ie::bar_id::BarId;
use crate::ie::downlink_data_notification_delay::DownlinkDataNotificationDelay;
use crate::ie::suggested_buffering_packets_count::SuggestedBufferingPacketsCount;
use crate::ie::{marshal_ies, Ie, IeIterator, IeType};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UpdateBarWithinSessionReportResponse {
pub bar_id: BarId,
pub downlink_data_notification_delay: Option<DownlinkDataNotificationDelay>,
pub suggested_buffering_packets_count: Option<SuggestedBufferingPacketsCount>,
}
impl UpdateBarWithinSessionReportResponse {
pub fn new(bar_id: BarId) -> Self {
UpdateBarWithinSessionReportResponse {
bar_id,
downlink_data_notification_delay: None,
suggested_buffering_packets_count: None,
}
}
pub fn with_downlink_data_notification_delay(
mut self,
delay: DownlinkDataNotificationDelay,
) -> Self {
self.downlink_data_notification_delay = Some(delay);
self
}
pub fn with_suggested_buffering_packets_count(
mut self,
count: SuggestedBufferingPacketsCount,
) -> Self {
self.suggested_buffering_packets_count = Some(count);
self
}
pub fn marshal(&self) -> Vec<u8> {
let mut ies = Vec::new();
ies.push(self.bar_id.to_ie());
if let Some(ref delay) = self.downlink_data_notification_delay {
ies.push(Ie::new(
IeType::DownlinkDataNotificationDelay,
delay.marshal(),
));
}
if let Some(ref count) = self.suggested_buffering_packets_count {
ies.push(Ie::new(
IeType::DlBufferingSuggestedPacketCount,
count.marshal(),
));
}
marshal_ies(&ies)
}
pub fn unmarshal(payload: &[u8]) -> Result<Self, PfcpError> {
let mut bar_id = None;
let mut downlink_data_notification_delay = None;
let mut suggested_buffering_packets_count = None;
for ie_result in IeIterator::new(payload) {
let ie = ie_result?;
match ie.ie_type {
IeType::BarId => bar_id = Some(BarId::unmarshal(&ie.payload)?),
IeType::DownlinkDataNotificationDelay => {
downlink_data_notification_delay =
Some(DownlinkDataNotificationDelay::unmarshal(&ie.payload)?)
}
IeType::DlBufferingSuggestedPacketCount => {
suggested_buffering_packets_count =
Some(SuggestedBufferingPacketsCount::unmarshal(&ie.payload)?)
}
_ => (),
}
}
let bar_id = bar_id.ok_or(PfcpError::MissingMandatoryIe {
ie_type: IeType::BarId,
message_type: None,
parent_ie: Some(IeType::UpdateBarWithinSessionReportResponse),
})?;
Ok(UpdateBarWithinSessionReportResponse {
bar_id,
downlink_data_notification_delay,
suggested_buffering_packets_count,
})
}
pub fn to_ie(&self) -> Ie {
Ie::new(IeType::UpdateBarWithinSessionReportResponse, self.marshal())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_update_bar_within_session_report_response_marshal_unmarshal_minimal() {
let bar_id = BarId::new(5);
let update_bar = UpdateBarWithinSessionReportResponse::new(bar_id.clone());
let marshaled = update_bar.marshal();
let unmarshaled = UpdateBarWithinSessionReportResponse::unmarshal(&marshaled).unwrap();
assert_eq!(update_bar, unmarshaled);
assert_eq!(unmarshaled.bar_id, bar_id);
assert_eq!(unmarshaled.downlink_data_notification_delay, None);
assert_eq!(unmarshaled.suggested_buffering_packets_count, None);
}
#[test]
fn test_update_bar_within_session_report_response_marshal_unmarshal_complete() {
let bar_id = BarId::new(10);
let delay = DownlinkDataNotificationDelay::new(std::time::Duration::from_millis(1000)); let count = SuggestedBufferingPacketsCount::new(50);
let update_bar = UpdateBarWithinSessionReportResponse::new(bar_id.clone())
.with_downlink_data_notification_delay(delay.clone())
.with_suggested_buffering_packets_count(count.clone());
let marshaled = update_bar.marshal();
let unmarshaled = UpdateBarWithinSessionReportResponse::unmarshal(&marshaled).unwrap();
assert_eq!(update_bar, unmarshaled);
assert_eq!(unmarshaled.bar_id, bar_id);
assert_eq!(unmarshaled.downlink_data_notification_delay, Some(delay));
assert_eq!(unmarshaled.suggested_buffering_packets_count, Some(count));
}
#[test]
fn test_update_bar_within_session_report_response_to_ie() {
let bar_id = BarId::new(15);
let update_bar = UpdateBarWithinSessionReportResponse::new(bar_id);
let ie = update_bar.to_ie();
assert_eq!(ie.ie_type, IeType::UpdateBarWithinSessionReportResponse);
let unmarshaled = UpdateBarWithinSessionReportResponse::unmarshal(&ie.payload).unwrap();
assert_eq!(update_bar, unmarshaled);
}
#[test]
fn test_update_bar_within_session_report_response_unmarshal_missing_bar_id() {
let result = UpdateBarWithinSessionReportResponse::unmarshal(&[]);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::MissingMandatoryIe { .. }
));
}
#[test]
fn test_update_bar_within_session_report_response_unmarshal_invalid_data() {
let result = UpdateBarWithinSessionReportResponse::unmarshal(&[0xFF]);
assert!(result.is_err());
}
#[test]
fn test_update_bar_within_session_report_response_with_delay_only() {
let bar_id = BarId::new(7);
let delay = DownlinkDataNotificationDelay::new(std::time::Duration::from_millis(2500));
let update_bar = UpdateBarWithinSessionReportResponse::new(bar_id.clone())
.with_downlink_data_notification_delay(delay.clone());
let marshaled = update_bar.marshal();
let unmarshaled = UpdateBarWithinSessionReportResponse::unmarshal(&marshaled).unwrap();
assert_eq!(update_bar, unmarshaled);
assert_eq!(unmarshaled.bar_id, bar_id);
assert_eq!(unmarshaled.downlink_data_notification_delay, Some(delay));
assert_eq!(unmarshaled.suggested_buffering_packets_count, None);
}
}