#![deny(missing_docs)]
use std::ops::{Deref, DerefMut};
use std::fmt::{self, Display};
#[macro_export]
macro_rules! lazy_mut {
(/* empty */) => {};
($(#[$attr:meta])* let mut $N:ident: $T:ty = $e:expr; $($t:tt)*) => {
$(#[$attr])*
let mut $N: $crate::LazyMut<$T> = {
fn init() -> $T { $e }
$crate::LazyMut::Init(init)
};
lazy_mut!($($t)*);
};
($(#[$attr:meta])* static mut $N:ident: $T:ty = $e:expr; $($t:tt)*) => {
$(#[$attr])*
static mut $N: $crate::LazyMut<$T> = {
fn init() -> $T { $e }
$crate::LazyMut::Init(init)
};
lazy_mut!($($t)*);
};
($(#[$attr:meta])* pub static mut $N:ident: $T:ty = $e:expr; $($t:tt)*) => {
$(#[$attr])*
pub static mut $N: $crate::LazyMut<$T> = {
fn init() -> $T { $e }
$crate::LazyMut::Init(init)
};
lazy_mut!($($t)*);
};
($(#[$attr:meta])* pub ($($vis:tt)+) static mut $N:ident: $T:ty = $e:expr;
$($t:tt)*) => {
$(#[$attr])*
pub ($($vis)+) static mut $N: $crate::LazyMut<$T> = {
fn init() -> $T { $e }
$crate::LazyMut::Init(init)
};
lazy_mut!($($t)*);
};
}
#[derive(Clone, Debug)]
pub enum LazyMut<T> {
Init(fn() -> T),
Value(T),
}
impl<T> LazyMut<T> {
pub fn unwrap(self) -> T {
use LazyMut::*;
match self {
Init(init) => init(),
Value(val) => val,
}
}
pub fn init(&mut self) -> &mut LazyMut<T> {
use LazyMut::*;
let new = match self {
&mut Init(init) => Value(init()),
other => return other,
};
*self = new;
self
}
pub fn init_once(&mut self) -> &mut LazyMut<T> {
use LazyMut::*;
let new = match self {
&mut Init(init) => Value(init()),
_ => panic!("call to `init_once` on already initialized value"),
};
*self = new;
self
}
pub fn get(this: &LazyMut<T>) -> Option<&T> {
use LazyMut::*;
match this {
&Init(_) => None,
&Value(ref val) => Some(val),
}
}
pub fn get_mut(this: &mut LazyMut<T>) -> Option<&mut T> {
use LazyMut::*;
match this {
&mut Init(_) => None,
&mut Value(ref mut val) => Some(val),
}
}
pub fn is_initialized(&self) -> bool {
use LazyMut::*;
match self {
&Init(_) => false,
&Value(_) => true,
}
}
}
impl<T> Deref for LazyMut<T> {
type Target = T;
fn deref(&self) -> &T {
use LazyMut::*;
match self {
&Init(_) => panic!("cannot dereference uninitialized value"),
&Value(ref val) => val,
}
}
}
impl<T> DerefMut for LazyMut<T> {
fn deref_mut(&mut self) -> &mut T {
self.init();
use LazyMut::*;
match self {
&mut Init(_) => unreachable!(),
&mut Value(ref mut val) => val,
}
}
}
impl<T> Display for LazyMut<T> where T: Display {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use LazyMut::*;
match self {
&Init(_) => write!(f, "{{uninitialized}}"),
&Value(ref val) => val.fmt(f),
}
}
}