diff options
Diffstat (limited to 'crates/stdx/src')
-rw-r--r-- | crates/stdx/src/lib.rs | 95 |
1 files changed, 30 insertions, 65 deletions
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs index b65875c96..273b0f55b 100644 --- a/crates/stdx/src/lib.rs +++ b/crates/stdx/src/lib.rs | |||
@@ -1,5 +1,8 @@ | |||
1 | //! Missing batteries for standard libraries. | 1 | //! Missing batteries for standard libraries. |
2 | use std::{cell::Cell, fmt, time::Instant}; | 2 | use std::{ |
3 | sync::atomic::{AtomicUsize, Ordering}, | ||
4 | time::Instant, | ||
5 | }; | ||
3 | 6 | ||
4 | mod macros; | 7 | mod macros; |
5 | 8 | ||
@@ -8,69 +11,6 @@ pub fn is_ci() -> bool { | |||
8 | option_env!("CI").is_some() | 11 | option_env!("CI").is_some() |
9 | } | 12 | } |
10 | 13 | ||
11 | pub trait SepBy: Sized { | ||
12 | /// Returns an `impl fmt::Display`, which joins elements via a separator. | ||
13 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self>; | ||
14 | } | ||
15 | |||
16 | impl<I> SepBy for I | ||
17 | where | ||
18 | I: Iterator, | ||
19 | I::Item: fmt::Display, | ||
20 | { | ||
21 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self> { | ||
22 | SepByBuilder::new(sep, self) | ||
23 | } | ||
24 | } | ||
25 | |||
26 | pub struct SepByBuilder<'a, I> { | ||
27 | sep: &'a str, | ||
28 | prefix: &'a str, | ||
29 | suffix: &'a str, | ||
30 | iter: Cell<Option<I>>, | ||
31 | } | ||
32 | |||
33 | impl<'a, I> SepByBuilder<'a, I> { | ||
34 | fn new(sep: &'a str, iter: I) -> SepByBuilder<'a, I> { | ||
35 | SepByBuilder { sep, prefix: "", suffix: "", iter: Cell::new(Some(iter)) } | ||
36 | } | ||
37 | |||
38 | pub fn prefix(mut self, prefix: &'a str) -> Self { | ||
39 | self.prefix = prefix; | ||
40 | self | ||
41 | } | ||
42 | |||
43 | pub fn suffix(mut self, suffix: &'a str) -> Self { | ||
44 | self.suffix = suffix; | ||
45 | self | ||
46 | } | ||
47 | |||
48 | /// Set both suffix and prefix. | ||
49 | pub fn surround_with(self, prefix: &'a str, suffix: &'a str) -> Self { | ||
50 | self.prefix(prefix).suffix(suffix) | ||
51 | } | ||
52 | } | ||
53 | |||
54 | impl<I> fmt::Display for SepByBuilder<'_, I> | ||
55 | where | ||
56 | I: Iterator, | ||
57 | I::Item: fmt::Display, | ||
58 | { | ||
59 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
60 | f.write_str(self.prefix)?; | ||
61 | let mut first = true; | ||
62 | for item in self.iter.take().unwrap() { | ||
63 | if !first { | ||
64 | f.write_str(self.sep)?; | ||
65 | } | ||
66 | first = false; | ||
67 | fmt::Display::fmt(&item, f)?; | ||
68 | } | ||
69 | f.write_str(self.suffix)?; | ||
70 | Ok(()) | ||
71 | } | ||
72 | } | ||
73 | |||
74 | #[must_use] | 14 | #[must_use] |
75 | pub fn timeit(label: &'static str) -> impl Drop { | 15 | pub fn timeit(label: &'static str) -> impl Drop { |
76 | struct Guard { | 16 | struct Guard { |
@@ -80,7 +20,7 @@ pub fn timeit(label: &'static str) -> impl Drop { | |||
80 | 20 | ||
81 | impl Drop for Guard { | 21 | impl Drop for Guard { |
82 | fn drop(&mut self) { | 22 | fn drop(&mut self) { |
83 | eprintln!("{}: {:?}", self.label, self.start.elapsed()) | 23 | eprintln!("{}: {:.2?}", self.label, self.start.elapsed()) |
84 | } | 24 | } |
85 | } | 25 | } |
86 | 26 | ||
@@ -197,6 +137,31 @@ where | |||
197 | left | 137 | left |
198 | } | 138 | } |
199 | 139 | ||
140 | pub struct RacyFlag(AtomicUsize); | ||
141 | |||
142 | impl RacyFlag { | ||
143 | pub const fn new() -> RacyFlag { | ||
144 | RacyFlag(AtomicUsize::new(!0)) | ||
145 | } | ||
146 | |||
147 | pub fn get(&self, init: impl FnMut() -> bool) -> bool { | ||
148 | let mut init = Some(init); | ||
149 | self.get_impl(&mut || init.take().map_or(false, |mut f| f())) | ||
150 | } | ||
151 | |||
152 | fn get_impl(&self, init: &mut dyn FnMut() -> bool) -> bool { | ||
153 | match self.0.load(Ordering::Relaxed) { | ||
154 | 0 => false, | ||
155 | 1 => true, | ||
156 | _ => { | ||
157 | let res = init(); | ||
158 | self.0.store(if res { 1 } else { 0 }, Ordering::Relaxed); | ||
159 | res | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | |||
200 | #[cfg(test)] | 165 | #[cfg(test)] |
201 | mod tests { | 166 | mod tests { |
202 | use super::*; | 167 | use super::*; |