use {
super::{Image, ImageIndex, Wim},
crate::{
error::result_from_raw,
string::{OptionalAsFfiExt, TStr},
sys,
wim::new_image_index,
Error,
},
std::{fmt::Debug, marker::PhantomData, mem::MaybeUninit, num::NonZero, ptr::null},
uuid::Uuid,
};
impl Wim {
#[doc(alias = "wimlib_add_empty_image")]
pub fn add_empty_image(&self, name: &TStr) -> Result<ImageIndex, Error> {
let mut out_index = 0;
result_from_raw(unsafe {
sys::wimlib_add_empty_image(self.wimstruct, name.as_ptr(), &mut out_index)
})?;
let index = new_image_index(out_index).expect("FFI returned no image");
Ok(index)
}
#[doc(alias = "wimlib_add_image")]
pub fn add_image(
&self,
source: &TStr,
name: &TStr,
config_file: Option<&TStr>,
add_flags: AddFlags,
) -> Result<(), Error> {
let config_file_ptr = config_file.map(TStr::as_ptr).unwrap_or(null());
result_from_raw(unsafe {
sys::wimlib_add_image(
self.wimstruct,
source.as_ptr(),
name.as_ptr(),
config_file_ptr,
add_flags.bits(),
)
})
}
#[doc(alias = "wimlib_add_image_multisource")]
pub fn add_image_multisource(
&self,
source_target_pairs: &[SourceTargetPair],
name: &TStr,
config_file: Option<&TStr>,
add_flags: AddFlags,
) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_add_image_multisource(
self.wimstruct,
source_target_pairs.as_ptr().cast(),
source_target_pairs.len(),
name.as_ptr(),
config_file.as_nullable_ptr(),
add_flags.bits(),
)
})
}
pub fn set_info(&self, info: SetInfo) -> Result<(), Error> {
let mut wim_info: sys::wimlib_wim_info = unsafe { MaybeUninit::zeroed().assume_init() };
let mut which = 0;
if let Some(flag) = info.readonly_flag {
wim_info.set_is_marked_readonly(flag as _);
which |= sys::WIMLIB_CHANGE_READONLY_FLAG;
}
if let Some(guid) = info.guid {
wim_info.guid = guid.into_bytes();
which |= sys::WIMLIB_CHANGE_GUID;
}
if let Some(boot_index) = info.boot_index {
let boot_index = boot_index.map(NonZero::get).unwrap_or_default();
wim_info.boot_index = boot_index;
which |= sys::WIMLIB_CHANGE_BOOT_INDEX;
}
if let Some(rpfix_flag) = info.rpfix_flag {
wim_info.set_has_rpfix(rpfix_flag as _);
which |= sys::WIMLIB_CHANGE_RPFIX_FLAG;
}
result_from_raw(unsafe {
sys::wimlib_set_wim_info(self.wimstruct, &wim_info, which as i32)
})
}
}
#[repr(transparent)]
pub struct SourceTargetPair<'a> {
inner: sys::wimlib_capture_source,
_borrow: PhantomData<(&'a TStr, &'a TStr)>,
}
impl<'a> SourceTargetPair<'a> {
pub fn new(source: &'a TStr, target: &'a TStr) -> Self {
let inner = sys::wimlib_capture_source {
fs_source_path: source.as_ptr().cast_mut(),
wim_target_path: target.as_ptr().cast_mut(),
reserved: 0,
};
Self {
inner,
_borrow: PhantomData,
}
}
pub fn array<const N: usize>(pairs: [(&'a TStr, &'a TStr); N]) -> [Self; N] {
pairs.map(|(src, target)| SourceTargetPair::new(src, target))
}
}
impl Image<'_> {
#[doc(alias = "wimlib_add_tree")]
pub fn add_tree(
&self,
fs_source_path: &TStr,
wim_target_path: &TStr,
add_flags: AddFlags,
) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_add_tree(
self.wimstruct,
self.ffi_index(),
fs_source_path.as_ptr(),
wim_target_path.as_ptr(),
add_flags.bits(),
)
})
}
#[doc(alias = "wimlib_delete_image")]
pub fn delete_self(self) -> Result<(), Error> {
result_from_raw(unsafe { sys::wimlib_delete_image(self.wimstruct, self.ffi_index()) })
}
#[doc(alias = "wimlib_delete_path")]
pub fn delete_path(&self, path: &TStr, delete_flags: DeleteFlags) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_delete_path(
self.wimstruct,
self.ffi_index(),
path.as_ptr(),
delete_flags.bits(),
)
})
}
#[doc(alias = "wimlib_export_image")]
pub fn export(
&self,
dest_wim: &Wim,
dest_new_name: Option<&TStr>,
dest_new_description: Option<&TStr>,
export_flags: ExportFlags,
) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_export_image(
self.wimstruct,
self.ffi_index(),
dest_wim.wimstruct,
dest_new_name.as_nullable_ptr(),
dest_new_description.as_nullable_ptr(),
export_flags.bits(),
)
})
}
#[doc(alias = "wimlib_reference_template_image")]
pub fn reference_template_image(
&self,
template_image: &Image,
flags: ReferenceTemplateImageFlags,
) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_reference_template_image(
self.wimstruct,
self.ffi_index(),
template_image.wimstruct,
template_image.ffi_index(),
flags.bits(),
)
})
}
#[doc(alias = "wimlib_rename_path")]
pub fn rename_path(&self, from: &TStr, to: &TStr) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_rename_path(self.wimstruct, self.ffi_index(), from.as_ptr(), to.as_ptr())
})
}
#[doc(alias = "wimlib_set_image_property")]
pub fn set_property(&self, name: &TStr, value: Option<&TStr>) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_set_image_property(
self.wimstruct,
self.ffi_index(),
name.as_ptr(),
value.as_nullable_ptr(),
)
})
}
pub fn update(
&self,
commands: &[UpdateCommand],
update_flags: UpdateFlags,
) -> Result<(), Error> {
result_from_raw(unsafe {
sys::wimlib_update_image(
self.wimstruct,
self.ffi_index(),
commands.as_ptr().cast(),
commands.len(),
update_flags.bits(),
)
})
}
}
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct UpdateCommand<'a> {
inner: sys::wimlib_update_command,
_borrows: PhantomData<&'a TStr>,
}
impl Debug for UpdateCommand<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.inner.op {
sys::wimlib_update_op_WIMLIB_UPDATE_OP_ADD => unsafe {
let variant = &self.inner.__bindgen_anon_1.add;
f.debug_struct("Add")
.field(
"add_flags",
&AddFlags::from_bits_truncate(variant.add_flags),
)
.field("fs_source_path", &TStr::from_ptr(variant.fs_source_path))
.field("wim_target_path", &TStr::from_ptr(variant.wim_target_path))
.field("config_file", &TStr::from_ptr_optional(variant.config_file))
.finish()
},
sys::wimlib_update_op_WIMLIB_UPDATE_OP_DELETE => unsafe {
let variant = &self.inner.__bindgen_anon_1.delete_;
f.debug_struct("Delete")
.field("wim_path", &TStr::from_ptr(variant.wim_path))
.field(
"delete_flags",
&DeleteFlags::from_bits_truncate(variant.delete_flags),
)
.finish()
},
sys::wimlib_update_op_WIMLIB_UPDATE_OP_RENAME => unsafe {
let variant = &self.inner.__bindgen_anon_1.rename;
f.debug_struct("Rename")
.field("wim_source_path", &TStr::from_ptr(variant.wim_source_path))
.field("wim_target_path", &TStr::from_ptr(variant.wim_target_path))
.field(
"rename_flags",
&RenameFlags::from_bits_truncate(variant.rename_flags),
)
.finish()
},
tag => unreachable!("Unknown tag: {tag}"),
}
}
}
impl PartialEq for UpdateCommand<'_> {
fn eq(&self, other: &Self) -> bool {
if self.inner.op != other.inner.op {
return false;
}
match self.inner.op {
sys::wimlib_update_op_WIMLIB_UPDATE_OP_ADD => unsafe {
let this = &self.inner.__bindgen_anon_1.add;
let other = &self.inner.__bindgen_anon_1.add;
this.add_flags == other.add_flags
&& TStr::from_ptr_optional(this.config_file)
== TStr::from_ptr_optional(other.config_file)
&& TStr::from_ptr(this.fs_source_path) == TStr::from_ptr(this.fs_source_path)
&& TStr::from_ptr(this.wim_target_path) == TStr::from_ptr(other.wim_target_path)
},
sys::wimlib_update_op_WIMLIB_UPDATE_OP_DELETE => unsafe {
let this = &self.inner.__bindgen_anon_1.delete_;
let other = &other.inner.__bindgen_anon_1.delete_;
this.delete_flags == other.delete_flags
&& TStr::from_ptr(this.wim_path) == TStr::from_ptr(other.wim_path)
},
sys::wimlib_update_op_WIMLIB_UPDATE_OP_RENAME => unsafe {
let this = &self.inner.__bindgen_anon_1.rename;
let other = &self.inner.__bindgen_anon_1.rename;
this.rename_flags == other.rename_flags
&& TStr::from_ptr(this.wim_source_path) == TStr::from_ptr(other.wim_source_path)
&& TStr::from_ptr(this.wim_target_path) == TStr::from_ptr(other.wim_target_path)
},
_ => false,
}
}
}
impl Eq for UpdateCommand<'_> {}
impl<'a> UpdateCommand<'a> {
pub fn add(
fs_source_path: &'a TStr,
wim_target_path: &'a TStr,
config_file: Option<&'a TStr>,
add_flags: AddFlags,
) -> Self {
let command = sys::wimlib_add_command {
fs_source_path: fs_source_path.as_ptr().cast_mut(),
wim_target_path: wim_target_path.as_ptr().cast_mut(),
config_file: config_file.as_nullable_ptr().cast_mut(),
add_flags: add_flags.bits(),
};
let inner = sys::wimlib_update_command {
op: sys::wimlib_update_op_WIMLIB_UPDATE_OP_ADD,
__bindgen_anon_1: sys::wimlib_update_command__bindgen_ty_1 { add: command },
};
Self {
inner,
_borrows: PhantomData,
}
}
pub fn delete(path: &'a TStr, delete_flags: DeleteFlags) -> Self {
let command = sys::wimlib_delete_command {
wim_path: path.as_ptr().cast_mut(),
delete_flags: delete_flags.bits(),
};
let inner = sys::wimlib_update_command {
op: sys::wimlib_update_op_WIMLIB_UPDATE_OP_DELETE,
__bindgen_anon_1: sys::wimlib_update_command__bindgen_ty_1 { delete_: command },
};
Self {
inner,
_borrows: PhantomData,
}
}
pub fn rename(from: &'a TStr, to: &'a TStr, rename_flags: RenameFlags) -> Self {
let command = sys::wimlib_rename_command {
wim_source_path: from.as_ptr().cast_mut(),
wim_target_path: to.as_ptr().cast_mut(),
rename_flags: rename_flags.bits(),
};
let inner = sys::wimlib_update_command {
op: sys::wimlib_update_op_WIMLIB_UPDATE_OP_RENAME,
__bindgen_anon_1: sys::wimlib_update_command__bindgen_ty_1 { rename: command },
};
Self {
inner,
_borrows: PhantomData,
}
}
pub fn into_raw(self) -> sys::wimlib_update_command {
self.inner
}
pub unsafe fn from_raw(ffi: sys::wimlib_update_command) -> Self {
Self {
inner: ffi,
_borrows: PhantomData,
}
}
}
#[derive(Default)]
pub struct SetInfo {
readonly_flag: Option<bool>,
guid: Option<Uuid>,
boot_index: Option<Option<ImageIndex>>,
rpfix_flag: Option<bool>,
}
impl SetInfo {
pub fn readonly_flag(mut self, flag: bool) -> Self {
self.readonly_flag = Some(flag);
self
}
pub fn guid(mut self, guid: Uuid) -> Self {
self.guid = Some(guid);
self
}
pub fn boot_index(mut self, boot_index: Option<ImageIndex>) -> Self {
self.boot_index = Some(boot_index);
self
}
pub fn rpfix_flag(mut self, flag: bool) -> Self {
self.rpfix_flag = Some(flag);
self
}
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct AddFlags: std::ffi::c_int {
#[cfg(any(unix, doc))]
const NTFS = sys::WIMLIB_ADD_FLAG_NTFS as _;
const DEREFERENCE = sys::WIMLIB_ADD_FLAG_DEREFERENCE as _;
const VERBOSE = sys::WIMLIB_ADD_FLAG_VERBOSE as _;
const BOOT = sys::WIMLIB_ADD_FLAG_BOOT as _;
#[cfg(any(unix, doc))]
const UNIX_DATA = sys::WIMLIB_ADD_FLAG_UNIX_DATA as _;
const NO_ACLS = sys::WIMLIB_ADD_FLAG_NO_ACLS as _;
const STRICT_ACLS = sys::WIMLIB_ADD_FLAG_STRICT_ACLS as _;
const EXCLUDE_VERBOSE = sys::WIMLIB_ADD_FLAG_EXCLUDE_VERBOSE as _;
const RPFIX = sys::WIMLIB_ADD_FLAG_RPFIX as _;
const NORPFIX = sys::WIMLIB_ADD_FLAG_NORPFIX as _;
const NO_UNSUPPORTED_EXCLUDE = sys::WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE as _;
const WINCONFIG = sys::WIMLIB_ADD_FLAG_WINCONFIG as _;
const WIMBOOT = sys::WIMLIB_ADD_FLAG_WIMBOOT as _;
const NO_REPLACE = sys::WIMLIB_ADD_FLAG_NO_REPLACE as _;
const TEST_FILE_EXCLUSION = sys::WIMLIB_ADD_FLAG_TEST_FILE_EXCLUSION as _;
const SNAPSHOT = sys::WIMLIB_ADD_FLAG_SNAPSHOT as _;
const FILE_PATHS_UNNEEDED = sys::WIMLIB_ADD_FLAG_FILE_PATHS_UNNEEDED as _;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct DeleteFlags: std::ffi::c_int {
const FORCE = sys::WIMLIB_DELETE_FLAG_FORCE as _;
const RECURSIVE = sys::WIMLIB_DELETE_FLAG_RECURSIVE as _;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ExportFlags: std::ffi::c_int {
const BOOT = sys::WIMLIB_EXPORT_FLAG_BOOT as _;
const NO_NAMES = sys::WIMLIB_EXPORT_FLAG_NO_NAMES as _;
const NO_DESCRIPTIONS = sys::WIMLIB_EXPORT_FLAG_NO_DESCRIPTIONS as _;
const GIFT = sys::WIMLIB_EXPORT_FLAG_GIFT as _;
const WIMBOOT = sys::WIMLIB_EXPORT_FLAG_WIMBOOT as _;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct UpdateFlags: std::ffi::c_int {
const SEND_PROGRESS = sys::WIMLIB_UPDATE_FLAG_SEND_PROGRESS as _;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RenameFlags: std::ffi::c_int {}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ReferenceTemplateImageFlags: std::ffi::c_int {}
}