use std::fmt::Write;
use crate::message::attributes::*;
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg(feature = "serialization")]
#[derive(Serialize, Deserialize)]
pub struct BgpAttrSet {
pub asn: u32,
pub attrs: Vec<BgpAttrItem>,
}
impl BgpAttrSet {
pub fn decode_from(peer: &BgpSessionParams, buf: &[u8]) -> Result<BgpAttrSet, BgpError> {
if !peer.has_as32bit {
return Err(BgpError::static_str(
"Invalid BgpAttrSet without 32-bit AS support",
));
}
if buf.len() < 4 {
return Err(BgpError::static_str("Invalid BgpAttrSet buffer length"));
}
let mut attrs = Vec::<BgpAttrItem>::new();
let mut curpos = 4;
while curpos < buf.len() {
let flags = buf[curpos];
let tc = buf[curpos + 1];
let attrlen = if (flags & 16) > 0 {
curpos += 4;
getn_u16(&buf[(curpos - 2)..curpos]) as usize
} else {
curpos += 3;
buf[curpos - 1] as usize
};
if (curpos + attrlen) > buf.len() {
return Err(BgpError::static_str("Protocol error"));
};
attrs.push(BgpAttrItem::decode_from(
peer,
tc,
flags,
attrlen,
&buf[curpos..(curpos + attrlen)],
)?);
curpos += attrlen;
}
Ok(BgpAttrSet {
asn: getn_u32(buf),
attrs,
})
}
}
impl std::fmt::Debug for BgpAttrSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BgpAttrSet")
.field("asn", &self.asn)
.field("attrs", &self.attrs)
.finish()
}
}
impl std::fmt::Display for BgpAttrSet {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "AS{}(", self.asn)?;
crate::util::fmt_vec(self.attrs.iter(), ',', f)?;
f.write_char(')')
}
}
impl BgpAttr for BgpAttrSet {
fn attr(&self) -> BgpAttrParams {
BgpAttrParams {
typecode: 128,
flags: 224,
}
}
fn encode_to(&self, _peer: &BgpSessionParams, _buf: &mut [u8]) -> Result<usize, BgpError> {
unimplemented!()
}
}