summaryrefslogtreecommitdiff
path: root/rust/src/project/file.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/project/file.rs')
-rw-r--r--rust/src/project/file.rs167
1 files changed, 167 insertions, 0 deletions
diff --git a/rust/src/project/file.rs b/rust/src/project/file.rs
new file mode 100644
index 00000000..5071dd50
--- /dev/null
+++ b/rust/src/project/file.rs
@@ -0,0 +1,167 @@
+use crate::project::{systime_from_bntime, Project, ProjectFolder};
+use crate::rc::{CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
+use crate::string::{BnStrCompatible, BnString};
+use binaryninjacore_sys::{
+ BNFreeProjectFile, BNFreeProjectFileList, BNNewProjectFileReference, BNProjectFile,
+ BNProjectFileExistsOnDisk, BNProjectFileExport, BNProjectFileGetCreationTimestamp,
+ BNProjectFileGetDescription, BNProjectFileGetFolder, BNProjectFileGetId, BNProjectFileGetName,
+ BNProjectFileGetPathOnDisk, BNProjectFileGetProject, BNProjectFileSetDescription,
+ BNProjectFileSetFolder, BNProjectFileSetName,
+};
+use std::ffi::c_char;
+use std::fmt::Debug;
+use std::ptr::{null_mut, NonNull};
+use std::time::SystemTime;
+
+#[repr(transparent)]
+pub struct ProjectFile {
+ pub(crate) handle: NonNull<BNProjectFile>,
+}
+
+impl ProjectFile {
+ pub(crate) unsafe fn from_raw(handle: NonNull<BNProjectFile>) -> Self {
+ Self { handle }
+ }
+
+ pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNProjectFile>) -> Ref<Self> {
+ Ref::new(Self { handle })
+ }
+
+ /// Get the project that owns this file
+ pub fn project(&self) -> Ref<Project> {
+ unsafe {
+ Project::ref_from_raw(
+ NonNull::new(BNProjectFileGetProject(self.handle.as_ptr())).unwrap(),
+ )
+ }
+ }
+
+ /// Get the path on disk to this file's contents
+ pub fn path_on_disk(&self) -> BnString {
+ unsafe { BnString::from_raw(BNProjectFileGetPathOnDisk(self.handle.as_ptr())) }
+ }
+
+ /// Check if this file's contents exist on disk
+ pub fn exists_on_disk(&self) -> bool {
+ unsafe { BNProjectFileExistsOnDisk(self.handle.as_ptr()) }
+ }
+
+ /// Get the unique id of this file
+ pub fn id(&self) -> BnString {
+ unsafe { BnString::from_raw(BNProjectFileGetId(self.handle.as_ptr())) }
+ }
+
+ /// Get the name of this file
+ pub fn name(&self) -> BnString {
+ unsafe { BnString::from_raw(BNProjectFileGetName(self.handle.as_ptr())) }
+ }
+
+ /// Set the name of this file
+ pub fn set_name<S: BnStrCompatible>(&self, value: S) -> bool {
+ let value_raw = value.into_bytes_with_nul();
+ unsafe {
+ BNProjectFileSetName(
+ self.handle.as_ptr(),
+ value_raw.as_ref().as_ptr() as *const c_char,
+ )
+ }
+ }
+
+ /// Get the description of this file
+ pub fn description(&self) -> BnString {
+ unsafe { BnString::from_raw(BNProjectFileGetDescription(self.handle.as_ptr())) }
+ }
+
+ /// Set the description of this file
+ pub fn set_description<S: BnStrCompatible>(&self, value: S) -> bool {
+ let value_raw = value.into_bytes_with_nul();
+ unsafe {
+ BNProjectFileSetDescription(
+ self.handle.as_ptr(),
+ value_raw.as_ref().as_ptr() as *const c_char,
+ )
+ }
+ }
+
+ /// Get the file creation time
+ pub fn creation_time(&self) -> SystemTime {
+ systime_from_bntime(unsafe { BNProjectFileGetCreationTimestamp(self.handle.as_ptr()) })
+ .unwrap()
+ }
+
+ /// Get the folder that contains this file
+ pub fn folder(&self) -> Option<Ref<ProjectFolder>> {
+ let result = unsafe { BNProjectFileGetFolder(self.handle.as_ptr()) };
+ NonNull::new(result).map(|handle| unsafe { ProjectFolder::ref_from_raw(handle) })
+ }
+
+ /// Set the folder that contains this file
+ pub fn set_folder(&self, folder: Option<&ProjectFolder>) -> bool {
+ let folder_handle = folder.map(|x| x.handle.as_ptr()).unwrap_or(null_mut());
+ unsafe { BNProjectFileSetFolder(self.handle.as_ptr(), folder_handle) }
+ }
+
+ /// Export this file to disk, `true' if the export succeeded
+ ///
+ /// * `dest` - Destination path for the exported contents
+ pub fn export<S: BnStrCompatible>(&self, dest: S) -> bool {
+ let dest_raw = dest.into_bytes_with_nul();
+ unsafe {
+ BNProjectFileExport(
+ self.handle.as_ptr(),
+ dest_raw.as_ref().as_ptr() as *const c_char,
+ )
+ }
+ }
+}
+
+impl Debug for ProjectFile {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("ProjectFile")
+ .field("id", &self.id())
+ .field("name", &self.name())
+ .field("description", &self.description())
+ .field("creation_time", &self.creation_time())
+ .field("exists_on_disk", &self.exists_on_disk())
+ .field("project", &self.project())
+ .field("folder", &self.folder())
+ .finish()
+ }
+}
+
+impl ToOwned for ProjectFile {
+ type Owned = Ref<Self>;
+
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
+ }
+}
+
+unsafe impl RefCountable for ProjectFile {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: NonNull::new(BNNewProjectFileReference(handle.handle.as_ptr())).unwrap(),
+ })
+ }
+
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeProjectFile(handle.handle.as_ptr());
+ }
+}
+
+impl CoreArrayProvider for ProjectFile {
+ type Raw = *mut BNProjectFile;
+ type Context = ();
+ type Wrapped<'a> = Guard<'a, Self>;
+}
+
+unsafe impl CoreArrayProviderInner for ProjectFile {
+ unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
+ BNFreeProjectFileList(raw, count)
+ }
+
+ unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
+ let raw_ptr = NonNull::new(*raw).unwrap();
+ Guard::new(Self::from_raw(raw_ptr), context)
+ }
+}