use std::marker::PhantomData;
use lief_ffi as ffi;
use crate::common::{FromFFI, into_optional};
use crate::pe::Algorithms;
use crate::to_slice;
pub struct ContentInfo<'a> {
ptr: cxx::UniquePtr<ffi::PE_ContentInfo>,
_owner: PhantomData<&'a ffi::PE_Signature>,
}
impl ContentInfo<'_> {
pub fn content_type(&self) -> String {
self.ptr.content_type().to_string()
}
pub fn value(&self) -> Option<Content<'_>> {
into_optional(self.ptr.value())
}
pub fn digest(&self) -> Vec<u8> {
Vec::from(self.ptr.digest().as_slice())
}
pub fn digest_algorithm(&self) -> Algorithms {
Algorithms::from(self.ptr.digest_algorithm())
}
}
impl std::fmt::Debug for ContentInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ContentInfo")
.field("content_type", &self.content_type())
.finish()
}
}
impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
ContentInfo {
ptr,
_owner: PhantomData,
}
}
}
#[derive(Debug)]
pub enum Content<'a> {
SpcIndirectData(SpcIndirectData<'a>),
PKCS9TSTInfo(PKCS9TSTInfo<'a>),
Generic(Generic<'a>),
}
impl<'a> FromFFI<ffi::PE_ContentInfo_Content> for Content<'a> {
fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ContentInfo_Content>) -> Self {
unsafe {
let content_ref = ffi_entry.as_ref().unwrap();
if ffi::PE_SpcIndirectData::classof(content_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
type To = cxx::UniquePtr<ffi::PE_SpcIndirectData>;
std::mem::transmute::<From, To>(ffi_entry)
};
Content::SpcIndirectData(SpcIndirectData::from_ffi(raw))
} else if ffi::PE_PKCS9TSTInfo::classof(content_ref) {
let raw = {
type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
type To = cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>;
std::mem::transmute::<From, To>(ffi_entry)
};
Content::PKCS9TSTInfo(PKCS9TSTInfo::from_ffi(raw))
} else {
let raw = {
type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
type To = cxx::UniquePtr<ffi::PE_GenericContent>;
std::mem::transmute::<From, To>(ffi_entry)
};
Content::Generic(Generic::from_ffi(raw))
}
}
}
}
pub trait ContentTrait {
#[doc(hidden)]
fn as_generic(&self) -> &ffi::PE_ContentInfo_Content;
fn content_type(&self) -> String {
self.as_generic().content_type().to_string()
}
}
pub struct SpcIndirectData<'a> {
ptr: cxx::UniquePtr<ffi::PE_SpcIndirectData>,
_owner: PhantomData<&'a ffi::PE_ContentInfo>,
}
impl SpcIndirectData<'_> {
pub fn file(&self) -> String {
self.ptr.file().to_string()
}
pub fn url(&self) -> String {
self.ptr.url().to_string()
}
pub fn digest(&self) -> &[u8] {
to_slice!(self.ptr.digest());
}
pub fn digest_algorithm(&self) -> Algorithms {
Algorithms::from(self.ptr.digest_algorithm())
}
}
impl std::fmt::Debug for SpcIndirectData<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SpcIndirectData")
.field("file", &self.file())
.field("url", &self.url())
.field("digest_algorithm", &self.digest_algorithm())
.finish()
}
}
impl FromFFI<ffi::PE_SpcIndirectData> for SpcIndirectData<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_SpcIndirectData>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl ContentTrait for SpcIndirectData<'_> {
fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
self.ptr.as_ref().unwrap().as_ref()
}
}
pub struct PKCS9TSTInfo<'a> {
ptr: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>,
_owner: PhantomData<&'a ffi::PE_ContentInfo>,
}
impl PKCS9TSTInfo<'_> {
}
impl std::fmt::Debug for PKCS9TSTInfo<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PKCS9TSTInfo").finish()
}
}
impl FromFFI<ffi::PE_PKCS9TSTInfo> for PKCS9TSTInfo<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl ContentTrait for PKCS9TSTInfo<'_> {
fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
self.ptr.as_ref().unwrap().as_ref()
}
}
pub struct Generic<'a> {
ptr: cxx::UniquePtr<ffi::PE_GenericContent>,
_owner: PhantomData<&'a ffi::PE_ContentInfo>,
}
impl Generic<'_> {
pub fn raw(&self) -> &[u8] {
to_slice!(self.ptr.raw());
}
pub fn oid(&self) -> String {
self.ptr.oid().to_string()
}
}
impl std::fmt::Debug for Generic<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Generic").finish()
}
}
impl FromFFI<ffi::PE_GenericContent> for Generic<'_> {
fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_GenericContent>) -> Self {
Self {
ptr: cmd,
_owner: PhantomData,
}
}
}
impl ContentTrait for Generic<'_> {
fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
self.ptr.as_ref().unwrap().as_ref()
}
}