summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoniEx2 <endermoneymod@gmail.com>2023-01-14 01:08:09 -0300
committerSoniEx2 <endermoneymod@gmail.com>2023-01-14 01:08:09 -0300
commit55161ce3c7a5487b0ed8597e9daa50261b549489 (patch)
tree5fc8dea2d58cdaf75d4e821a3c4724d753680c4a
[Project] Self-Ref Cell Environment
Possibly-unsound extensions to `selfref`
-rw-r--r--.gitignore2
-rw-r--r--Cargo.toml20
-rw-r--r--README.md8
-rw-r--r--src/lib.rs129
4 files changed, 159 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4fffb2f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/target
+/Cargo.lock
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..9444bf9
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,20 @@
+[package]
+name = "srce"
+version = "0.1.0"
+authors = ["SoniEx2 <endermoneymod@gmail.com>"]
+edition = "2021"
+description = "Self-Ref Cell Environments"
+license = "MIT OR Apache-2.0"
+repository = "https://soniex2.autistic.space/git-repos/srce.git"
+categories = ["no-std", "rust-patterns"]
+readme = "README.md"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+selfref = "0.4"
+qcell = {version="0.5.2", default-features=false, features=["generativity"]}
+generativity = "1.0.1"
+
+[dev-dependencies]
+selfref = {features=["alloc"]}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5decae9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# Self-Ref Cell Environment (SRCE)
+
+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.
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;
+}