From 08a0735ddedc85e37908c78b6f0371b4cf2bffa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Tue, 15 Aug 2023 18:49:47 +0800 Subject: [PATCH] refactor: implement `RoCell` to replace `OnceCell` (#63) --- Cargo.lock | 117 ++++++++++++++++++++--------------------- adaptor/Cargo.toml | 1 - adaptor/src/adaptor.rs | 10 ++-- adaptor/src/lib.rs | 8 +++ app/src/main.rs | 4 +- config/Cargo.toml | 1 - config/src/lib.rs | 44 +++++++++------- core/Cargo.toml | 1 - core/src/blocker.rs | 6 ++- core/src/event.rs | 17 ++---- core/src/lib.rs | 2 + shared/src/lib.rs | 2 + shared/src/ro_cell.rs | 34 ++++++++++++ 13 files changed, 143 insertions(+), 104 deletions(-) create mode 100644 shared/src/ro_cell.rs diff --git a/Cargo.lock b/Cargo.lock index 7ef9775c..5b05f500 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,6 @@ dependencies = [ "color_quant", "config", "image", - "once_cell", "ratatui", "shared", "tokio", @@ -35,9 +34,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] @@ -109,9 +108,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -119,9 +118,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "f768393e7fabd388fe8409b13faa4d93ab0fef35db1508438dfdb066918bcf38" [[package]] name = "app" @@ -206,9 +205,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-buffer" @@ -296,6 +295,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", + "once_cell", "strsim", ] @@ -349,7 +349,6 @@ dependencies = [ "glob", "indexmap 2.0.0", "md-5", - "once_cell", "ratatui", "regex", "serde", @@ -372,7 +371,6 @@ dependencies = [ "futures", "indexmap 2.0.0", "notify", - "once_cell", "parking_lot", "ratatui", "serde", @@ -466,7 +464,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "crossterm_winapi", "futures-core", "libc", @@ -596,9 +594,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", "miniz_oxide", @@ -1018,9 +1016,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "malloc_buf" @@ -1241,7 +1239,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.1", + "windows-targets 0.48.2", ] [[package]] @@ -1278,9 +1276,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -1387,7 +1385,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8285baa38bdc9f879d92c0e37cb562ef38aa3aeefca22b3200186bc39242d3d5" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "cassowary", "crossterm 0.26.1", "indoc", @@ -1464,11 +1462,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", @@ -1634,12 +1632,12 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1702,18 +1700,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "dedd246497092a89beedfe2c9f176d44c1b672ea6090edc20544ade01fbb7ea0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "7d7b1fadccbbc7e19ea64708629f9d8dccd007c260d66485f20a6d41bc1cf4b3" dependencies = [ "proc-macro2", "quote", @@ -1786,11 +1784,10 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", @@ -2167,7 +2164,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.2", ] [[package]] @@ -2185,7 +2182,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.2", ] [[package]] @@ -2205,17 +2202,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.2", + "windows_aarch64_msvc 0.48.2", + "windows_i686_gnu 0.48.2", + "windows_i686_msvc 0.48.2", + "windows_x86_64_gnu 0.48.2", + "windows_x86_64_gnullvm 0.48.2", + "windows_x86_64_msvc 0.48.2", ] [[package]] @@ -2226,9 +2223,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f" [[package]] name = "windows_aarch64_msvc" @@ -2238,9 +2235,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058" [[package]] name = "windows_i686_gnu" @@ -2250,9 +2247,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd" [[package]] name = "windows_i686_msvc" @@ -2262,9 +2259,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287" [[package]] name = "windows_x86_64_gnu" @@ -2274,9 +2271,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a" [[package]] name = "windows_x86_64_gnullvm" @@ -2286,9 +2283,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d" [[package]] name = "windows_x86_64_msvc" @@ -2298,15 +2295,15 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9" [[package]] name = "winnow" -version = "0.5.4" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" +checksum = "5504cc7644f4b593cbc05c4a55bf9bd4e94b867c3c0bd440934174d50482427d" dependencies = [ "memchr", ] diff --git a/adaptor/Cargo.toml b/adaptor/Cargo.toml index 774a592e..d7c52766 100644 --- a/adaptor/Cargo.toml +++ b/adaptor/Cargo.toml @@ -12,7 +12,6 @@ anyhow = "^1" base64 = "^0" color_quant = "^1" image = "^0" -once_cell = "^1" ratatui = "^0" tokio = { version = "^1", features = [ "parking_lot" ] } diff --git a/adaptor/src/adaptor.rs b/adaptor/src/adaptor.rs index 22d3f7b1..515dbd54 100644 --- a/adaptor/src/adaptor.rs +++ b/adaptor/src/adaptor.rs @@ -2,24 +2,22 @@ use std::{path::{Path, PathBuf}, sync::atomic::{AtomicBool, Ordering}}; use anyhow::Result; use config::{preview::PreviewAdaptor, BOOT, PREVIEW}; -use once_cell::sync::Lazy; use ratatui::prelude::Rect; +use shared::RoCell; use tokio::{fs, sync::mpsc::UnboundedSender}; -use super::{Iterm2, Kitty, Ueberzug}; +use super::{Iterm2, Kitty}; use crate::Sixel; static IMAGE_SHOWN: AtomicBool = AtomicBool::new(false); #[allow(clippy::type_complexity)] -static UEBERZUG: Lazy>>> = - Lazy::new(|| if PREVIEW.adaptor.needs_ueberzug() { Ueberzug::start().ok() } else { None }); +pub(super) static UEBERZUG: RoCell>>> = + RoCell::new(); pub struct Adaptor; impl Adaptor { - pub fn init() { Lazy::force(&UEBERZUG); } - pub async fn image_show(mut path: &Path, rect: Rect) -> Result<()> { if IMAGE_SHOWN.swap(true, Ordering::Relaxed) { Self::image_hide(rect).ok(); diff --git a/adaptor/src/lib.rs b/adaptor/src/lib.rs index 8e6f2bdc..ed8c1a21 100644 --- a/adaptor/src/lib.rs +++ b/adaptor/src/lib.rs @@ -13,3 +13,11 @@ use sixel::*; use ueberzug::*; pub use crate::{adaptor::*, image::*}; + +pub fn init() { + UEBERZUG.init(if config::PREVIEW.adaptor.needs_ueberzug() { + Ueberzug::start().ok() + } else { + None + }); +} diff --git a/app/src/main.rs b/app/src/main.rs index 77ae1bec..89ff02c1 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -27,7 +27,9 @@ async fn main() -> anyhow::Result<()> { config::init(); - adaptor::Adaptor::init(); + core::init(); + + adaptor::init(); App::run().await } diff --git a/config/Cargo.toml b/config/Cargo.toml index 73ee20b1..166b95dc 100644 --- a/config/Cargo.toml +++ b/config/Cargo.toml @@ -14,7 +14,6 @@ futures = "^0" glob = "^0" indexmap = "^2" md-5 = "^0" -once_cell = "^1" ratatui = "^0" regex = "^1" serde = { version = "^1", features = [ "derive" ] } diff --git a/config/src/lib.rs b/config/src/lib.rs index 6f697a1e..ca467e9e 100644 --- a/config/src/lib.rs +++ b/config/src/lib.rs @@ -1,6 +1,6 @@ #![allow(clippy::module_inception)] -use once_cell::sync::Lazy; +use shared::RoCell; mod boot; pub mod keymap; @@ -17,26 +17,30 @@ mod validation; pub(crate) use pattern::*; pub(crate) use preset::*; -static MERGED_KEYMAP: Lazy = Lazy::new(Preset::keymap); -static MERGED_THEME: Lazy = Lazy::new(Preset::theme); -static MERGED_YAZI: Lazy = Lazy::new(Preset::yazi); +static MERGED_KEYMAP: RoCell = RoCell::new(); +static MERGED_THEME: RoCell = RoCell::new(); +static MERGED_YAZI: RoCell = RoCell::new(); -pub static BOOT: Lazy = Lazy::new(Default::default); -pub static KEYMAP: Lazy = Lazy::new(Default::default); -pub static LOG: Lazy = Lazy::new(Default::default); -pub static MANAGER: Lazy = Lazy::new(Default::default); -pub static OPEN: Lazy = Lazy::new(Default::default); -pub static PREVIEW: Lazy = Lazy::new(Default::default); -pub static TASKS: Lazy = Lazy::new(Default::default); -pub static THEME: Lazy = Lazy::new(Default::default); +pub static BOOT: RoCell = RoCell::new(); +pub static KEYMAP: RoCell = RoCell::new(); +pub static LOG: RoCell = RoCell::new(); +pub static MANAGER: RoCell = RoCell::new(); +pub static OPEN: RoCell = RoCell::new(); +pub static PREVIEW: RoCell = RoCell::new(); +pub static TASKS: RoCell = RoCell::new(); +pub static THEME: RoCell = RoCell::new(); pub fn init() { - Lazy::force(&BOOT); - Lazy::force(&KEYMAP); - Lazy::force(&LOG); - Lazy::force(&MANAGER); - Lazy::force(&OPEN); - Lazy::force(&PREVIEW); - Lazy::force(&TASKS); - Lazy::force(&THEME); + MERGED_KEYMAP.with(Preset::keymap); + MERGED_THEME.with(Preset::theme); + MERGED_YAZI.with(Preset::yazi); + + BOOT.with(Default::default); + KEYMAP.with(Default::default); + LOG.with(Default::default); + MANAGER.with(Default::default); + OPEN.with(Default::default); + PREVIEW.with(Default::default); + TASKS.with(Default::default); + THEME.with(Default::default); } diff --git a/core/Cargo.toml b/core/Cargo.toml index 4eac2fa8..f29f9bef 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -15,7 +15,6 @@ crossterm = "^0" futures = "^0" indexmap = "^2" notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] } -once_cell = "^1" parking_lot = "^0" ratatui = "^0" serde = "^1" diff --git a/core/src/blocker.rs b/core/src/blocker.rs index 7b06e6d5..7df45d8f 100644 --- a/core/src/blocker.rs +++ b/core/src/blocker.rs @@ -1,4 +1,6 @@ -use once_cell::sync::Lazy; +use shared::RoCell; use tokio::sync::Semaphore; -pub static BLOCKER: Lazy = Lazy::new(|| Semaphore::new(1)); +pub static BLOCKER: RoCell = RoCell::new(); + +pub(super) fn init_blocker() { BLOCKER.init(Semaphore::new(1)) } diff --git a/core/src/event.rs b/core/src/event.rs index ef124632..6f54410e 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -3,11 +3,12 @@ use std::{collections::BTreeMap, ffi::OsString, path::PathBuf}; use anyhow::Result; use config::{keymap::{Control, KeymapLayer}, open::Opener}; use crossterm::event::KeyEvent; +use shared::RoCell; use tokio::sync::{mpsc::UnboundedSender, oneshot}; use super::{files::{File, FilesOp}, input::InputOpt, manager::PreviewData, select::SelectOpt}; -static mut TX: Option> = None; +static TX: RoCell> = RoCell::new(); pub enum Event { Quit, @@ -38,21 +39,13 @@ pub enum Event { impl Event { #[inline] - pub fn init(tx: UnboundedSender) { - unsafe { - TX.replace(tx); - } - } + pub fn init(tx: UnboundedSender) { TX.init(tx); } #[inline] - pub fn emit(self) { - let tx = unsafe { TX.as_ref().unwrap() }; - tx.send(self).ok(); - } + pub fn emit(self) { TX.send(self).ok(); } pub async fn wait(self, rx: oneshot::Receiver) -> T { - let tx = unsafe { TX.as_ref().unwrap() }; - tx.send(self).ok(); + TX.send(self).ok(); rx.await.unwrap() } } diff --git a/core/src/lib.rs b/core/src/lib.rs index 35f0aa5b..0b819f3d 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -22,3 +22,5 @@ pub use blocker::*; pub use event::*; pub use highlighter::*; pub use position::*; + +pub fn init() { init_blocker(); } diff --git a/shared/src/lib.rs b/shared/src/lib.rs index b1d7811b..d94a58e6 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -4,6 +4,7 @@ mod defer; mod fns; mod fs; mod mime; +mod ro_cell; mod term; mod throttle; mod tty; @@ -14,6 +15,7 @@ pub use defer::*; pub use fns::*; pub use fs::*; pub use mime::*; +pub use ro_cell::*; pub use term::*; pub use throttle::*; pub use tty::*; diff --git a/shared/src/ro_cell.rs b/shared/src/ro_cell.rs new file mode 100644 index 00000000..6b0b8dc4 --- /dev/null +++ b/shared/src/ro_cell.rs @@ -0,0 +1,34 @@ +use std::{cell::UnsafeCell, ops::Deref}; + +// Read-only cell. It's safe to use this in a static variable, but it's not safe +// to mutate it. This is useful for storing static data that is expensive to +// initialize, but is immutable once. +pub struct RoCell(UnsafeCell>); + +unsafe impl Sync for RoCell {} + +impl RoCell { + #[inline] + pub const fn new() -> Self { Self(UnsafeCell::new(None)) } + + #[inline] + pub fn init(&self, value: T) { + unsafe { + *self.0.get() = Some(value); + } + } + + #[inline] + pub fn with(&self, f: F) + where + F: FnOnce() -> T, + { + self.init(f()); + } +} + +impl Deref for RoCell { + type Target = T; + + fn deref(&self) -> &Self::Target { unsafe { (*self.0.get()).as_ref().unwrap() } } +}