| //! ASN.1 DER headers. | |
| use crate::{Decode, DerOrd, Encode, ErrorKind, Length, Reader, Result, Tag, Writer}; | |
| use core::cmp::Ordering; | |
| /// ASN.1 DER headers: tag + length component of TLV-encoded values | |
| #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
| pub struct Header { | |
| /// Tag representing the type of the encoded value | |
| pub tag: Tag, | |
| /// Length of the encoded value | |
| pub length: Length, | |
| } | |
| impl Header { | |
| /// Create a new [`Header`] from a [`Tag`] and a specified length. | |
| /// | |
| /// Returns an error if the length exceeds the limits of [`Length`]. | |
| pub fn new(tag: Tag, length: impl TryInto<Length>) -> Result<Self> { | |
| let length = length.try_into().map_err(|_| ErrorKind::Overflow)?; | |
| Ok(Self { tag, length }) | |
| } | |
| } | |
| impl<'a> Decode<'a> for Header { | |
| fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Header> { | |
| let tag = Tag::decode(reader)?; | |
| let length = Length::decode(reader).map_err(|e| { | |
| if e.kind() == ErrorKind::Overlength { | |
| ErrorKind::Length { tag }.into() | |
| } else { | |
| e | |
| } | |
| })?; | |
| Ok(Self { tag, length }) | |
| } | |
| } | |
| impl Encode for Header { | |
| fn encoded_len(&self) -> Result<Length> { | |
| self.tag.encoded_len()? + self.length.encoded_len()? | |
| } | |
| fn encode(&self, writer: &mut dyn Writer) -> Result<()> { | |
| self.tag.encode(writer)?; | |
| self.length.encode(writer) | |
| } | |
| } | |
| impl DerOrd for Header { | |
| fn der_cmp(&self, other: &Self) -> Result<Ordering> { | |
| match self.tag.der_cmp(&other.tag)? { | |
| Ordering::Equal => self.length.der_cmp(&other.length), | |
| ordering => Ok(ordering), | |
| } | |
| } | |
| } |