binaryninja/
rc.rs

1// Copyright 2021-2026 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Reference counting for core Binary Ninja objects.
16
17use std::borrow::Borrow;
18use std::fmt::{Debug, Display, Formatter};
19use std::hash::{Hash, Hasher};
20use std::marker::PhantomData;
21use std::mem;
22use std::ops::{Deref, DerefMut};
23use std::ptr;
24use std::slice;
25
26// RefCountable provides an abstraction over the various
27// core-allocated refcounted resources.
28//
29// It is important that consumers don't acquire ownership
30// of a `RefCountable` object directly -- they should only
31// ever get their hands on a `Ref<T>` or `&T`, otherwise it
32// would be possible for the allocation in the core to
33// be trivially leaked, as `T` does not have the `Drop` impl
34//
35// `T` does not have the `Drop` impl in order to allow more
36// efficient handling of core owned objects we receive pointers
37// to in callbacks
38pub(crate) unsafe trait RefCountable: ToOwned<Owned = Ref<Self>> + Sized {
39    unsafe fn inc_ref(handle: &Self) -> Ref<Self>;
40    unsafe fn dec_ref(handle: &Self);
41}
42
43// Represents an 'owned' reference tracked by the core
44// that we are responsible for cleaning up once we're
45// done with the encapsulated value.
46#[allow(private_bounds)]
47pub struct Ref<T: RefCountable> {
48    contents: T,
49}
50
51#[allow(private_bounds)]
52impl<T: RefCountable> Ref<T> {
53    /// Safety: You need to make sure wherever you got the contents from incremented the ref count already. Anywhere the core passes out an object to the API does this.
54    pub(crate) unsafe fn new(contents: T) -> Self {
55        Self { contents }
56    }
57
58    pub unsafe fn into_raw(obj: Self) -> T {
59        let res = ptr::read(&obj.contents);
60        mem::forget(obj);
61        res
62    }
63}
64
65impl<T: RefCountable> AsRef<T> for Ref<T> {
66    fn as_ref(&self) -> &T {
67        &self.contents
68    }
69}
70
71impl<T: RefCountable> AsMut<T> for Ref<T> {
72    fn as_mut(&mut self) -> &mut T {
73        &mut self.contents
74    }
75}
76
77impl<T: RefCountable> Deref for Ref<T> {
78    type Target = T;
79
80    fn deref(&self) -> &T {
81        &self.contents
82    }
83}
84
85impl<T: RefCountable> DerefMut for Ref<T> {
86    fn deref_mut(&mut self) -> &mut T {
87        &mut self.contents
88    }
89}
90
91impl<T: RefCountable> Borrow<T> for Ref<T> {
92    fn borrow(&self) -> &T {
93        &self.contents
94    }
95}
96
97impl<T: RefCountable> Drop for Ref<T> {
98    fn drop(&mut self) {
99        unsafe {
100            RefCountable::dec_ref(&self.contents);
101        }
102    }
103}
104
105impl<T: RefCountable> Clone for Ref<T> {
106    fn clone(&self) -> Self {
107        unsafe { RefCountable::inc_ref(&self.contents) }
108    }
109}
110
111impl<T: RefCountable + Display> Display for Ref<T> {
112    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
113        self.contents.fmt(f)
114    }
115}
116
117impl<T: RefCountable + Debug> Debug for Ref<T> {
118    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
119        self.contents.fmt(f)
120    }
121}
122
123impl<T: RefCountable + PartialEq> PartialEq for Ref<T> {
124    fn eq(&self, other: &Self) -> bool {
125        self.contents.eq(&other.contents)
126    }
127}
128
129impl<T: RefCountable + Eq> Eq for Ref<T> {}
130
131impl<T: RefCountable + Hash> Hash for Ref<T> {
132    fn hash<H: Hasher>(&self, state: &mut H) {
133        self.contents.hash(state);
134    }
135}
136
137// Guard provides access to a core-allocated resource whose
138// reference is held indirectly (e.g. a core-allocated array
139// of raw `*mut BNRawT`).
140//
141// This wrapper is necessary because rust wrappers around
142// core objects can be bigger than the raw pointer to the core
143// object. This lets us create the full wrapper object and ensure
144// that it does not outlive the core-allocated array (or similar)
145// that our object came from.
146pub struct Guard<'a, T> {
147    contents: T,
148    _guard: PhantomData<&'a ()>,
149}
150
151impl<'a, T> Guard<'a, T> {
152    pub(crate) unsafe fn new<O: 'a>(contents: T, _owner: &O) -> Self {
153        Self {
154            contents,
155            _guard: PhantomData,
156        }
157    }
158}
159
160impl<T> Debug for Guard<'_, T>
161where
162    T: Debug,
163{
164    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
165        self.contents.fmt(f)
166    }
167}
168
169#[allow(private_bounds)]
170impl<T> Guard<'_, T>
171where
172    T: RefCountable,
173{
174    #[allow(clippy::should_implement_trait)] // This _is_ out own (lite) version of that trait
175    pub fn clone(&self) -> Ref<T> {
176        unsafe { <T as RefCountable>::inc_ref(&self.contents) }
177    }
178}
179
180impl<T> AsRef<T> for Guard<'_, T> {
181    fn as_ref(&self) -> &T {
182        &self.contents
183    }
184}
185
186impl<T> Deref for Guard<'_, T> {
187    type Target = T;
188
189    fn deref(&self) -> &T {
190        &self.contents
191    }
192}
193
194impl<T> DerefMut for Guard<'_, T> {
195    fn deref_mut(&mut self) -> &mut T {
196        &mut self.contents
197    }
198}
199
200impl<T> Borrow<T> for Guard<'_, T> {
201    fn borrow(&self) -> &T {
202        &self.contents
203    }
204}
205
206pub trait CoreArrayProvider {
207    type Raw;
208    type Context;
209    type Wrapped<'a>
210    where
211        Self: 'a;
212}
213
214pub(crate) unsafe trait CoreArrayProviderInner: CoreArrayProvider {
215    unsafe fn free(raw: *mut Self::Raw, count: usize, context: &Self::Context);
216    unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a>;
217}
218
219// TODO: I would really like if we impld Debug for this, but lifetimes are hard!
220#[allow(private_bounds)]
221pub struct Array<P: CoreArrayProviderInner> {
222    contents: *mut P::Raw,
223    count: usize,
224    context: P::Context,
225}
226
227#[allow(private_bounds)]
228impl<P: CoreArrayProviderInner> Array<P> {
229    pub(crate) unsafe fn new(raw: *mut P::Raw, count: usize, context: P::Context) -> Self {
230        Self {
231            contents: raw,
232            count,
233            context,
234        }
235    }
236
237    #[inline]
238    pub fn len(&self) -> usize {
239        self.count
240    }
241
242    #[inline]
243    pub fn is_empty(&self) -> bool {
244        self.count == 0
245    }
246
247    pub fn to_vec(&self) -> Vec<P::Wrapped<'_>> {
248        let mut res = Vec::with_capacity(self.count);
249        res.extend(self.iter());
250        res
251    }
252
253    #[inline]
254    pub fn get(&self, index: usize) -> P::Wrapped<'_> {
255        unsafe {
256            let backing = slice::from_raw_parts(self.contents, self.count);
257            P::wrap_raw(&backing[index], &self.context)
258        }
259    }
260
261    pub fn iter(&self) -> ArrayIter<'_, P> {
262        ArrayIter {
263            it: unsafe { slice::from_raw_parts(self.contents, self.count).iter() },
264            context: &self.context,
265        }
266    }
267}
268
269unsafe impl<P> Sync for Array<P>
270where
271    P: CoreArrayProviderInner,
272    P::Context: Sync,
273{
274}
275unsafe impl<P> Send for Array<P>
276where
277    P: CoreArrayProviderInner,
278    P::Context: Send,
279{
280}
281
282impl<'a, P: CoreArrayProviderInner> IntoIterator for &'a Array<P> {
283    type Item = P::Wrapped<'a>;
284    type IntoIter = ArrayIter<'a, P>;
285
286    fn into_iter(self) -> Self::IntoIter {
287        self.iter()
288    }
289}
290
291impl<P: CoreArrayProviderInner> Drop for Array<P> {
292    fn drop(&mut self) {
293        unsafe {
294            P::free(self.contents, self.count, &self.context);
295        }
296    }
297}
298
299#[allow(private_bounds)]
300pub struct ArrayGuard<P: CoreArrayProviderInner> {
301    contents: *mut P::Raw,
302    count: usize,
303    context: P::Context,
304}
305
306unsafe impl<P> Sync for ArrayGuard<P>
307where
308    P: CoreArrayProviderInner,
309    P::Context: Sync,
310{
311}
312unsafe impl<P> Send for ArrayGuard<P>
313where
314    P: CoreArrayProviderInner,
315    P::Context: Send,
316{
317}
318
319#[allow(private_bounds)]
320impl<P: CoreArrayProviderInner> ArrayGuard<P> {
321    #[inline]
322    pub fn len(&self) -> usize {
323        self.count
324    }
325
326    #[inline]
327    pub fn is_empty(&self) -> bool {
328        self.count == 0
329    }
330}
331
332#[allow(private_bounds)]
333impl<P: CoreArrayProviderInner> ArrayGuard<P> {
334    #[inline]
335    pub fn get(&self, index: usize) -> P::Wrapped<'_> {
336        unsafe {
337            let backing = slice::from_raw_parts(self.contents, self.count);
338            P::wrap_raw(&backing[index], &self.context)
339        }
340    }
341
342    pub fn iter(&self) -> ArrayIter<'_, P> {
343        ArrayIter {
344            it: unsafe { slice::from_raw_parts(self.contents, self.count).iter() },
345            context: &self.context,
346        }
347    }
348}
349
350impl<'a, P: CoreArrayProviderInner> IntoIterator for &'a ArrayGuard<P> {
351    type Item = P::Wrapped<'a>;
352    type IntoIter = ArrayIter<'a, P>;
353
354    fn into_iter(self) -> Self::IntoIter {
355        self.iter()
356    }
357}
358
359#[allow(private_bounds)]
360pub struct ArrayIter<'a, P>
361where
362    P: CoreArrayProviderInner,
363{
364    it: slice::Iter<'a, P::Raw>,
365    context: &'a P::Context,
366}
367
368unsafe impl<P> Send for ArrayIter<'_, P>
369where
370    P: CoreArrayProviderInner,
371    P::Context: Sync,
372{
373}
374
375impl<'a, P> Iterator for ArrayIter<'a, P>
376where
377    P: 'a + CoreArrayProviderInner,
378{
379    type Item = P::Wrapped<'a>;
380
381    #[inline]
382    fn next(&mut self) -> Option<Self::Item> {
383        self.it
384            .next()
385            .map(|r| unsafe { P::wrap_raw(r, self.context) })
386    }
387
388    #[inline]
389    fn size_hint(&self) -> (usize, Option<usize>) {
390        self.it.size_hint()
391    }
392}
393
394impl<'a, P> ExactSizeIterator for ArrayIter<'a, P>
395where
396    P: 'a + CoreArrayProviderInner,
397{
398    #[inline]
399    fn len(&self) -> usize {
400        self.it.len()
401    }
402}
403
404impl<'a, P> DoubleEndedIterator for ArrayIter<'a, P>
405where
406    P: 'a + CoreArrayProviderInner,
407{
408    #[inline]
409    fn next_back(&mut self) -> Option<P::Wrapped<'a>> {
410        self.it
411            .next_back()
412            .map(|r| unsafe { P::wrap_raw(r, self.context) })
413    }
414}
415
416#[cfg(feature = "rayon")]
417use rayon::prelude::*;
418
419#[cfg(feature = "rayon")]
420use rayon::iter::plumbing::*;
421
422#[allow(private_bounds)]
423#[cfg(feature = "rayon")]
424impl<P> Array<P>
425where
426    P: CoreArrayProviderInner,
427    P::Context: Sync,
428    for<'a> P::Wrapped<'a>: Send,
429{
430    pub fn par_iter(&self) -> ParArrayIter<'_, P> {
431        ParArrayIter { it: self.iter() }
432    }
433}
434#[allow(private_bounds)]
435#[cfg(feature = "rayon")]
436pub struct ParArrayIter<'a, P>
437where
438    P: CoreArrayProviderInner,
439    ArrayIter<'a, P>: Send,
440{
441    it: ArrayIter<'a, P>,
442}
443
444#[cfg(feature = "rayon")]
445impl<'a, P> ParallelIterator for ParArrayIter<'a, P>
446where
447    P: 'a + CoreArrayProviderInner,
448    P::Wrapped<'a>: Send,
449    ArrayIter<'a, P>: Send,
450{
451    type Item = P::Wrapped<'a>;
452
453    fn drive_unindexed<C>(self, consumer: C) -> C::Result
454    where
455        C: UnindexedConsumer<Self::Item>,
456    {
457        bridge(self, consumer)
458    }
459
460    fn opt_len(&self) -> Option<usize> {
461        Some(self.it.len())
462    }
463}
464
465#[cfg(feature = "rayon")]
466impl<'a, P> IndexedParallelIterator for ParArrayIter<'a, P>
467where
468    P: 'a + CoreArrayProviderInner,
469    P::Wrapped<'a>: Send,
470    ArrayIter<'a, P>: Send,
471{
472    fn drive<C>(self, consumer: C) -> C::Result
473    where
474        C: Consumer<Self::Item>,
475    {
476        bridge(self, consumer)
477    }
478
479    fn len(&self) -> usize {
480        self.it.len()
481    }
482
483    fn with_producer<CB>(self, callback: CB) -> CB::Output
484    where
485        CB: ProducerCallback<Self::Item>,
486    {
487        callback.callback(ArrayIterProducer { it: self.it })
488    }
489}
490
491#[cfg(feature = "rayon")]
492struct ArrayIterProducer<'a, P>
493where
494    P: 'a + CoreArrayProviderInner,
495    ArrayIter<'a, P>: Send,
496{
497    it: ArrayIter<'a, P>,
498}
499
500#[cfg(feature = "rayon")]
501impl<'a, P> Producer for ArrayIterProducer<'a, P>
502where
503    P: 'a + CoreArrayProviderInner,
504    ArrayIter<'a, P>: Send,
505{
506    type Item = P::Wrapped<'a>;
507    type IntoIter = ArrayIter<'a, P>;
508
509    fn into_iter(self) -> ArrayIter<'a, P> {
510        self.it
511    }
512
513    fn split_at(self, index: usize) -> (Self, Self) {
514        let (l, r) = self.it.it.as_slice().split_at(index);
515
516        (
517            Self {
518                it: ArrayIter {
519                    it: l.iter(),
520                    context: self.it.context,
521                },
522            },
523            Self {
524                it: ArrayIter {
525                    it: r.iter(),
526                    context: self.it.context,
527                },
528            },
529        )
530    }
531}