use crate::tag::{Tag, TagClass};
use crate::error as asn1err;
use crate::length::{build_length, parse_length};
pub trait Asn1Object: Sized + Default {
fn tag() -> Tag;
fn build_value(&self) -> Vec<u8>;
fn parse_value(&mut self, raw: &[u8]) -> asn1err::Result<()>;
fn build(&self) -> Vec<u8> {
let mut encoded = Self::tag().build();
let mut encoded_length_value = self.build_length_value();
encoded.append(&mut encoded_length_value);
return encoded;
}
fn build_length_value(&self) -> Vec<u8> {
let mut encoded_value = self.build_value();
let mut encoded_length = build_length(encoded_value.len());
let mut encoded = Vec::new();
encoded.append(&mut encoded_length);
encoded.append(&mut encoded_value);
return encoded;
}
fn parse(raw: &[u8]) -> asn1err::Result<(&[u8], Self)> {
let (raw, parsed_tag) = Tag::parse(raw)?;
if parsed_tag != Self::tag() {
return Err(asn1err::Error::UnmatchedTag(TagClass::Universal))?;
}
return Self::parse_length_value(raw);
}
fn parse_length_value(raw: &[u8]) -> asn1err::Result<(&[u8], Self)> {
let (raw, length) = parse_length(raw)?;
if length > raw.len() {
return Err(asn1err::Error::NoDataForLength)?;
}
let (raw_value, raw) = raw.split_at(length);
let mut asn1obj = Self::default();
asn1obj.parse_value(raw_value)?;
return Ok((raw, asn1obj));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Default)]
struct TestObject {
}
impl TestObject {}
impl Asn1Object for TestObject {
fn tag() -> Tag {
return Tag::default();
}
fn build_value(&self) -> Vec<u8> {
return vec![];
}
fn parse_value(&mut self, _raw: &[u8]) -> asn1err::Result<()> {
return Ok(());
}
}
#[should_panic (expected = "NoDataForLength")]
#[test]
fn test_parse_with_excesive_length_for_data() {
TestObject::parse(&[0x0, 0x3, 0x0]).unwrap();
}
}