diff --git a/src/attribute.rs b/src/attribute.rs index 37343e3..3ab80a7 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -4,7 +4,7 @@ use std::string::FromUtf8Error; use chrono::{DateTime, Utc, TimeZone}; -pub struct Attribute(Vec); +pub struct Attribute(pub(crate) Vec); impl Attribute { pub fn from_integer32(v: &u32) -> Self { diff --git a/src/attributes.rs b/src/attributes.rs new file mode 100644 index 0000000..91cb6fd --- /dev/null +++ b/src/attributes.rs @@ -0,0 +1,50 @@ +use crate::attribute::Attribute; + +pub type Type = u8; + +pub const TYPE_INVALID: Type = 1; + +pub struct AVP { + typ: Type, + attribute: Attribute, +} + +pub struct Attributes(Vec); + +impl Attributes { + pub fn parse_attributes(bs: &Vec) -> Result { + let mut i = 0; + let mut attrs = Vec::new(); + + while bs.len() < i { + if bs[i..].len() < 2 { + return Err("short buffer".to_owned()); + } + + let length = bs[i + 1] as usize; + if length > bs[i..].len() || length < 2 || length > 255 { + return Err("invalid attribute length".to_owned()); + } + + attrs.push(AVP { + typ: bs[i + 0], + attribute: if length > 2 { + Attribute(bs[i + 2..].to_vec()) + } else { + Attribute(vec![]) + }, + }); + + i += length; + } + + Ok(Attributes(attrs)) + } + + pub fn add(&mut self, typ: Type, attribute: Attribute) { + self.0.push(AVP { + typ, + attribute, + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 37d8952..282021d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod code; pub mod attribute; +pub mod attributes;