Skip to content

Commit 69e80ce

Browse files
committed
Import and tidy up macro from Gist
1 parent f8c24fc commit 69e80ce

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

lib.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*!
2+
Macro to declare lazily evaluated statics, which allows runtime initialization.
3+
4+
The macro works by defining a custom type with a `Deref` impl, which delegates the dereferencing
5+
to a hidden `static mut` that gets lazily initialized on first access.
6+
7+
# Examples
8+
9+
To load the extension and use it:
10+
11+
```rust,ignore
12+
13+
}
14+
```
15+
*/
16+
17+
#![crate_id = "lazy_static"]
18+
#![crate_type = "dylib"]
19+
#![license = "MIT"]
20+
21+
#![feature(macro_rules)]
22+
23+
#[macro_export]
24+
macro_rules! lazy_static {
25+
($(static ref $N:ident : $T:ty = $e:expr;)*) => {
26+
$(
27+
#[allow(non_camel_case_types)]
28+
#[allow(dead_code)]
29+
struct $N {__unit__: ()}
30+
static $N: $N = $N {__unit__: ()};
31+
impl Deref<$T> for $N {
32+
fn deref<'a>(&'a self) -> &'a $T {
33+
use std::sync::{Once, ONCE_INIT};
34+
use std::mem::transmute;
35+
36+
#[inline(always)]
37+
fn require_share<T: Share>(_: &T) { }
38+
39+
unsafe {
40+
static mut s: *$T = 0 as *$T;
41+
static mut ONCE: Once = ONCE_INIT;
42+
ONCE.doit(|| {
43+
s = transmute::<Box<$T>, *$T>(box() ($e));
44+
});
45+
let static_ref = &*s;
46+
require_share(static_ref);
47+
static_ref
48+
}
49+
}
50+
}
51+
52+
)*
53+
}
54+
}
55+
56+
#[cfg(test)]
57+
mod test {
58+
use std::collections::HashMap;
59+
60+
lazy_static! {
61+
static ref NUMBER: uint = times_two(3);
62+
static ref VEC: [Box<uint>, ..3] = [box 1, box 2, box 3];
63+
static ref OWNED_STRING: String = "hello".to_string();
64+
static ref HASHMAP: HashMap<uint, &'static str> = {
65+
let mut m = HashMap::new();
66+
m.insert(0u, "abc");
67+
m.insert(1, "def");
68+
m.insert(2, "ghi");
69+
m
70+
};
71+
static ref UNUSED: () = ();
72+
}
73+
74+
fn times_two(n: uint) -> uint {
75+
n * 2
76+
}
77+
78+
#[test]
79+
fn test_basic() {
80+
assert_eq!(OWNED_STRING.as_slice(), "hello");
81+
assert_eq!(*NUMBER, 6);
82+
assert!(HASHMAP.find(&1).is_some());
83+
assert!(HASHMAP.find(&3).is_none());
84+
assert_eq!(VEC.as_slice(), &[box 1, box 2, box 3]);
85+
}
86+
87+
#[test]
88+
fn test_repeat() {
89+
assert_eq!(*NUMBER, 6);
90+
assert_eq!(*NUMBER, 6);
91+
assert_eq!(*NUMBER, 6);
92+
}
93+
}

0 commit comments

Comments
 (0)