├── .gitignore ├── Cargo.toml ├── README.md ├── LICENSE └── src ├── pin_mut.rs ├── pin_ref.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pin-cell" 3 | version = "0.2.0" 4 | repository = "https://github.com/dignifiedquire/pin-cell" 5 | documentation = "https://docs.rs/pin-cell" 6 | authors = [ 7 | "Without Boats ", 8 | "dignifiedquire " 9 | ] 10 | license = "MIT" 11 | description = "A pin-safe cell" 12 | readme = "README.md" 13 | edition = "2018" 14 | 15 | [dependencies] 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `PinCell` 2 | 3 | This library defines the `PinCell` type, a pinning variant of the standard 4 | library's `RefCell`. 5 | 6 | It is not safe to "pin project" through a `RefCell` - getting a pinned 7 | reference to something inside the `RefCell` when you have a pinned 8 | refernece to the `RefCell` - because `RefCell` is too powerful. 9 | 10 | A `PinCell` is slightly less powerful than `RefCell`: unlike a `RefCell`, 11 | one cannot get a mutable reference into a `PinCell`, only a pinned mutable 12 | reference (`Pin<&mut T>`). This makes pin projection safe, allowing you 13 | to use interior mutability with the knowledge that `T` will never actually 14 | be moved out of the `RefCell` that wraps it. 15 | 16 | 17 | ## License 18 | 19 | 20 | Licensed under MIT license. 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-2022 Without Boats 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/pin_mut.rs: -------------------------------------------------------------------------------- 1 | use core::cell::RefMut; 2 | use core::fmt; 3 | use core::ops::Deref; 4 | use core::pin::Pin; 5 | 6 | #[derive(Debug)] 7 | /// A wrapper type for a mutably borrowed value from a `PinCell`. 8 | pub struct PinMut<'a, T: ?Sized> { 9 | pub(crate) inner: Pin>, 10 | } 11 | 12 | impl<'a, T: ?Sized> Deref for PinMut<'a, T> { 13 | type Target = T; 14 | 15 | fn deref(&self) -> &T { 16 | &*self.inner 17 | } 18 | } 19 | 20 | impl<'a, T: ?Sized> PinMut<'a, T> { 21 | /// Get a pinned mutable reference to the value inside this wrapper. 22 | pub fn as_mut<'b>(orig: &'b mut PinMut<'a, T>) -> Pin<&'b mut T> { 23 | orig.inner.as_mut() 24 | } 25 | } 26 | 27 | /* TODO implement these APIs 28 | 29 | impl<'a, T: ?Sized> PinMut<'a, T> { 30 | pub fn map(orig: PinMut<'a, T>, f: F) -> PinMut<'a, U> where 31 | F: FnOnce(Pin<&mut T>) -> Pin<&mut U>, 32 | { 33 | panic!() 34 | } 35 | 36 | pub fn map_split(orig: PinMut<'a, T>, f: F) -> (PinMut<'a, U>, PinMut<'a, V>) where 37 | F: FnOnce(Pin<&mut T>) -> (Pin<&mut U>, Pin<&mut V>) 38 | { 39 | panic!() 40 | } 41 | } 42 | */ 43 | 44 | impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> { 45 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 46 | ::fmt(&**self, f) 47 | } 48 | } 49 | 50 | // TODO CoerceUnsized 51 | -------------------------------------------------------------------------------- /src/pin_ref.rs: -------------------------------------------------------------------------------- 1 | use core::cell::Ref; 2 | use core::fmt; 3 | use core::ops::Deref; 4 | use core::pin::Pin; 5 | 6 | #[derive(Debug)] 7 | /// A wrapper type for a immutably borrowed value from a `PinCell`. 8 | pub struct PinRef<'a, T: ?Sized> { 9 | pub(crate) inner: Pin>, 10 | } 11 | 12 | impl<'a, T: ?Sized> Deref for PinRef<'a, T> { 13 | type Target = T; 14 | 15 | fn deref(&self) -> &T { 16 | &*self.inner 17 | } 18 | } 19 | 20 | impl<'a, T: ?Sized> PinRef<'a, T> { 21 | /// Get a pinned reference to the value inside this wrapper. 22 | pub fn as_ref<'b>(orig: &'b PinRef<'a, T>) -> Pin<&'b T> { 23 | orig.inner.as_ref() 24 | } 25 | } 26 | 27 | /* TODO implement these APIs 28 | 29 | impl<'a, T: ?Sized> PinRef<'a, T> { 30 | pub fn clone(orig: &PinRef<'a, T>) -> PinRef<'a, T> { 31 | panic!() 32 | } 33 | 34 | pub fn map(orig: PinRef<'a, T>, f: F) -> PinRef<'a, U> where 35 | F: FnOnce(Pin<&T>) -> Pin<&U>, 36 | { 37 | panic!() 38 | } 39 | 40 | pub fn map_split(orig: PinRef<'a, T>, f: F) -> (PinRef<'a, U>, PinRef<'a, V>) where 41 | F: FnOnce(Pin<&T>) -> (Pin<&U>, Pin<&V>) 42 | { 43 | panic!() 44 | } 45 | } 46 | */ 47 | 48 | impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinRef<'a, T> { 49 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 50 | ::fmt(&**self, f) 51 | } 52 | } 53 | 54 | // TODO CoerceUnsized 55 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![deny(warnings, missing_docs, missing_debug_implementations)] 3 | //! This library defines the `PinCell` type, a pinning variant of the standard 4 | //! library's `RefCell`. 5 | //! 6 | //! It is not safe to "pin project" through a `RefCell` - getting a pinned 7 | //! reference to something inside the `RefCell` when you have a pinned 8 | //! refernece to the `RefCell` - because `RefCell` is too powerful. 9 | //! 10 | //! A `PinCell` is slightly less powerful than `RefCell`: unlike a `RefCell`, 11 | //! one cannot get a mutable reference into a `PinCell`, only a pinned mutable 12 | //! reference (`Pin<&mut T>`). This makes pin projection safe, allowing you 13 | //! to use interior mutability with the knowledge that `T` will never actually 14 | //! be moved out of the `RefCell` that wraps it. 15 | 16 | mod pin_mut; 17 | mod pin_ref; 18 | 19 | use core::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut}; 20 | use core::pin::Pin; 21 | 22 | pub use crate::pin_mut::PinMut; 23 | pub use crate::pin_ref::PinRef; 24 | 25 | /// A mutable memory location with dynamically checked borrow rules 26 | /// 27 | /// Unlike `RefCell`, this type only allows *pinned* mutable access to the 28 | /// inner value, enabling a "pin-safe" version of interior mutability. 29 | /// 30 | /// See the standard library documentation for more information. 31 | #[derive(Default, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] 32 | pub struct PinCell { 33 | inner: RefCell, 34 | } 35 | 36 | impl PinCell { 37 | /// Creates a new `PinCell` containing `value`. 38 | pub const fn new(value: T) -> PinCell { 39 | PinCell { 40 | inner: RefCell::new(value), 41 | } 42 | } 43 | } 44 | 45 | impl PinCell { 46 | /// Immutably borrows the wrapped value. 47 | /// 48 | /// The borrow lasts until the returned `Ref` exits scope. Multiple 49 | /// immutable borrows can be taken out at the same time (both pinned and 50 | /// unpinned). 51 | pub fn borrow(&self) -> Ref<'_, T> { 52 | self.inner.borrow() 53 | } 54 | 55 | /// Immutably borrows the wrapped value, returning an error if the value is 56 | /// currently mutably borrowed. 57 | /// 58 | /// The borrow lasts until the returned `Ref` exits scope. Multiple 59 | /// immutable borrows can be taken out at the same time (both pinned and 60 | /// unpinned). 61 | /// 62 | /// This is the non-panicking variant of `borrow`. 63 | pub fn try_borrow(&self) -> Result, BorrowError> { 64 | self.inner.try_borrow() 65 | } 66 | 67 | /// Mutably borrows the wrapped value, preserving its pinnedness. 68 | /// 69 | /// The borrow lasts until the returned `PinMut` or all `PinMut`s derived 70 | /// from it exit scope. The value cannot be borrowed while this borrow is 71 | /// active. 72 | pub fn borrow_mut<'a>(self: Pin<&'a Self>) -> PinMut<'a, T> { 73 | self.try_borrow_mut().expect("already borrowed") 74 | } 75 | 76 | /// Mutably borrows the wrapped value, preserving its pinnedness, 77 | /// returning an error if the value is currently borrowed. 78 | /// 79 | /// The borrow lasts until the returned `PinMut` or all `PinMut`s derived 80 | /// from it exit scope. The value cannot be borrowed while this borrow is 81 | /// active. 82 | /// 83 | /// This is the non-panicking variant of `borrow_mut`. 84 | pub fn try_borrow_mut<'a>(self: Pin<&'a Self>) -> Result, BorrowMutError> { 85 | let ref_mut: RefMut<'a, T> = Pin::get_ref(self).inner.try_borrow_mut()?; 86 | 87 | // this is a pin projection from Pin<&PinCell> to Pin> 88 | // projecting is safe because: 89 | // 90 | // - for (PinCell: Unpin) imples (RefMut: Unpin) 91 | // holds true 92 | // - PinCell does not implement Drop 93 | // 94 | // see discussion on tracking issue #49150 about pin projection 95 | // invariants 96 | let pin_ref_mut: Pin> = unsafe { Pin::new_unchecked(ref_mut) }; 97 | 98 | Ok(PinMut { inner: pin_ref_mut }) 99 | } 100 | 101 | /// Immutably borrows the wrapped value, preserving its pinnedness. 102 | /// 103 | /// The borrow lasts until the returned `PinRef` exits scope. Multiple 104 | /// immutable borrows can be taken out at the same time (both pinned and 105 | /// unpinned). 106 | pub fn borrow_pin<'a>(self: Pin<&'a Self>) -> PinRef<'a, T> { 107 | self.try_borrow_pin().expect("already mutably borrowed") 108 | } 109 | 110 | /// Immutably borrows the wrapped value, preserving its pinnedness, 111 | /// returning an error if the value is currently mutably borrowed. 112 | /// 113 | /// The borrow lasts until the returned `PinRef` exits scope. Multiple 114 | /// immutable borrows can be taken out at the same time (both pinned and 115 | /// unpinned). 116 | /// 117 | /// This is the non-panicking variant of `borrow_pin`. 118 | pub fn try_borrow_pin<'a>(self: Pin<&'a Self>) -> Result, BorrowError> { 119 | let r: Ref<'a, T> = Pin::get_ref(self).inner.try_borrow()?; 120 | 121 | // this is a pin projection from Pin<&PinCell> to Pin> 122 | // projecting is safe because: 123 | // 124 | // - for (PinCell: Unpin) imples (Ref: Unpin) 125 | // holds true 126 | // - PinCell does not implement Drop 127 | // 128 | // see discussion on tracking issue #49150 about pin projection 129 | // invariants 130 | let pin_ref: Pin> = unsafe { Pin::new_unchecked(r) }; 131 | 132 | Ok(PinRef { inner: pin_ref }) 133 | } 134 | 135 | /// Returns a raw pointer to the underlying data in this cell. 136 | pub fn as_ptr(&self) -> *mut T { 137 | self.inner.as_ptr() 138 | } 139 | 140 | /// Returns a mutable reference to the underlying data. 141 | /// 142 | /// This call borrows `PinCell` mutably (at compile-time) so there is no 143 | /// need for dynamic checks. 144 | /// 145 | /// However be cautious: this method expects self to be mutable, which is 146 | /// generally not the case when using a `PinCell`. Take a look at the 147 | /// `borrow_mut` method instead if self isn't mutable. 148 | /// 149 | /// Also, please be aware that this method is only for special 150 | /// circumstances and is usually not what you want. In case of doubt, use 151 | /// `borrow_mut` instead. 152 | pub fn get_mut(&mut self) -> &mut T { 153 | self.inner.get_mut() 154 | } 155 | } 156 | 157 | impl From for PinCell { 158 | fn from(value: T) -> PinCell { 159 | PinCell::new(value) 160 | } 161 | } 162 | 163 | impl From> for PinCell { 164 | fn from(cell: RefCell) -> PinCell { 165 | PinCell { inner: cell } 166 | } 167 | } 168 | 169 | impl Into> for PinCell { 170 | fn into(self) -> RefCell { 171 | self.inner 172 | } 173 | } 174 | 175 | // TODO CoerceUnsized 176 | --------------------------------------------------------------------------------