summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..3004718
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,129 @@
+// SRCE - Self-referential cell environments
+// Copyright (C) 2022-2023 Soni L.
+// This software is made with love by a queer trans person.
+//
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+#![cfg_attr(not(test), no_std)]
+
+//! SRCE is a way to open and close an `LCellOwner`, thus allowing the use of 
+//! `LCell` with tokio.
+//!
+//! It is based on `qcell` and `selfref`.
+//!
+//! This crate has not been audited for soundness at this time.
+
+use qcell::LCellOwner;
+use selfref::{Builder, Holder, Opaque, OperateIn};
+
+use core::pin::Pin;
+
+/// A self-referential environment of `LCell`s, with zero runtime cost.
+pub struct LCellEnvironment<'k, T: Opaque + 'k> {
+    inner: Holder<'k, T>,
+}
+
+impl<'k, T> LCellEnvironment<'k, T> where T: Opaque {
+    /// Creates a new `LCellEnvironment`.
+    ///
+    /// Works exactly like [`Holder::new_with`].
+    pub fn new_with<F>(f: F) -> Self
+    where
+        F: for<'a> FnOnce(&mut Builder<'a, T>),
+        T::Kind<'k>: Sized,
+    {
+        Self {
+            inner: Holder::new_with(f)
+        }
+    }
+}
+
+impl<'k, T> LCellEnvironment<'k, T> where T: Opaque {
+    /// Opens this LCellEnvironment for reading and writing (mutable).
+    pub fn open_rw<'i, F, R>(self: Pin<&'i mut Self>, f: F) -> R
+    where
+        F: for<'a, 'id> FnOnce(&'a mut LCellOwner<'id>, OperateIn<'id, T>) -> R,
+    {
+        unsafe {
+            self.map_unchecked_mut(|this| &mut this.inner)
+        }.into_ref().operate_in(|env| {
+            // SAFETY? we're actually unsure if this is sound!
+            // the LCellOwner is owned by us, and the borrow given to the
+            // closure is mutable if we're mutable, and shared if we're shared.
+            let guard = unsafe {
+                generativity::Guard::new(generativity::Id::new())
+            };
+            f(&mut LCellOwner::new(guard), env)
+        })
+    }
+
+    /// Opens this LCellEnvironment for reading only (shared).
+    pub fn open_ro<'i, F, R>(self: Pin<&'i Self>, f: F) -> R
+    where
+        F: for<'a, 'id> FnOnce(&'a LCellOwner<'id>, OperateIn<'id, T>) -> R,
+    {
+        unsafe {
+            self.map_unchecked(|this| &this.inner)
+        }.operate_in(|env| {
+            // SAFETY? we're actually unsure if this is sound!
+            // the LCellOwner is owned by us, and the borrow given to the
+            // closure is mutable if we're mutable, and shared if we're shared.
+            let guard = unsafe {
+                generativity::Guard::new(generativity::Id::new())
+            };
+            f(&LCellOwner::new(guard), env)
+        })
+    }
+}
+
+#[test]
+fn test() {
+    use core::cell::Cell;
+    use core::marker::PhantomData;
+    use qcell::LCell;
+
+    trait Foo {
+        fn update(&mut self);
+    }
+    trait Bar {
+        fn get(&self) -> String;
+    }
+    struct MyThing;
+    impl Foo for MyThing {
+        fn update(&mut self) {
+            println!("hello world!");
+        }
+    }
+    impl Bar for MyThing {
+        fn get(&self) -> String {
+            return String::from("hello");
+        }
+    }
+    struct IntrusiveLCell<'a, T: ?Sized> {
+        y: Cell<Option<&'a LCell<'a, dyn Bar>>>,
+        x: LCell<'a, T>,
+    }
+    struct IntrusiveLCellKey<T: ?Sized>(PhantomData<T>);
+    selfref::opaque! {
+        impl[T: ?Sized] Opaque for IntrusiveLCellKey<T> {
+            type Kind<'this> = IntrusiveLCell<'this, T>;
+        }
+    }
+    let mut holder = Box::pin(
+        LCellEnvironment::<IntrusiveLCellKey<MyThing>>::new_with(|b| b.build(
+            IntrusiveLCell {
+                x: LCell::new(MyThing),
+                y: Cell::new(None),
+            }
+        ))
+    );
+
+
+    holder.as_mut().open_rw(|owner, x| {
+        x.y.set(Some(&x.get_ref().x));
+        owner.rw(&x.x).update();
+        println!("{}", owner.ro(x.y.get().unwrap()).get());
+    });
+
+    let mut holder_dyn: Pin<Box<LCellEnvironment<IntrusiveLCellKey<dyn Foo>>>> = holder;
+}