aboutsummaryrefslogtreecommitdiff
path: root/crates/stdx/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/stdx/src')
-rw-r--r--crates/stdx/src/lib.rs95
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.
2use std::{cell::Cell, fmt, time::Instant}; 2use std::{
3 sync::atomic::{AtomicUsize, Ordering},
4 time::Instant,
5};
3 6
4mod macros; 7mod 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
11pub 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
16impl<I> SepBy for I
17where
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
26pub struct SepByBuilder<'a, I> {
27 sep: &'a str,
28 prefix: &'a str,
29 suffix: &'a str,
30 iter: Cell<Option<I>>,
31}
32
33impl<'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
54impl<I> fmt::Display for SepByBuilder<'_, I>
55where
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]
75pub fn timeit(label: &'static str) -> impl Drop { 15pub 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
140pub struct RacyFlag(AtomicUsize);
141
142impl 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)]
201mod tests { 166mod tests {
202 use super::*; 167 use super::*;