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}