mutable_constant/lib.rs
1//! # `mutable-constant`
2//!
3//! This crate provides a smart pointer that allows
4//! mutation on immutable values. In most cases, this
5//! will behave like a normal smart pointer like `Box`,
6//! but it allows mutation internally when Rust would
7//! otherwise forbid it.
8//!
9//! Doing this is an unsafe operation. You will need
10//! to use `unsafe` blocks to use this crate effectively.
11//!
12//! ## Example
13//!
14//! ```
15//! use mutable_constant::Mc;
16//!
17//! let mc = Mc::new(42);
18//! let mc_ref = mc.as_ref();
19//!
20//! assert_eq!(*mc_ref, 42);
21//!
22//! unsafe {
23//! *mc.as_defiant_mut() = 43; // This would normally be a compile error
24//! }
25//!
26//! assert_eq!(*mc_ref, 43);
27//! ```
28
29#![warn(missing_docs)]
30
31mod impls;
32
33/// A smart pointer that allows mutation on immutable values.
34///
35/// This uses a `*mut T` internally, so most internal operations
36/// are unsafe. However, thanks to Rust's borrowing guarantees,
37/// many of these operations are safe when used publicly. The
38/// only operation that is not safe is `as_defiant_mut`, which
39/// creates a mutable reference in defiance of Rust's rules.
40pub struct Mc<T>(*mut T);
41
42impl<T> Mc<T> {
43 /// Creates a new `Mc` from a value.
44 ///
45 /// # Example
46 /// ```
47 /// use mutable_constant::Mc;
48 ///
49 /// let mc = Mc::new(42);
50 /// ```
51 pub fn new(t: T) -> Mc<T> {
52 Mc(Box::into_raw(Box::new(t)))
53 }
54
55 /// Gets a mutable reference to the inner value.
56 ///
57 /// # Safety
58 ///
59 /// This is unsafe because the mutable reference does
60 /// not obey the borrow checker. For example, a mutable
61 /// reference to a `Mc` can be created while there is
62 /// an immutable reference to the same `Mc`. If you do
63 /// not need this specific behavior, use `as_mut` instead.
64 ///
65 /// # Example
66 /// ```
67 /// use mutable_constant::Mc;
68 ///
69 /// let mut mc = Mc::new(42);
70 ///
71 /// unsafe {
72 /// *mc.as_defiant_mut() = 43;
73 /// }
74 /// ```
75 pub unsafe fn as_defiant_mut(&self) -> &mut T {
76 &mut *self.0
77 }
78}
79
80impl<T> Drop for Mc<T> {
81 fn drop(&mut self) {
82 unsafe {
83 drop(Box::from_raw(self.0));
84 }
85 }
86}
87
88impl<T> AsRef<T> for Mc<T> {
89 fn as_ref(&self) -> &T {
90 unsafe { &*self.0 }
91 }
92}
93
94impl<T> AsMut<T> for Mc<T> {
95 fn as_mut(&mut self) -> &mut T {
96 unsafe { &mut *self.0 }
97 }
98}