a basic owning reference implementation

This commit is contained in:
numzero 2026-05-07 18:58:20 +03:00
commit 087017f9e8
5 changed files with 78 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "ownref"
version = "0.1.0"

6
Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "ownref"
version = "0.1.0"
edition = "2024"
[dependencies]

1
rustfmt.toml Normal file
View File

@ -0,0 +1 @@
hard_tabs = true

63
src/lib.rs Normal file
View File

@ -0,0 +1,63 @@
use std::{
marker::PhantomData,
mem::ManuallyDrop,
ops::{Deref, DerefMut},
ptr::{self, NonNull},
};
pub struct OwnRef<'a, T: ?Sized>(Option<NonNull<T>>, PhantomData<&'a mut T>);
impl<T: ?Sized> Drop for OwnRef<'_, T> {
fn drop(&mut self) {
let Some(p) = self.0 else { return };
unsafe { ptr::drop_in_place(p.as_ptr()) };
}
}
impl<T: ?Sized> Deref for OwnRef<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { self.0.unwrap().as_ref() }
}
}
impl<T: ?Sized> DerefMut for OwnRef<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.0.unwrap().as_mut() }
}
}
impl<T: ?Sized> OwnRef<'_, T> {
pub unsafe fn new_unchecked(p: *mut T) -> Self {
Self(Some(NonNull::new(p).unwrap()), PhantomData)
}
}
impl<'a, T: ?Sized> OwnRef<'a, T> {
pub unsafe fn from_manually_drop(p: &'a mut ManuallyDrop<T>) -> Self {
unsafe { Self::new_unchecked(p.deref_mut() as *mut _) }
}
}
impl<T: Sized> OwnRef<'_, T> {
pub fn take(mut self) -> T {
let p = self.0.take().unwrap();
unsafe { p.read() }
}
}
impl OwnRef<'_, dyn std::any::Any> {
pub fn take<U: 'static>(mut self) -> Option<U> {
if !self.is::<U>() {
return None;
}
let p = self.0.take().unwrap();
let p = p.cast::<U>();
Some(unsafe { p.read() })
}
}
#[cfg(test)]
mod tests {
use super::*;
}