use crate::error::Result;
use crate::metadata::{MetaData, MetaDataRef};
use mdflib_sys as ffi;
use std::ffi::{CStr, CString};
use std::marker::PhantomData;
use std::ops::Deref;
use std::os::raw::c_char;
#[derive(Debug, Clone, Copy)]
pub struct AttachmentRef<'a> {
pub(crate) inner: *const ffi::IAttachment,
_marker: PhantomData<&'a ()>,
}
impl std::fmt::Display for AttachmentRef<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Attachment {{ index: {}, creator_index: {}, embedded: {}, compressed: {}, md5: {:?}, filename: {}, file_type: {} }}",
self.get_index(),
self.get_creator_index(),
self.get_embedded(),
self.get_compressed(),
self.get_md5(),
self.get_filename(),
self.get_file_type()
)
}
}
impl<'a> AttachmentRef<'a> {
#[allow(dead_code)]
pub(crate) fn new(inner: *const ffi::IAttachment) -> Self {
Self {
inner,
_marker: PhantomData,
}
}
pub fn get_index(&self) -> u64 {
unsafe { ffi::AttachmentGetIndex(self.inner) }
}
pub fn get_creator_index(&self) -> u16 {
unsafe { ffi::AttachmentGetCreatorIndex(self.inner) }
}
pub fn get_embedded(&self) -> bool {
unsafe { ffi::AttachmentGetEmbedded(self.inner) }
}
pub fn get_compressed(&self) -> bool {
unsafe { ffi::AttachmentGetCompressed(self.inner) }
}
pub fn get_md5(&self) -> Option<String> {
unsafe {
let mut buf = vec![0 as c_char; 33]; if ffi::AttachmentGetMd5(self.inner, buf.as_mut_ptr(), buf.len()) {
Some(CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned())
} else {
None
}
}
}
pub fn get_filename(&self) -> String {
unsafe {
let mut len = ffi::AttachmentGetFileName(self.inner, std::ptr::null_mut(), 0);
if len == 0 {
return String::new();
}
len += 1; let mut buf = vec![0 as c_char; len as usize];
ffi::AttachmentGetFileName(self.inner, buf.as_mut_ptr(), len);
CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned()
}
}
pub fn get_file_type(&self) -> String {
unsafe {
let mut len = ffi::AttachmentGetFileType(self.inner, std::ptr::null_mut(), 0);
if len == 0 {
return String::new();
}
len += 1; let mut buf = vec![0 as c_char; len as usize];
ffi::AttachmentGetFileType(self.inner, buf.as_mut_ptr(), len);
CStr::from_ptr(buf.as_ptr()).to_string_lossy().into_owned()
}
}
pub fn get_metadata(&self) -> Option<MetaDataRef<'a>> {
unsafe {
let metadata = ffi::AttachmentGetMetaData(self.inner);
if metadata.is_null() {
None
} else {
Some(MetaDataRef::new(metadata))
}
}
}
}
#[derive(Debug)]
pub struct Attachment<'a> {
pub(crate) inner: *mut ffi::IAttachment,
inner_ref: AttachmentRef<'a>,
}
impl<'a> Attachment<'a> {
#[allow(dead_code)]
pub(crate) fn new(inner: *mut ffi::IAttachment) -> Self {
Self {
inner,
inner_ref: AttachmentRef::new(inner),
}
}
pub fn set_creator_index(&mut self, index: u16) {
unsafe {
ffi::AttachmentSetCreatorIndex(self.inner, index);
}
}
pub fn set_embedded(&mut self, embedded: bool) {
unsafe {
ffi::AttachmentSetEmbedded(self.inner, embedded);
}
}
pub fn set_compressed(&mut self, compressed: bool) {
unsafe {
ffi::AttachmentSetCompressed(self.inner, compressed);
}
}
pub fn set_filename(&mut self, name: &str) -> Result<()> {
let c_name = CString::new(name)?;
unsafe {
ffi::AttachmentSetFileName(self.inner, c_name.as_ptr());
}
Ok(())
}
pub fn set_file_type(&mut self, file_type: &str) -> Result<()> {
let c_type = CString::new(file_type)?;
unsafe {
ffi::AttachmentSetFileType(self.inner, c_type.as_ptr());
}
Ok(())
}
pub fn create_metadata(&mut self) -> Option<MetaData<'a>> {
unsafe {
let metadata = ffi::AttachmentCreateMetaData(self.inner);
if metadata.is_null() {
None
} else {
Some(MetaData::new(metadata))
}
}
}
}
impl<'a> Deref for Attachment<'a> {
type Target = AttachmentRef<'a>;
fn deref(&self) -> &Self::Target {
&self.inner_ref
}
}