use crate::error::PfcpError;
use crate::ie::{Ie, IeType};
use crate::message::{header::Header, Message, MsgType};
use crate::types::{Seid, SequenceNumber};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VersionNotSupportedResponse {
pub header: Header,
pub ies: Vec<Ie>, }
impl VersionNotSupportedResponse {
pub fn new(seq: impl Into<SequenceNumber>) -> Self {
let mut header = Header::new(MsgType::VersionNotSupportedResponse, false, 0, seq);
header.length = 4;
VersionNotSupportedResponse {
header,
ies: Vec::new(),
}
}
pub fn new_with_ies(seq: impl Into<SequenceNumber>, ies: Vec<Ie>) -> Self {
let mut payload_len = 0;
for ie in &ies {
payload_len += ie.len();
}
let mut header = Header::new(MsgType::VersionNotSupportedResponse, false, 0, seq);
header.length = 4 + payload_len;
VersionNotSupportedResponse { header, ies }
}
}
impl Message for VersionNotSupportedResponse {
fn msg_type(&self) -> MsgType {
MsgType::VersionNotSupportedResponse
}
fn marshal(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(self.marshaled_size());
self.marshal_into(&mut buf);
buf
}
fn marshal_into(&self, buf: &mut Vec<u8>) {
buf.reserve(self.marshaled_size());
self.header.marshal_into(buf);
for ie in &self.ies {
ie.marshal_into(buf);
}
}
fn marshaled_size(&self) -> usize {
let mut size = self.header.len() as usize;
for ie in &self.ies {
size += ie.len() as usize;
}
size
}
fn unmarshal(buf: &[u8]) -> Result<Self, PfcpError>
where
Self: Sized,
{
let header = Header::unmarshal(buf)?;
let mut ies = Vec::new();
let mut cursor = header.len() as usize;
while cursor < buf.len() {
let ie = Ie::unmarshal(&buf[cursor..])?;
let ie_len = ie.len() as usize;
ies.push(ie);
cursor += ie_len;
}
Ok(VersionNotSupportedResponse { header, ies })
}
fn seid(&self) -> Option<Seid> {
if self.header.has_seid {
Some(self.header.seid)
} else {
None
}
}
fn sequence(&self) -> SequenceNumber {
self.header.sequence_number
}
fn set_sequence(&mut self, seq: SequenceNumber) {
self.header.sequence_number = seq;
}
fn ies(&self, ie_type: IeType) -> crate::message::IeIter<'_> {
use crate::message::IeIter;
IeIter::generic(&self.ies, ie_type)
}
fn all_ies(&self) -> Vec<&Ie> {
self.ies.iter().collect()
}
}
#[derive(Debug, Default)]
pub struct VersionNotSupportedResponseBuilder {
sequence: SequenceNumber,
ies: Vec<Ie>,
}
impl VersionNotSupportedResponseBuilder {
pub fn new(sequence: impl Into<SequenceNumber>) -> Self {
Self {
sequence: sequence.into(),
ies: Vec::new(),
}
}
pub fn ie(mut self, ie: Ie) -> Self {
self.ies.push(ie);
self
}
pub fn ies(mut self, mut ies: Vec<Ie>) -> Self {
self.ies.append(&mut ies);
self
}
pub fn build(self) -> VersionNotSupportedResponse {
if self.ies.is_empty() {
VersionNotSupportedResponse::new(self.sequence)
} else {
VersionNotSupportedResponse::new_with_ies(self.sequence, self.ies)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version_not_supported_response_marshal_unmarshal_empty() {
let original = VersionNotSupportedResponse::new(123);
let marshaled = original.marshal();
let unmarshaled = VersionNotSupportedResponse::unmarshal(&marshaled).unwrap();
assert_eq!(
original.header.message_type,
unmarshaled.header.message_type
);
assert_eq!(
original.header.sequence_number,
unmarshaled.header.sequence_number
);
assert_eq!(original.header.length, unmarshaled.header.length);
assert_eq!(original.ies.len(), unmarshaled.ies.len());
}
#[test]
fn test_version_not_supported_response_with_ies() {
let ies = vec![
Ie::new(IeType::OffendingIe, vec![0x00, 0x01]), Ie::new(IeType::Unknown, vec![0xFF, 0xFF, 0xFF]), ];
let original = VersionNotSupportedResponse::new_with_ies(456, ies.clone());
let marshaled = original.marshal();
let unmarshaled = VersionNotSupportedResponse::unmarshal(&marshaled).unwrap();
assert_eq!(
original.header.message_type,
unmarshaled.header.message_type
);
assert_eq!(
original.header.sequence_number,
unmarshaled.header.sequence_number
);
assert_eq!(original.ies.len(), unmarshaled.ies.len());
assert_eq!(original.ies, unmarshaled.ies);
}
#[test]
fn test_version_not_supported_response_ies() {
let ies = vec![Ie::new(IeType::OffendingIe, vec![0x00, 0x01])];
let message = VersionNotSupportedResponse::new_with_ies(123, ies);
assert!(message.ies(IeType::OffendingIe).next().is_some());
assert!(message.ies(IeType::NodeId).next().is_none());
}
#[test]
fn test_version_not_supported_response_header_validation() {
let message = VersionNotSupportedResponse::new(789);
assert_eq!(message.msg_type(), MsgType::VersionNotSupportedResponse);
assert_eq!(*message.sequence(), 789);
assert_eq!(message.seid(), None); assert_eq!(message.version(), 1); }
#[test]
fn test_version_not_supported_response_round_trip() {
let original = VersionNotSupportedResponse::new(999);
let marshaled = original.marshal();
let unmarshaled = VersionNotSupportedResponse::unmarshal(&marshaled).unwrap();
assert_eq!(original, unmarshaled);
}
#[test]
fn test_version_not_supported_response_builder_minimal() {
let response = VersionNotSupportedResponseBuilder::new(12345).build();
assert_eq!(*response.sequence(), 12345);
assert_eq!(response.msg_type(), MsgType::VersionNotSupportedResponse);
assert!(response.ies.is_empty());
assert_eq!(response.seid(), None);
}
#[test]
fn test_version_not_supported_response_builder_with_ie() {
let offending_ie = Ie::new(IeType::OffendingIe, vec![0x00, 0x01]);
let response = VersionNotSupportedResponseBuilder::new(12345)
.ie(offending_ie.clone())
.build();
assert_eq!(*response.sequence(), 12345);
assert_eq!(response.ies.len(), 1);
assert_eq!(response.ies[0], offending_ie);
}
#[test]
fn test_version_not_supported_response_builder_with_multiple_ies() {
let ie1 = Ie::new(IeType::OffendingIe, vec![0x00, 0x01]);
let ie2 = Ie::new(IeType::Unknown, vec![0x02, 0x03]);
let ie3 = Ie::new(IeType::Unknown, vec![0x04, 0x05, 0x06]);
let response = VersionNotSupportedResponseBuilder::new(98765)
.ie(ie1.clone())
.ies(vec![ie2.clone(), ie3.clone()])
.build();
assert_eq!(*response.sequence(), 98765);
assert_eq!(response.ies.len(), 3);
assert_eq!(response.ies[0], ie1);
assert_eq!(response.ies[1], ie2);
assert_eq!(response.ies[2], ie3);
}
#[test]
fn test_version_not_supported_response_builder_roundtrip() {
let ie1 = Ie::new(IeType::OffendingIe, vec![0xFF, 0x01]);
let ie2 = Ie::new(IeType::Unknown, vec![0xDE, 0xAD, 0xBE, 0xEF]);
let original = VersionNotSupportedResponseBuilder::new(54321)
.ie(ie1)
.ie(ie2)
.build();
let marshaled = original.marshal();
let unmarshaled = VersionNotSupportedResponse::unmarshal(&marshaled).unwrap();
assert_eq!(original, unmarshaled);
}
#[test]
fn test_version_not_supported_response_builder_empty_vs_with_ies() {
let empty_response = VersionNotSupportedResponseBuilder::new(111).build();
let ie = Ie::new(IeType::OffendingIe, vec![0x01]);
let with_ies_response = VersionNotSupportedResponseBuilder::new(222).ie(ie).build();
assert!(empty_response.ies.is_empty());
assert_eq!(with_ies_response.ies.len(), 1);
assert_ne!(empty_response.sequence(), with_ies_response.sequence());
}
}