rawn/
lib.rs

1//! # Rawn
2//! 
3//! Helper of raw pointers cleaning.
4//! 
5//! Trait [BoxRaw] is default implemented for tuples of mut raw pointers.
6//! 
7//! Struct [BoxRaws] is new type struct wrapping [BoxRaw] implemented type.
8//!  
9//! # Example
10//! ```rust
11//! use rawn::{BoxRaw, BoxRaws};
12//! 
13//! // declare a raw pointer
14//! let x: *mut u8 = Box::into_raw(Box::new(0u8));
15//! // destruct it with [`clean()`] method of trait [`BoxRaw`]
16//! x.clean();
17//! 
18//! // below code would work, but it's accessing dangling pointer,
19//! // which is already cleaned out.
20//! // rust's miri test would not pass this case.
21//! #[cfg_attr(miri, ignore)]
22//! {
23//!   unsafe {
24//!     let _ = *x;
25//!   }
26//! }
27//! 
28//! // BoxRaw is implemented for tuples of mut raw pointers.
29//! // Available tuple size is from 1 to 12.
30//! let a = Box::into_raw(Box::new(String::from("raw")));
31//! let b = Box::into_raw(Box::new(12.));
32//! let c: Box<Vec<u8>> = Box::new(vec![0, 1, 2]);
33//! let c: *mut Vec<u8> = Box::into_raw(c);
34//! 
35//! let x = (a, b, c);
36//! x.clean();
37//! 
38//! // [BoxRaws] is new type struct wrapping a tuple of raw pointers.
39//! // It implements [BowRaw] too.
40//! let a = Box::into_raw(Box::new(0u8));
41//! let b = Box::into_raw(Box::new(1u8));
42//! let raws = BoxRaws::new((a, b));
43//! raws.clean();
44//! 
45//! // [BoxRaw] is only for raw pointers which are declared using `Box::into_raw()`.
46//! // Thus, Using coerced mutable references would make errors.
47//! // Below code will panic:
48//! /*
49//! let mut c: Vec<u8> = vec![0, 1, 2];
50//! let c: *mut Vec<u8> = &mut c;
51//! c.clean();
52//! */
53//! ```
54
55pub trait BoxRaw {
56  /// clean up multiple raw pointers contained inside a tuple.
57  /// 
58  /// It's only for raw pointers which are declared using
59  /// `Box::into_raw()`.
60  /// 
61  /// Coerced mutable references would cause errors.
62  /// 
63  fn clean(self);
64}
65
66impl<X> BoxRaw for *mut X {
67  fn clean(self) {
68    unsafe {
69      let _ = Box::from_raw(self);
70    }
71  }
72}
73
74macro_rules! impl_mut_raws_for_tuple {
75  ($($T:tt),*) => {
76    paste::paste! {
77      impl<$($T,)*> BoxRaw for ($($T,)*)
78      where
79        $($T: BoxRaw,)*
80      {
81        fn clean(self) {
82          let ($([<$T:lower>],)*) = self;
83          $(
84            [<$T:lower>].clean();
85          )*
86        }
87      }
88    }
89  }
90}
91
92impl_mut_raws_for_tuple!(A);
93impl_mut_raws_for_tuple!(A, B);
94impl_mut_raws_for_tuple!(A, B, C);
95impl_mut_raws_for_tuple!(A, B, C, D);
96impl_mut_raws_for_tuple!(A, B, C, D, E);
97impl_mut_raws_for_tuple!(A, B, C, D, E, F);
98impl_mut_raws_for_tuple!(A, B, C, D, E, F, G);
99impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H);
100impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I);
101impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I, J);
102impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I, J, K);
103impl_mut_raws_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
104
105
106pub struct BoxRaws<X: BoxRaw>(pub X);
107
108impl<X: BoxRaw> BoxRaw for BoxRaws<X> {
109  fn clean(self) {
110    self.0.clean();
111  }
112}
113
114impl<X: BoxRaw> BoxRaws<X> {
115  pub fn new(raws: X) -> Self { Self(raws) }
116}
117
118
119#[cfg(test)]
120mod tests {
121  use super::*;
122
123  /// Conduct `cargo miri test`
124  #[test]
125  fn pass_miri() {
126
127    let x = Box::into_raw(Box::new(2u8));
128    x.clean();
129
130    let x = (
131      Box::into_raw(Box::new(2u8)),
132      Box::into_raw(Box::new(2u32))
133    );
134    x.clean();
135
136    let i = Box::into_raw(Box::new(0));
137
138    let x = (
139      i,
140      Box::into_raw(Box::new(2u32)),
141      Box::into_raw(Box::new(String::from("raw")))
142    );
143    x.clean();
144  }
145
146  #[test]
147  #[cfg_attr(miri, ignore)]
148  fn not_pass_miri() {
149
150    let i = Box::into_raw(Box::new(0));
151
152    let x = (
153      i,
154      Box::into_raw(Box::new(14u32))
155    );
156
157    x.clean();
158
159    unsafe {
160      // accessing dangling pointer
161      let y = *i + 10;
162      assert_eq!(y, 10);
163    }
164  }
165
166  #[test]
167  fn box_raws() {
168    let x: Box<Vec<String>> = Box::new(vec![String::from("Rome")]);
169    let x = Box::into_raw(x);
170    let y = Box::into_raw(Box::new(10i32));
171
172    (x, y).clean();
173    
174    // use struct `BoxRaws`
175    let x: Box<Vec<String>> = Box::new(vec![String::from("Rome")]);
176    let x = Box::into_raw(x);
177    let y = Box::into_raw(Box::new(10i32));
178
179    let raws = BoxRaws::new((x, y));
180    raws.clean();
181  }
182}