mssf_core/
mem.rs

1// ------------------------------------------------------------
2// Copyright (c) Microsoft Corporation.  All rights reserved.
3// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
4// ------------------------------------------------------------
5
6/// A pool to hold boxes to extend their lifetime.
7/// This is typically useful to build raw COM structures that require
8/// raw pointers in struct fields.
9#[derive(Debug, Default)]
10pub struct BoxPool {
11    inner: Vec<Box<dyn 'static + std::any::Any>>,
12}
13
14impl BoxPool {
15    pub fn new() -> Self {
16        Self { inner: Vec::new() }
17    }
18
19    /// Push a box into the pool, and return a raw pointer to the boxed value.
20    /// The pointer is valid as long as the pool is alive.
21    #[must_use]
22    pub fn push<T: 'static>(&mut self, b: Box<T>) -> *const T {
23        let raw = b.as_ref() as *const T;
24        self.inner.push(b);
25        raw
26    }
27
28    /// Push a Vec<T> into the pool, and return its length and a raw pointer to its data.
29    /// The pointer is valid as long as the pool is alive.
30    #[must_use]
31    pub fn push_vec<T: 'static>(&mut self, v: Vec<T>) -> (usize, *const T) {
32        let len = v.len();
33        let raw = v.as_ptr();
34        // Convert Vec<T> to Box<dyn Any>.
35        let boxed_v = Box::new(v);
36        self.inner.push(boxed_v);
37        (len, raw)
38    }
39}
40
41/// Trait to get a raw pointer from a type, using a BoxPool to hold the box.
42/// This is useful to implement conversions to raw COM types that require
43/// raw pointers in struct fields.
44pub trait GetRawWithBoxPool<T> {
45    fn get_raw_with_pool(&self, pool: &mut BoxPool) -> T;
46}
47
48/// Trait to get a raw pointer from a type.
49/// Type should implement this trait if it can return a raw pointer without BoxPool.
50pub trait GetRaw<T> {
51    fn get_raw(&self) -> T;
52}
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57
58    #[test]
59    fn test_box_pool() {
60        let mut pool = BoxPool::new();
61        let b = Box::new(42);
62        let raw = pool.push(b);
63        assert_eq!(unsafe { *raw }, 42);
64
65        let v = vec![1, 2, 3];
66        let (len, raw_v) = pool.push_vec(v);
67        assert_eq!(len, 3);
68        assert_eq!(unsafe { *raw_v }, 1);
69    }
70}