/rust/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.5.0/src/lib.rs
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2016 lazy-static.rs Developers |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or |
4 | | // https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or |
5 | | // https://opensource.org/licenses/MIT>, at your option. This file may not be |
6 | | // copied, modified, or distributed except according to those terms. |
7 | | |
8 | | /*! |
9 | | A macro for declaring lazily evaluated statics. |
10 | | |
11 | | Using this macro, it is possible to have `static`s that require code to be |
12 | | executed at runtime in order to be initialized. |
13 | | This includes anything requiring heap allocations, like vectors or hash maps, |
14 | | as well as anything that requires function calls to be computed. |
15 | | |
16 | | # Syntax |
17 | | |
18 | | ```ignore |
19 | | lazy_static! { |
20 | | [pub] static ref NAME_1: TYPE_1 = EXPR_1; |
21 | | [pub] static ref NAME_2: TYPE_2 = EXPR_2; |
22 | | ... |
23 | | [pub] static ref NAME_N: TYPE_N = EXPR_N; |
24 | | } |
25 | | ``` |
26 | | |
27 | | Attributes (including doc comments) are supported as well: |
28 | | |
29 | | ```rust |
30 | | use lazy_static::lazy_static; |
31 | | |
32 | | # fn main() { |
33 | | lazy_static! { |
34 | | /// This is an example for using doc comment attributes |
35 | | static ref EXAMPLE: u8 = 42; |
36 | | } |
37 | | # } |
38 | | ``` |
39 | | |
40 | | # Semantics |
41 | | |
42 | | For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that |
43 | | implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Attributes end up |
44 | | attaching to this type.) |
45 | | |
46 | | On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs |
47 | | can return a reference to the same object. Note that this can lead to deadlocks |
48 | | if you have multiple lazy statics that depend on each other in their initialization. |
49 | | |
50 | | Apart from the lazy initialization, the resulting "static ref" variables |
51 | | have generally the same properties as regular "static" variables: |
52 | | |
53 | | - Any type in them needs to fulfill the `Sync` trait. |
54 | | - If the type has a destructor, then it will not run when the process exits. |
55 | | |
56 | | # Example |
57 | | |
58 | | Using the macro: |
59 | | |
60 | | ```rust |
61 | | use lazy_static::lazy_static; |
62 | | use std::collections::HashMap; |
63 | | |
64 | | lazy_static! { |
65 | | static ref HASHMAP: HashMap<u32, &'static str> = { |
66 | | let mut m = HashMap::new(); |
67 | | m.insert(0, "foo"); |
68 | | m.insert(1, "bar"); |
69 | | m.insert(2, "baz"); |
70 | | m |
71 | | }; |
72 | | static ref COUNT: usize = HASHMAP.len(); |
73 | | static ref NUMBER: u32 = times_two(21); |
74 | | } |
75 | | |
76 | | fn times_two(n: u32) -> u32 { n * 2 } |
77 | | |
78 | | fn main() { |
79 | | println!("The map has {} entries.", *COUNT); |
80 | | println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap()); |
81 | | println!("A expensive calculation on a static results in: {}.", *NUMBER); |
82 | | } |
83 | | ``` |
84 | | |
85 | | # Implementation details |
86 | | |
87 | | The `Deref` implementation uses a hidden static variable that is guarded by an atomic check on each access. |
88 | | |
89 | | # Cargo features |
90 | | |
91 | | This crate provides one cargo feature: |
92 | | |
93 | | - `spin_no_std`: This allows using this crate in a no-std environment, by depending on the standalone `spin` crate. |
94 | | |
95 | | */ |
96 | | |
97 | | #![doc(html_root_url = "https://docs.rs/lazy_static/1.5.0")] |
98 | | #![no_std] |
99 | | |
100 | | #[cfg(doctest)] |
101 | | #[macro_use] |
102 | | extern crate doc_comment; |
103 | | |
104 | | #[cfg(doctest)] |
105 | | doctest!("../README.md"); |
106 | | |
107 | | #[cfg_attr(feature = "spin_no_std", path = "core_lazy.rs")] |
108 | | #[cfg_attr(not(feature = "spin_no_std"), path = "inline_lazy.rs")] |
109 | | #[doc(hidden)] |
110 | | pub mod lazy; |
111 | | |
112 | | #[doc(hidden)] |
113 | | pub use core::ops::Deref as __Deref; |
114 | | |
115 | | #[macro_export(local_inner_macros)] |
116 | | #[doc(hidden)] |
117 | | macro_rules! __lazy_static_internal { |
118 | | // optional visibility restrictions are wrapped in `()` to allow for |
119 | | // explicitly passing otherwise implicit information about private items |
120 | | ($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { |
121 | | __lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N); |
122 | | __lazy_static_internal!(@TAIL, $N : $T = $e); |
123 | | lazy_static!($($t)*); |
124 | | }; |
125 | | (@TAIL, $N:ident : $T:ty = $e:expr) => { |
126 | | impl $crate::__Deref for $N { |
127 | | type Target = $T; |
128 | 2 | fn deref(&self) -> &$T { |
129 | | #[inline(always)] |
130 | 1 | fn __static_ref_initialize() -> $T { $e } <mozjs::rust::ENGINE_STATE as core::ops::deref::Deref>::deref::__static_ref_initialize Line | Count | Source | 130 | 1 | fn __static_ref_initialize() -> $T { $e } |
Unexecuted instantiation: <colored::control::SHOULD_COLORIZE as core::ops::deref::Deref>::deref::__static_ref_initialize |
131 | | |
132 | | #[inline(always)] |
133 | 2 | fn __stability() -> &'static $T { |
134 | 2 | __lazy_static_create!(LAZY, $T); |
135 | 2 | LAZY.get(__static_ref_initialize) |
136 | 2 | } <mozjs::rust::ENGINE_STATE as core::ops::deref::Deref>::deref::__stability Line | Count | Source | 133 | 2 | fn __stability() -> &'static $T { | 134 | 2 | __lazy_static_create!(LAZY, $T); | 135 | 2 | LAZY.get(__static_ref_initialize) | 136 | 2 | } |
Unexecuted instantiation: <colored::control::SHOULD_COLORIZE as core::ops::deref::Deref>::deref::__stability |
137 | 2 | __stability() |
138 | 2 | } <mozjs::rust::ENGINE_STATE as core::ops::deref::Deref>::deref Line | Count | Source | 128 | 2 | fn deref(&self) -> &$T { | 129 | | #[inline(always)] | 130 | | fn __static_ref_initialize() -> $T { $e } | 131 | | | 132 | | #[inline(always)] | 133 | | fn __stability() -> &'static $T { | 134 | | __lazy_static_create!(LAZY, $T); | 135 | | LAZY.get(__static_ref_initialize) | 136 | | } | 137 | 2 | __stability() | 138 | 2 | } |
Unexecuted instantiation: <colored::control::SHOULD_COLORIZE as core::ops::deref::Deref>::deref |
139 | | } |
140 | | impl $crate::LazyStatic for $N { |
141 | 0 | fn initialize(lazy: &Self) { |
142 | 0 | let _ = &**lazy; |
143 | 0 | } Unexecuted instantiation: <mozjs::rust::ENGINE_STATE as lazy_static::LazyStatic>::initialize Unexecuted instantiation: <colored::control::SHOULD_COLORIZE as lazy_static::LazyStatic>::initialize |
144 | | } |
145 | | }; |
146 | | // `vis` is wrapped in `()` to prevent parsing ambiguity |
147 | | (@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => { |
148 | | #[allow(missing_copy_implementations)] |
149 | | #[allow(non_camel_case_types)] |
150 | | #[allow(dead_code)] |
151 | | $(#[$attr])* |
152 | | $($vis)* struct $N {__private_field: ()} |
153 | | #[doc(hidden)] |
154 | | #[allow(non_upper_case_globals)] |
155 | | $($vis)* static $N: $N = $N {__private_field: ()}; |
156 | | }; |
157 | | () => () |
158 | | } |
159 | | |
160 | | #[macro_export(local_inner_macros)] |
161 | | macro_rules! lazy_static { |
162 | | ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { |
163 | | // use `()` to explicitly forward the information about private items |
164 | | __lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*); |
165 | | }; |
166 | | ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { |
167 | | __lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*); |
168 | | }; |
169 | | ($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { |
170 | | __lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*); |
171 | | }; |
172 | | () => () |
173 | | } |
174 | | |
175 | | /// Support trait for enabling a few common operation on lazy static values. |
176 | | /// |
177 | | /// This is implemented by each defined lazy static, and |
178 | | /// used by the free functions in this crate. |
179 | | pub trait LazyStatic { |
180 | | #[doc(hidden)] |
181 | | fn initialize(lazy: &Self); |
182 | | } |
183 | | |
184 | | /// Takes a shared reference to a lazy static and initializes |
185 | | /// it if it has not been already. |
186 | | /// |
187 | | /// This can be used to control the initialization point of a lazy static. |
188 | | /// |
189 | | /// Example: |
190 | | /// |
191 | | /// ```rust |
192 | | /// use lazy_static::lazy_static; |
193 | | /// |
194 | | /// lazy_static! { |
195 | | /// static ref BUFFER: Vec<u8> = (0..255).collect(); |
196 | | /// } |
197 | | /// |
198 | | /// fn main() { |
199 | | /// lazy_static::initialize(&BUFFER); |
200 | | /// |
201 | | /// // ... |
202 | | /// work_with_initialized_data(&BUFFER); |
203 | | /// } |
204 | | /// # fn work_with_initialized_data(_: &[u8]) {} |
205 | | /// ``` |
206 | | pub fn initialize<T: LazyStatic>(lazy: &T) { |
207 | | LazyStatic::initialize(lazy); |
208 | | } |