binaryninja/
rc.rs

1// Copyright 2021-2025 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    pub(crate) unsafe fn new(raw: *mut P::Raw, count: usize, context: P::Context) -> Self {
322        Self {
323            contents: raw,
324            count,
325            context,
326        }
327    }
328
329    #[inline]
330    pub fn len(&self) -> usize {
331        self.count
332    }
333
334    #[inline]
335    pub fn is_empty(&self) -> bool {
336        self.count == 0
337    }
338}
339
340#[allow(private_bounds)]
341impl<P: CoreArrayProviderInner> ArrayGuard<P> {
342    #[inline]
343    pub fn get(&self, index: usize) -> P::Wrapped<'_> {
344        unsafe {
345            let backing = slice::from_raw_parts(self.contents, self.count);
346            P::wrap_raw(&backing[index], &self.context)
347        }
348    }
349
350    pub fn iter(&self) -> ArrayIter<'_, P> {
351        ArrayIter {
352            it: unsafe { slice::from_raw_parts(self.contents, self.count).iter() },
353            context: &self.context,
354        }
355    }
356}
357
358impl<'a, P: CoreArrayProviderInner> IntoIterator for &'a ArrayGuard<P> {
359    type Item = P::Wrapped<'a>;
360    type IntoIter = ArrayIter<'a, P>;
361
362    fn into_iter(self) -> Self::IntoIter {
363        self.iter()
364    }
365}
366
367#[allow(private_bounds)]
368pub struct ArrayIter<'a, P>
369where
370    P: CoreArrayProviderInner,
371{
372    it: slice::Iter<'a, P::Raw>,
373    context: &'a P::Context,
374}
375
376unsafe impl<P> Send for ArrayIter<'_, P>
377where
378    P: CoreArrayProviderInner,
379    P::Context: Sync,
380{
381}
382
383impl<'a, P> Iterator for ArrayIter<'a, P>
384where
385    P: 'a + CoreArrayProviderInner,
386{
387    type Item = P::Wrapped<'a>;
388
389    #[inline]
390    fn next(&mut self) -> Option<Self::Item> {
391        self.it
392            .next()
393            .map(|r| unsafe { P::wrap_raw(r, self.context) })
394    }
395
396    #[inline]
397    fn size_hint(&self) -> (usize, Option<usize>) {
398        self.it.size_hint()
399    }
400}
401
402impl<'a, P> ExactSizeIterator for ArrayIter<'a, P>
403where
404    P: 'a + CoreArrayProviderInner,
405{
406    #[inline]
407    fn len(&self) -> usize {
408        self.it.len()
409    }
410}
411
412impl<'a, P> DoubleEndedIterator for ArrayIter<'a, P>
413where
414    P: 'a + CoreArrayProviderInner,
415{
416    #[inline]
417    fn next_back(&mut self) -> Option<P::Wrapped<'a>> {
418        self.it
419            .next_back()
420            .map(|r| unsafe { P::wrap_raw(r, self.context) })
421    }
422}
423
424#[cfg(feature = "rayon")]
425use rayon::prelude::*;
426
427#[cfg(feature = "rayon")]
428use rayon::iter::plumbing::*;
429
430#[allow(private_bounds)]
431#[cfg(feature = "rayon")]
432impl<P> Array<P>
433where
434    P: CoreArrayProviderInner,
435    P::Context: Sync,
436    for<'a> P::Wrapped<'a>: Send,
437{
438    pub fn par_iter(&self) -> ParArrayIter<'_, P> {
439        ParArrayIter { it: self.iter() }
440    }
441}
442#[allow(private_bounds)]
443#[cfg(feature = "rayon")]
444pub struct ParArrayIter<'a, P>
445where
446    P: CoreArrayProviderInner,
447    ArrayIter<'a, P>: Send,
448{
449    it: ArrayIter<'a, P>,
450}
451
452#[cfg(feature = "rayon")]
453impl<'a, P> ParallelIterator for ParArrayIter<'a, P>
454where
455    P: 'a + CoreArrayProviderInner,
456    P::Wrapped<'a>: Send,
457    ArrayIter<'a, P>: Send,
458{
459    type Item = P::Wrapped<'a>;
460
461    fn drive_unindexed<C>(self, consumer: C) -> C::Result
462    where
463        C: UnindexedConsumer<Self::Item>,
464    {
465        bridge(self, consumer)
466    }
467
468    fn opt_len(&self) -> Option<usize> {
469        Some(self.it.len())
470    }
471}
472
473#[cfg(feature = "rayon")]
474impl<'a, P> IndexedParallelIterator for ParArrayIter<'a, P>
475where
476    P: 'a + CoreArrayProviderInner,
477    P::Wrapped<'a>: Send,
478    ArrayIter<'a, P>: Send,
479{
480    fn drive<C>(self, consumer: C) -> C::Result
481    where
482        C: Consumer<Self::Item>,
483    {
484        bridge(self, consumer)
485    }
486
487    fn len(&self) -> usize {
488        self.it.len()
489    }
490
491    fn with_producer<CB>(self, callback: CB) -> CB::Output
492    where
493        CB: ProducerCallback<Self::Item>,
494    {
495        callback.callback(ArrayIterProducer { it: self.it })
496    }
497}
498
499#[cfg(feature = "rayon")]
500struct ArrayIterProducer<'a, P>
501where
502    P: 'a + CoreArrayProviderInner,
503    ArrayIter<'a, P>: Send,
504{
505    it: ArrayIter<'a, P>,
506}
507
508#[cfg(feature = "rayon")]
509impl<'a, P> Producer for ArrayIterProducer<'a, P>
510where
511    P: 'a + CoreArrayProviderInner,
512    ArrayIter<'a, P>: Send,
513{
514    type Item = P::Wrapped<'a>;
515    type IntoIter = ArrayIter<'a, P>;
516
517    fn into_iter(self) -> ArrayIter<'a, P> {
518        self.it
519    }
520
521    fn split_at(self, index: usize) -> (Self, Self) {
522        let (l, r) = self.it.it.as_slice().split_at(index);
523
524        (
525            Self {
526                it: ArrayIter {
527                    it: l.iter(),
528                    context: self.it.context,
529                },
530            },
531            Self {
532                it: ArrayIter {
533                    it: r.iter(),
534                    context: self.it.context,
535                },
536            },
537        )
538    }
539}