#[cfg(any(feature = "payload", feature = "manifest", feature = "restore_info"))]
use der::{asn1::Ia5StringRef, ErrorKind, Reader};
#[cfg(feature = "payload")]
use {
core::ops::Add,
der::{asn1::ContextSpecific, Decode, Encode, Header, Length, TagNumber, Writer},
};
#[cfg(any(feature = "payload", feature = "manifest", feature = "restore_info"))]
pub fn decode_and_check_magic<'a, R: Reader<'a>>(
decoder: &mut R,
expected: &[u8; 4],
) -> der::Result<()> {
let position = decoder.position();
let magic = decoder.decode::<Ia5StringRef<'a>>()?;
if magic.as_bytes() == expected {
Ok(())
} else {
Err(ErrorKind::Value {
tag: der::Tag::Ia5String,
}
.at(position))
}
}
#[cfg(feature = "payload")]
pub fn decode_opt_field<'a, R: Reader<'a>, T: Decode<'a>>(
decoder: &mut R,
expected_tag: der::Tag,
) -> der::Result<Option<T>> {
match decoder.peek_tag() {
Ok(tag) if tag == expected_tag => decoder.decode::<T>().map(Some),
Ok(_) => Ok(None),
Err(e) if matches!(e.kind(), ErrorKind::Incomplete { .. }) => Ok(None),
Err(e) => Err(e),
}
}
#[cfg(feature = "payload")]
pub fn decode_opt_context_specific_field<'a, R: Reader<'a>, T: Decode<'a>>(
decoder: &mut R,
tag_number: TagNumber,
constructed: bool,
) -> der::Result<Option<T>> {
let field: Option<ContextSpecific<T>> = decode_opt_field(
decoder,
der::Tag::ContextSpecific {
constructed,
number: tag_number,
},
)?;
Ok(field.map(|f| f.value))
}
#[cfg(feature = "payload")]
pub fn encoded_opt_context_specific_field_len<T: Encode>(
field: Option<&T>,
tag_number: TagNumber,
constructed: bool,
) -> der::Result<Length> {
if let Some(field) = field {
let tag = der::Tag::ContextSpecific {
constructed,
number: tag_number,
};
let length = field.encoded_len()?;
let header = Header { tag, length };
header.encoded_len()?.add(length)
} else {
Ok(Length::ZERO)
}
}
#[cfg(feature = "payload")]
pub fn encode_opt_context_specific_field<W: Writer, T: Encode>(
writer: &mut W,
field: Option<&T>,
tag_number: TagNumber,
constructed: bool,
) -> der::Result<()> {
if let Some(field) = field {
let tag = der::Tag::ContextSpecific {
constructed,
number: tag_number,
};
let length = field.encoded_len()?;
let header = Header { tag, length };
header.encode(writer)?;
field.encode(writer)
} else {
Ok(())
}
}
#[cfg(feature = "property")]
pub fn shift_error_position(error: der::Error, position: der::Length) -> der::Error {
if let Some(cur_position) = error.position() {
(position + cur_position)
.map(|position| error.kind().at(position))
.unwrap_or_else(|e| e)
} else {
error
}
}