summaryrefslogtreecommitdiff
path: root/rust/src/database.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/database.rs')
-rw-r--r--rust/src/database.rs617
1 files changed, 106 insertions, 511 deletions
diff --git a/rust/src/database.rs b/rust/src/database.rs
index 3274c9c0..7174ebe8 100644
--- a/rust/src/database.rs
+++ b/rust/src/database.rs
@@ -1,115 +1,123 @@
-use std::collections::HashMap;
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
-use std::{ffi, mem, ptr};
+pub mod kvs;
+pub mod snapshot;
+pub mod undo;
use binaryninjacore_sys::*;
+use std::collections::HashMap;
+use std::ffi::{c_char, c_void};
+use std::fmt::Debug;
+use std::ptr::NonNull;
-use crate::binaryview::BinaryView;
-use crate::databuffer::DataBuffer;
-use crate::disassembly::InstructionTextToken;
-use crate::filemetadata::FileMetadata;
-use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
+use crate::binary_view::BinaryView;
+use crate::data_buffer::DataBuffer;
+use crate::database::kvs::KeyValueStore;
+use crate::database::snapshot::{Snapshot, SnapshotId};
+use crate::file_metadata::FileMetadata;
+use crate::progress::{NoProgressCallback, ProgressCallback};
+use crate::rc::{Array, Ref, RefCountable};
use crate::string::{BnStrCompatible, BnString};
-#[repr(transparent)]
pub struct Database {
- handle: ptr::NonNull<BNDatabase>,
+ pub(crate) handle: NonNull<BNDatabase>,
}
impl Database {
- pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNDatabase>) -> Self {
+ pub(crate) unsafe fn from_raw(handle: NonNull<BNDatabase>) -> Self {
Self { handle }
}
- #[allow(clippy::mut_from_ref)]
- pub(crate) unsafe fn as_raw(&self) -> &mut BNDatabase {
- &mut *self.handle.as_ptr()
+ pub(crate) unsafe fn ref_from_raw(handle: NonNull<BNDatabase>) -> Ref<Self> {
+ Ref::new(Self { handle })
}
/// Get a snapshot by its id, or None if no snapshot with that id exists
- pub fn snapshot(&self, id: i64) -> Option<Snapshot> {
- let result = unsafe { BNGetDatabaseSnapshot(self.as_raw(), id) };
- ptr::NonNull::new(result).map(|handle| unsafe { Snapshot::from_raw(handle) })
+ pub fn snapshot_by_id(&self, id: SnapshotId) -> Option<Ref<Snapshot>> {
+ let result = unsafe { BNGetDatabaseSnapshot(self.handle.as_ptr(), id.0) };
+ NonNull::new(result).map(|handle| unsafe { Snapshot::ref_from_raw(handle) })
}
/// Get a list of all snapshots in the database
pub fn snapshots(&self) -> Array<Snapshot> {
let mut count = 0;
- let result = unsafe { BNGetDatabaseSnapshots(self.as_raw(), &mut count) };
+ let result = unsafe { BNGetDatabaseSnapshots(self.handle.as_ptr(), &mut count) };
assert!(!result.is_null());
unsafe { Array::new(result, count, ()) }
}
/// Get the current snapshot
- pub fn current_snapshot(&self) -> Option<Snapshot> {
- let result = unsafe { BNGetDatabaseCurrentSnapshot(self.as_raw()) };
- ptr::NonNull::new(result).map(|handle| unsafe { Snapshot::from_raw(handle) })
+ pub fn current_snapshot(&self) -> Option<Ref<Snapshot>> {
+ let result = unsafe { BNGetDatabaseCurrentSnapshot(self.handle.as_ptr()) };
+ NonNull::new(result).map(|handle| unsafe { Snapshot::ref_from_raw(handle) })
}
+ /// Equivalent to [`Self::set_current_snapshot_id`].
pub fn set_current_snapshot(&self, value: &Snapshot) {
- unsafe { BNSetDatabaseCurrentSnapshot(self.as_raw(), value.id()) }
+ self.set_current_snapshot_id(value.id())
+ }
+
+ /// Sets the current snapshot to the [`SnapshotId`].
+ ///
+ /// **No** validation is done to ensure that the id is valid.
+ pub fn set_current_snapshot_id(&self, id: SnapshotId) {
+ unsafe { BNSetDatabaseCurrentSnapshot(self.handle.as_ptr(), id.0) }
}
pub fn write_snapshot_data<N: BnStrCompatible>(
&self,
- parents: &[i64],
+ parents: &[SnapshotId],
file: &BinaryView,
name: N,
data: &KeyValueStore,
auto_save: bool,
- ) -> i64 {
- let name_raw = name.into_bytes_with_nul();
- let name_ptr = name_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe {
- BNWriteDatabaseSnapshotData(
- self.as_raw(),
- parents.as_ptr() as *mut _,
- parents.len(),
- file.handle,
- name_ptr,
- data.as_raw(),
- auto_save,
- ptr::null_mut(),
- Some(cb_progress_nop),
- )
- }
+ ) -> SnapshotId {
+ self.write_snapshot_data_with_progress(
+ parents,
+ file,
+ name,
+ data,
+ auto_save,
+ NoProgressCallback,
+ )
}
- pub fn write_snapshot_data_with_progress<N, F>(
+ pub fn write_snapshot_data_with_progress<N, P>(
&self,
- parents: &[i64],
+ parents: &[SnapshotId],
file: &BinaryView,
name: N,
data: &KeyValueStore,
auto_save: bool,
- mut progress: F,
- ) -> i64
+ mut progress: P,
+ ) -> SnapshotId
where
N: BnStrCompatible,
- F: FnMut(usize, usize) -> bool,
+ P: ProgressCallback,
{
let name_raw = name.into_bytes_with_nul();
- let name_ptr = name_raw.as_ref().as_ptr() as *const ffi::c_char;
- let ctxt = &mut progress as *mut _ as *mut ffi::c_void;
- unsafe {
+ let name_ptr = name_raw.as_ref().as_ptr() as *const c_char;
+
+ let new_id = unsafe {
BNWriteDatabaseSnapshotData(
- self.as_raw(),
+ self.handle.as_ptr(),
+ // SAFETY: SnapshotId is just i64
parents.as_ptr() as *mut _,
parents.len(),
file.handle,
name_ptr,
- data.as_raw(),
+ data.handle.as_ptr(),
auto_save,
- ctxt,
- Some(cb_progress::<F>),
+ &mut progress as *mut P as *mut c_void,
+ Some(P::cb_progress_callback),
)
- }
+ };
+
+ SnapshotId(new_id)
}
/// Trim a snapshot's contents in the database by id, but leave the parent/child
/// hierarchy intact. Future references to this snapshot will return False for has_contents
- pub fn trim_snapshot(&self, id: i64) -> Result<(), ()> {
- if unsafe { BNTrimDatabaseSnapshot(self.as_raw(), id) } {
+ pub fn trim_snapshot(&self, id: SnapshotId) -> Result<(), ()> {
+ if unsafe { BNTrimDatabaseSnapshot(self.handle.as_ptr(), id.0) } {
Ok(())
} else {
Err(())
@@ -118,8 +126,8 @@ impl Database {
/// Remove a snapshot in the database by id, deleting its contents and references.
/// Attempting to remove a snapshot with children will raise an exception.
- pub fn remove_snapshot(&self, id: i64) -> Result<(), ()> {
- if unsafe { BNRemoveDatabaseSnapshot(self.as_raw(), id) } {
+ pub fn remove_snapshot(&self, id: SnapshotId) -> Result<(), ()> {
+ if unsafe { BNRemoveDatabaseSnapshot(self.handle.as_ptr(), id.0) } {
Ok(())
} else {
Err(())
@@ -127,14 +135,14 @@ impl Database {
}
pub fn has_global<S: BnStrCompatible>(&self, key: S) -> bool {
let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe { BNDatabaseHasGlobal(self.as_raw(), key_ptr) != 0 }
+ let key_ptr = key_raw.as_ref().as_ptr() as *const c_char;
+ unsafe { BNDatabaseHasGlobal(self.handle.as_ptr(), key_ptr) != 0 }
}
/// Get a list of keys for all globals in the database
pub fn global_keys(&self) -> Array<BnString> {
let mut count = 0;
- let result = unsafe { BNGetDatabaseGlobalKeys(self.as_raw(), &mut count) };
+ let result = unsafe { BNGetDatabaseGlobalKeys(self.handle.as_ptr(), &mut count) };
assert!(!result.is_null());
unsafe { Array::new(result, count, ()) }
}
@@ -150,505 +158,92 @@ impl Database {
/// Get a specific global by key
pub fn read_global<S: BnStrCompatible>(&self, key: S) -> Option<BnString> {
let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
- let result = unsafe { BNReadDatabaseGlobal(self.as_raw(), key_ptr) };
- unsafe { ptr::NonNull::new(result).map(|_| BnString::from_raw(result)) }
+ let key_ptr = key_raw.as_ref().as_ptr() as *const c_char;
+ let result = unsafe { BNReadDatabaseGlobal(self.handle.as_ptr(), key_ptr) };
+ unsafe { NonNull::new(result).map(|_| BnString::from_raw(result)) }
}
/// Write a global into the database
pub fn write_global<K: BnStrCompatible, V: BnStrCompatible>(&self, key: K, value: V) -> bool {
let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
+ let key_ptr = key_raw.as_ref().as_ptr() as *const c_char;
let value_raw = value.into_bytes_with_nul();
- let value_ptr = value_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe { BNWriteDatabaseGlobal(self.as_raw(), key_ptr, value_ptr) }
+ let value_ptr = value_raw.as_ref().as_ptr() as *const c_char;
+ unsafe { BNWriteDatabaseGlobal(self.handle.as_ptr(), key_ptr, value_ptr) }
}
/// Get a specific global by key, as a binary buffer
pub fn read_global_data<S: BnStrCompatible>(&self, key: S) -> Option<DataBuffer> {
let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
- let result = unsafe { BNReadDatabaseGlobalData(self.as_raw(), key_ptr) };
- ptr::NonNull::new(result).map(|_| DataBuffer::from_raw(result))
+ let key_ptr = key_raw.as_ref().as_ptr() as *const c_char;
+ let result = unsafe { BNReadDatabaseGlobalData(self.handle.as_ptr(), key_ptr) };
+ NonNull::new(result).map(|_| DataBuffer::from_raw(result))
}
/// Write a binary buffer into a global in the database
pub fn write_global_data<K: BnStrCompatible>(&self, key: K, value: &DataBuffer) -> bool {
let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe { BNWriteDatabaseGlobalData(self.as_raw(), key_ptr, value.as_raw()) }
+ let key_ptr = key_raw.as_ref().as_ptr() as *const c_char;
+ unsafe { BNWriteDatabaseGlobalData(self.handle.as_ptr(), key_ptr, value.as_raw()) }
}
/// Get the owning FileMetadata
pub fn file(&self) -> Ref<FileMetadata> {
- let result = unsafe { BNGetDatabaseFile(self.as_raw()) };
+ let result = unsafe { BNGetDatabaseFile(self.handle.as_ptr()) };
assert!(!result.is_null());
- unsafe { Ref::new(FileMetadata::from_raw(result)) }
+ FileMetadata::ref_from_raw(result)
}
/// Get the backing analysis cache kvs
- pub fn analysis_cache(&self) -> KeyValueStore {
- let result = unsafe { BNReadDatabaseAnalysisCache(self.as_raw()) };
- unsafe { KeyValueStore::from_raw(ptr::NonNull::new(result).unwrap()) }
+ pub fn analysis_cache(&self) -> Ref<KeyValueStore> {
+ let result = unsafe { BNReadDatabaseAnalysisCache(self.handle.as_ptr()) };
+ unsafe { KeyValueStore::ref_from_raw(NonNull::new(result).unwrap()) }
}
pub fn reload_connection(&self) {
- unsafe { BNDatabaseReloadConnection(self.as_raw()) }
+ unsafe { BNDatabaseReloadConnection(self.handle.as_ptr()) }
}
pub fn write_analysis_cache(&self, val: &KeyValueStore) -> Result<(), ()> {
- if unsafe { BNWriteDatabaseAnalysisCache(self.as_raw(), val.as_raw()) } {
+ if unsafe { BNWriteDatabaseAnalysisCache(self.handle.as_ptr(), val.handle.as_ptr()) } {
Ok(())
} else {
Err(())
}
}
- pub fn snapshot_has_data(&self, id: i64) -> bool {
- unsafe { BNSnapshotHasData(self.as_raw(), id) }
+ pub fn snapshot_has_data(&self, id: SnapshotId) -> bool {
+ unsafe { BNSnapshotHasData(self.handle.as_ptr(), id.0) }
}
}
-impl Clone for Database {
- fn clone(&self) -> Self {
- unsafe { Self::from_raw(ptr::NonNull::new(BNNewDatabaseReference(self.as_raw())).unwrap()) }
+impl Debug for Database {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Database")
+ .field("current_snapshot", &self.current_snapshot())
+ .field("snapshot_count", &self.snapshots().len())
+ .field("globals", &self.globals())
+ .field("analysis_cache", &self.analysis_cache())
+ .finish()
}
}
-impl Drop for Database {
- fn drop(&mut self) {
- unsafe { BNFreeDatabase(self.as_raw()) }
- }
-}
-
-#[repr(transparent)]
-pub struct Snapshot {
- handle: ptr::NonNull<BNSnapshot>,
-}
+impl ToOwned for Database {
+ type Owned = Ref<Self>;
-impl Snapshot {
- pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNSnapshot>) -> Self {
- Self { handle }
- }
-
- pub(crate) unsafe fn ref_from_raw(handle: &*mut BNSnapshot) -> &Self {
- mem::transmute(handle)
- }
-
- #[allow(clippy::mut_from_ref)]
- pub(crate) unsafe fn as_raw(&self) -> &mut BNSnapshot {
- &mut *self.handle.as_ptr()
- }
-
- /// Get the owning database
- pub fn database(&self) -> Database {
- unsafe {
- Database::from_raw(ptr::NonNull::new(BNGetSnapshotDatabase(self.as_raw())).unwrap())
- }
- }
-
- /// Get the numerical id (read-only)
- pub fn id(&self) -> i64 {
- unsafe { BNGetSnapshotId(self.as_raw()) }
- }
-
- /// Get the displayed snapshot name
- pub fn name(&self) -> BnString {
- unsafe { BnString::from_raw(BNGetSnapshotName(self.as_raw())) }
- }
-
- /// Set the displayed snapshot name
- pub fn set_name<S: BnStrCompatible>(&self, value: S) {
- let value_raw = value.into_bytes_with_nul();
- let value_ptr = value_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe { BNSetSnapshotName(self.as_raw(), value_ptr) }
- }
-
- /// If the snapshot was the result of an auto-save
- pub fn is_auto_save(&self) -> bool {
- unsafe { BNIsSnapshotAutoSave(self.as_raw()) }
- }
-
- /// If the snapshot has contents, and has not been trimmed
- pub fn has_contents(&self) -> bool {
- unsafe { BNSnapshotHasContents(self.as_raw()) }
- }
-
- /// If the snapshot has undo data
- pub fn has_undo(&self) -> bool {
- unsafe { BNSnapshotHasUndo(self.as_raw()) }
- }
-
- /// Get the first parent of the snapshot, or None if it has no parents
- pub fn first_parent(&self) -> Option<Snapshot> {
- let result = unsafe { BNGetSnapshotFirstParent(self.as_raw()) };
- ptr::NonNull::new(result).map(|s| unsafe { Snapshot::from_raw(s) })
- }
-
- /// Get a list of all parent snapshots of the snapshot
- pub fn parents(&self) -> Array<Snapshot> {
- let mut count = 0;
- let result = unsafe { BNGetSnapshotParents(self.as_raw(), &mut count) };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-
- /// Get a list of all child snapshots of the snapshot
- pub fn children(&self) -> Array<Snapshot> {
- let mut count = 0;
- let result = unsafe { BNGetSnapshotChildren(self.as_raw(), &mut count) };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-
- /// Get a buffer of the raw data at the time of the snapshot
- pub fn file_contents(&self) -> Option<DataBuffer> {
- self.has_contents().then(|| unsafe {
- let result = BNGetSnapshotFileContents(self.as_raw());
- assert!(!result.is_null());
- DataBuffer::from_raw(result)
- })
- }
-
- /// Get a hash of the data at the time of the snapshot
- pub fn file_contents_hash(&self) -> Option<DataBuffer> {
- self.has_contents().then(|| unsafe {
- let result = BNGetSnapshotFileContentsHash(self.as_raw());
- assert!(!result.is_null());
- DataBuffer::from_raw(result)
- })
- }
-
- /// Get a list of undo entries at the time of the snapshot
- pub fn undo_entries(&self) -> Array<UndoEntry> {
- assert!(self.has_undo());
- let mut count = 0;
- let result = unsafe { BNGetSnapshotUndoEntries(self.as_raw(), &mut count) };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-
- pub fn undo_entries_with_progress<F: FnMut(usize, usize) -> bool>(
- &self,
- mut progress: F,
- ) -> Array<UndoEntry> {
- assert!(self.has_undo());
- let ctxt = &mut progress as *mut _ as *mut ffi::c_void;
- let mut count = 0;
- let result = unsafe {
- BNGetSnapshotUndoEntriesWithProgress(
- self.as_raw(),
- ctxt,
- Some(cb_progress::<F>),
- &mut count,
- )
- };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-
- /// Get the backing kvs data with snapshot fields
- pub fn read_data(&self) -> KeyValueStore {
- let result = unsafe { BNReadSnapshotData(self.as_raw()) };
- unsafe { KeyValueStore::from_raw(ptr::NonNull::new(result).unwrap()) }
- }
-
- pub fn read_data_with_progress<F: FnMut(usize, usize) -> bool>(
- &self,
- mut progress: F,
- ) -> KeyValueStore {
- let ctxt = &mut progress as *mut _ as *mut ffi::c_void;
- let result =
- unsafe { BNReadSnapshotDataWithProgress(self.as_raw(), ctxt, Some(cb_progress::<F>)) };
- unsafe { KeyValueStore::from_raw(ptr::NonNull::new(result).unwrap()) }
- }
-
- pub fn undo_data(&self) -> DataBuffer {
- let result = unsafe { BNGetSnapshotUndoData(self.as_raw()) };
- assert!(!result.is_null());
- DataBuffer::from_raw(result)
- }
-
- pub fn store_data<F: FnMut(usize, usize) -> bool>(
- &self,
- data: KeyValueStore,
- mut progress: F,
- ) -> bool {
- let ctxt = &mut progress as *mut _ as *mut ffi::c_void;
- unsafe { BNSnapshotStoreData(self.as_raw(), data.as_raw(), ctxt, Some(cb_progress::<F>)) }
- }
-
- /// Determine if this snapshot has another as an ancestor
- pub fn has_ancestor(self, other: &Snapshot) -> bool {
- unsafe { BNSnapshotHasAncestor(self.as_raw(), other.as_raw()) }
- }
-}
-
-impl Clone for Snapshot {
- fn clone(&self) -> Self {
- unsafe { Self::from_raw(ptr::NonNull::new(BNNewSnapshotReference(self.as_raw())).unwrap()) }
- }
-}
-
-impl Drop for Snapshot {
- fn drop(&mut self) {
- unsafe { BNFreeSnapshot(self.as_raw()) }
+ fn to_owned(&self) -> Self::Owned {
+ unsafe { RefCountable::inc_ref(self) }
}
}
-impl CoreArrayProvider for Snapshot {
- type Raw = *mut BNSnapshot;
- type Context = ();
- type Wrapped<'a> = &'a Self;
-}
-
-unsafe impl CoreArrayProviderInner for Snapshot {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNFreeSnapshotList(raw, count);
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self::ref_from_raw(raw)
- }
-}
-
-#[repr(transparent)]
-pub struct KeyValueStore {
- handle: ptr::NonNull<BNKeyValueStore>,
-}
-
-impl KeyValueStore {
- pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNKeyValueStore>) -> Self {
- Self { handle }
- }
-
- #[allow(clippy::mut_from_ref)]
- pub(crate) unsafe fn as_raw(&self) -> &mut BNKeyValueStore {
- &mut *self.handle.as_ptr()
- }
-
- /// Get a list of all keys stored in the kvs
- pub fn keys(&self) -> Array<BnString> {
- let mut count = 0;
- let result = unsafe { BNGetKeyValueStoreKeys(self.as_raw(), &mut count) };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-
- /// Get the value for a single key
- pub fn value<S: BnStrCompatible>(&self, key: S) -> Option<DataBuffer> {
- let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
- let result = unsafe { BNGetKeyValueStoreBuffer(self.as_raw(), key_ptr) };
- ptr::NonNull::new(result).map(|_| DataBuffer::from_raw(result))
- }
-
- /// Set the value for a single key
- pub fn set_value<S: BnStrCompatible>(&self, key: S, value: &DataBuffer) -> bool {
- let key_raw = key.into_bytes_with_nul();
- let key_ptr = key_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe { BNSetKeyValueStoreBuffer(self.as_raw(), key_ptr, value.as_raw()) }
- }
-
- /// Get the stored representation of the kvs
- pub fn serialized_data(&self) -> DataBuffer {
- let result = unsafe { BNGetKeyValueStoreSerializedData(self.as_raw()) };
- assert!(!result.is_null());
- DataBuffer::from_raw(result)
- }
-
- /// Begin storing new keys into a namespace
- pub fn begin_namespace<S: BnStrCompatible>(&self, name: S) {
- let name_raw = name.into_bytes_with_nul();
- let name_ptr = name_raw.as_ref().as_ptr() as *const ffi::c_char;
- unsafe { BNBeginKeyValueStoreNamespace(self.as_raw(), name_ptr) }
- }
-
- /// End storing new keys into a namespace
- pub fn end_namespace(&self) {
- unsafe { BNEndKeyValueStoreNamespace(self.as_raw()) }
- }
-
- /// If the kvs is empty
- pub fn empty(&self) -> bool {
- unsafe { BNIsKeyValueStoreEmpty(self.as_raw()) }
- }
-
- /// Number of values in the kvs
- pub fn value_size(&self) -> usize {
- unsafe { BNGetKeyValueStoreValueSize(self.as_raw()) }
- }
-
- /// Length of serialized data
- pub fn data_size(&self) -> usize {
- unsafe { BNGetKeyValueStoreDataSize(self.as_raw()) }
- }
-
- /// Size of all data in storage
- pub fn value_storage_size(self) -> usize {
- unsafe { BNGetKeyValueStoreValueStorageSize(self.as_raw()) }
- }
-
- /// Number of namespaces pushed with begin_namespace
- pub fn namespace_size(self) -> usize {
- unsafe { BNGetKeyValueStoreNamespaceSize(self.as_raw()) }
- }
-}
-
-impl Clone for KeyValueStore {
- fn clone(&self) -> Self {
- unsafe {
- Self::from_raw(ptr::NonNull::new(BNNewKeyValueStoreReference(self.as_raw())).unwrap())
- }
- }
-}
-
-impl Drop for KeyValueStore {
- fn drop(&mut self) {
- unsafe { BNFreeKeyValueStore(self.as_raw()) }
- }
-}
-
-#[repr(transparent)]
-pub struct UndoEntry {
- handle: ptr::NonNull<BNUndoEntry>,
-}
-
-impl UndoEntry {
- pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNUndoEntry>) -> Self {
- Self { handle }
- }
-
- pub(crate) unsafe fn ref_from_raw(handle: &*mut BNUndoEntry) -> &Self {
- mem::transmute(handle)
- }
-
- #[allow(clippy::mut_from_ref)]
- pub(crate) unsafe fn as_raw(&self) -> &mut BNUndoEntry {
- &mut *self.handle.as_ptr()
- }
-
- pub fn id(&self) -> BnString {
- let result = unsafe { BNUndoEntryGetId(self.as_raw()) };
- assert!(!result.is_null());
- unsafe { BnString::from_raw(result) }
- }
-
- pub fn actions(&self) -> Array<UndoAction> {
- let mut count = 0;
- let result = unsafe { BNUndoEntryGetActions(self.as_raw(), &mut count) };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-
- pub fn time(&self) -> SystemTime {
- let m = Duration::from_secs(unsafe { BNUndoEntryGetTimestamp(self.as_raw()) });
- UNIX_EPOCH + m
- }
-}
-
-impl Clone for UndoEntry {
- fn clone(&self) -> Self {
- unsafe {
- Self::from_raw(ptr::NonNull::new(BNNewUndoEntryReference(self.as_raw())).unwrap())
- }
- }
-}
-
-impl Drop for UndoEntry {
- fn drop(&mut self) {
- unsafe { BNFreeUndoEntry(self.as_raw()) }
- }
-}
-
-impl CoreArrayProvider for UndoEntry {
- type Raw = *mut BNUndoEntry;
- type Context = ();
- type Wrapped<'a> = &'a Self;
-}
-
-unsafe impl CoreArrayProviderInner for UndoEntry {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNFreeUndoEntryList(raw, count);
- }
-
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self::ref_from_raw(raw)
- }
-}
-
-#[repr(transparent)]
-pub struct UndoAction {
- handle: ptr::NonNull<BNUndoAction>,
-}
-
-impl UndoAction {
- pub(crate) unsafe fn from_raw(handle: ptr::NonNull<BNUndoAction>) -> Self {
- Self { handle }
- }
-
- pub(crate) unsafe fn ref_from_raw(handle: &*mut BNUndoAction) -> &Self {
- mem::transmute(handle)
- }
-
- #[allow(clippy::mut_from_ref)]
- pub(crate) unsafe fn as_raw(&self) -> &mut BNUndoAction {
- &mut *self.handle.as_ptr()
- }
-
- pub fn summary_text(&self) -> BnString {
- let result = unsafe { BNUndoActionGetSummaryText(self.as_raw()) };
- assert!(!result.is_null());
- unsafe { BnString::from_raw(result) }
- }
-
- pub fn summary(&self) -> Array<InstructionTextToken> {
- let mut count = 0;
- let result = unsafe { BNUndoActionGetSummary(self.as_raw(), &mut count) };
- assert!(!result.is_null());
- unsafe { Array::new(result, count, ()) }
- }
-}
-
-impl Clone for UndoAction {
- fn clone(&self) -> Self {
- unsafe {
- Self::from_raw(ptr::NonNull::new(BNNewUndoActionReference(self.as_raw())).unwrap())
- }
- }
-}
-
-impl Drop for UndoAction {
- fn drop(&mut self) {
- unsafe { BNFreeUndoAction(self.as_raw()) }
- }
-}
-
-impl CoreArrayProvider for UndoAction {
- type Raw = *mut BNUndoAction;
- type Context = ();
- type Wrapped<'a> = &'a Self;
-}
-
-unsafe impl CoreArrayProviderInner for UndoAction {
- unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
- BNFreeUndoActionList(raw, count);
+unsafe impl RefCountable for Database {
+ unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
+ Ref::new(Self {
+ handle: NonNull::new(BNNewDatabaseReference(handle.handle.as_ptr())).unwrap(),
+ })
}
- unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, _context: &'a Self::Context) -> Self::Wrapped<'a> {
- Self::ref_from_raw(raw)
+ unsafe fn dec_ref(handle: &Self) {
+ BNFreeDatabase(handle.handle.as_ptr());
}
}
-
-unsafe extern "C" fn cb_progress<F: FnMut(usize, usize) -> bool>(
- ctxt: *mut ffi::c_void,
- arg1: usize,
- arg2: usize,
-) -> bool {
- let ctxt: &mut F = &mut *(ctxt as *mut F);
- ctxt(arg1, arg2)
-}
-
-unsafe extern "C" fn cb_progress_nop(_ctxt: *mut ffi::c_void, _arg1: usize, _arg2: usize) -> bool {
- true
-}