use alloc::string::String;
use alloc::vec::Vec;
use zerodds_cdr::{BufferReader, BufferWriter};
use crate::profile_body::CdrError;
pub const IIOP_BI_DIR_TAG: u32 = 5;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BiDirIiopListenPoint {
pub host: String,
pub port: u16,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct BiDirIiopServiceContext {
pub listen_points: Vec<BiDirIiopListenPoint>,
}
impl BiDirIiopServiceContext {
pub fn encode(&self, w: &mut BufferWriter) -> Result<(), CdrError> {
let n = u32::try_from(self.listen_points.len()).map_err(|_| CdrError::Overflow)?;
w.write_u32(n)?;
for lp in &self.listen_points {
w.write_string(&lp.host)?;
w.write_u16(lp.port)?;
}
Ok(())
}
pub fn decode(r: &mut BufferReader<'_>) -> Result<Self, CdrError> {
let n = r.read_u32()? as usize;
let mut listen_points = Vec::with_capacity(n.min(32));
for _ in 0..n {
let host = r.read_string()?;
let port = r.read_u16()?;
listen_points.push(BiDirIiopListenPoint { host, port });
}
Ok(Self { listen_points })
}
}
#[cfg(test)]
#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
mod tests {
use super::*;
use zerodds_cdr::Endianness;
#[test]
fn bidir_tag_value_matches_spec() {
assert_eq!(IIOP_BI_DIR_TAG, 5);
}
#[test]
fn empty_context_round_trip() {
let c = BiDirIiopServiceContext::default();
let mut w = BufferWriter::new(Endianness::Big);
c.encode(&mut w).unwrap();
let bytes = w.into_bytes();
let mut r = BufferReader::new(&bytes, Endianness::Big);
assert_eq!(BiDirIiopServiceContext::decode(&mut r).unwrap(), c);
}
#[test]
fn multi_listen_point_round_trip() {
let c = BiDirIiopServiceContext {
listen_points: alloc::vec![
BiDirIiopListenPoint {
host: "client-a.lab".into(),
port: 8080,
},
BiDirIiopListenPoint {
host: "10.0.0.42".into(),
port: 7000,
},
],
};
let mut w = BufferWriter::new(Endianness::Little);
c.encode(&mut w).unwrap();
let bytes = w.into_bytes();
let mut r = BufferReader::new(&bytes, Endianness::Little);
let decoded = BiDirIiopServiceContext::decode(&mut r).unwrap();
assert_eq!(decoded, c);
}
}