diff --git a/.lock b/.lock new file mode 100644 index 0000000..e69de29 diff --git a/crates.js b/crates.js new file mode 100644 index 0000000..9bcfaa5 --- /dev/null +++ b/crates.js @@ -0,0 +1 @@ +window.ALL_CRATES = ["lazy_init"]; \ No newline at end of file diff --git a/help.html b/help.html new file mode 100644 index 0000000..21e182c --- /dev/null +++ b/help.html @@ -0,0 +1 @@ +
A wrapper for lazy initialized values.
+Unlike lazy_static
, this crate does not provide concurrency safety.
+The value MUST be used after only ONE initialization. However, it
+can be more efficient, as there is no need to check whether other threads
+are also performing initialization at the same time.
use lazy_init::LazyInit;
+
+static VALUE: LazyInit<u32> = LazyInit::new();
+assert!(!VALUE.is_init());
+// println!("{}", *VALUE); // panic: use uninitialized value
+assert_eq!(VALUE.try_get(), None);
+
+VALUE.init_by(233);
+// VALUE.init_by(666); // panic: already initialized
+assert!(VALUE.is_init());
+assert_eq!(*VALUE, 233);
+assert_eq!(VALUE.try_get(), Some(&233));
pub struct LazyInit<T> { /* private fields */ }
Gets a reference to the value.
+Returns None
if the value is not initialized.
Gets the reference to the value without checking if it is initialized.
+Must be called after initialization.
+Get a mutable reference to the value without checking if it is initialized.
+Must be called after initialization.
+U::from(self)
.\nChecks whether the value is initialized.\nCreates a new uninitialized value.\nGets a reference to the value.")
\ No newline at end of file
diff --git a/settings.html b/settings.html
new file mode 100644
index 0000000..5b088e3
--- /dev/null
+++ b/settings.html
@@ -0,0 +1 @@
+1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +
//! A wrapper for lazy initialized values.
+//!
+//! Unlike [`lazy_static`][1], this crate does not provide concurrency safety.
+//! The value **MUST** be used after only **ONE** initialization. However, it
+//! can be more efficient, as there is no need to check whether other threads
+//! are also performing initialization at the same time.
+//!
+//! # Examples
+//!
+//! ```
+//! use lazy_init::LazyInit;
+//!
+//! static VALUE: LazyInit<u32> = LazyInit::new();
+//! assert!(!VALUE.is_init());
+//! // println!("{}", *VALUE); // panic: use uninitialized value
+//! assert_eq!(VALUE.try_get(), None);
+//!
+//! VALUE.init_by(233);
+//! // VALUE.init_by(666); // panic: already initialized
+//! assert!(VALUE.is_init());
+//! assert_eq!(*VALUE, 233);
+//! assert_eq!(VALUE.try_get(), Some(&233));
+//! ```
+//!
+//! [1]: https://docs.rs/lazy_static/latest/lazy_static/
+
+#![no_std]
+
+use core::cell::UnsafeCell;
+use core::fmt;
+use core::mem::MaybeUninit;
+use core::ops::{Deref, DerefMut};
+use core::sync::atomic::{AtomicBool, Ordering};
+
+/// A wrapper of a lazy initialized value.
+///
+/// It implements [`Deref`] and [`DerefMut`]. The caller must use the dereference
+/// operation after initialization, otherwise it will panic.
+pub struct LazyInit<T> {
+ inited: AtomicBool,
+ data: UnsafeCell<MaybeUninit<T>>,
+}
+
+unsafe impl<T: Send + Sync> Sync for LazyInit<T> {}
+unsafe impl<T: Send> Send for LazyInit<T> {}
+
+impl<T> LazyInit<T> {
+ /// Creates a new uninitialized value.
+ pub const fn new() -> Self {
+ Self {
+ inited: AtomicBool::new(false),
+ data: UnsafeCell::new(MaybeUninit::uninit()),
+ }
+ }
+
+ /// Initializes the value.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the value is already initialized.
+ pub fn init_by(&self, data: T) {
+ assert!(!self.is_init());
+ unsafe { (*self.data.get()).as_mut_ptr().write(data) };
+ self.inited.store(true, Ordering::Release);
+ }
+
+ /// Checks whether the value is initialized.
+ pub fn is_init(&self) -> bool {
+ self.inited.load(Ordering::Acquire)
+ }
+
+ /// Gets a reference to the value.
+ ///
+ /// Returns [`None`] if the value is not initialized.
+ pub fn try_get(&self) -> Option<&T> {
+ if self.is_init() {
+ unsafe { Some(&*(*self.data.get()).as_ptr()) }
+ } else {
+ None
+ }
+ }
+
+ fn check_init(&self) {
+ if !self.is_init() {
+ panic!(
+ "Use uninitialized value: {:?}",
+ core::any::type_name::<Self>()
+ )
+ }
+ }
+
+ #[inline]
+ fn get(&self) -> &T {
+ self.check_init();
+ unsafe { self.get_unchecked() }
+ }
+
+ #[inline]
+ fn get_mut(&mut self) -> &mut T {
+ self.check_init();
+ unsafe { self.get_mut_unchecked() }
+ }
+
+ /// Gets the reference to the value without checking if it is initialized.
+ ///
+ /// # Safety
+ ///
+ /// Must be called after initialization.
+ #[inline]
+ pub unsafe fn get_unchecked(&self) -> &T {
+ &*(*self.data.get()).as_ptr()
+ }
+
+ /// Get a mutable reference to the value without checking if it is initialized.
+ ///
+ /// # Safety
+ ///
+ /// Must be called after initialization.
+ #[inline]
+ pub unsafe fn get_mut_unchecked(&mut self) -> &mut T {
+ &mut *(*self.data.get()).as_mut_ptr()
+ }
+}
+
+impl<T: fmt::Debug> fmt::Debug for LazyInit<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.try_get() {
+ Some(s) => write!(f, "LazyInit {{ data: ")
+ .and_then(|()| s.fmt(f))
+ .and_then(|()| write!(f, "}}")),
+ None => write!(f, "LazyInit {{ <uninitialized> }}"),
+ }
+ }
+}
+
+impl<T> Deref for LazyInit<T> {
+ type Target = T;
+ #[inline]
+ fn deref(&self) -> &T {
+ self.get()
+ }
+}
+
+impl<T> DerefMut for LazyInit<T> {
+ #[inline]
+ fn deref_mut(&mut self) -> &mut T {
+ self.get_mut()
+ }
+}
+
+impl<T> Drop for LazyInit<T> {
+ fn drop(&mut self) {
+ if self.is_init() {
+ unsafe { core::ptr::drop_in_place((*self.data.get()).as_mut_ptr()) };
+ }
+ }
+}
+
fn:
) to \
+ restrict the search to a given item kind.","Accepted kinds are: fn
, mod
, struct
, \
+ enum
, trait
, type
, macro
, \
+ and const
.","Search functions by type signature (e.g., vec -> usize
or \
+ -> vec
or String, enum:Cow -> bool
)","You can look for items with an exact name by putting double quotes around \
+ your request: \"string\"
","Look for functions that accept or return \
+ slices and \
+ arrays by writing \
+ square brackets (e.g., -> [u8]
or [] -> Option
)","Look for items inside another one by searching for a path: vec::Vec
",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value.replaceAll(" ", " ")}
`}else{error[index]=value}});output+=`