diff options
Diffstat (limited to 'crates/stdx')
-rw-r--r-- | crates/stdx/Cargo.toml | 11 | ||||
-rw-r--r-- | crates/stdx/src/lib.rs | 75 |
2 files changed, 86 insertions, 0 deletions
diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml new file mode 100644 index 000000000..f9e380c10 --- /dev/null +++ b/crates/stdx/Cargo.toml | |||
@@ -0,0 +1,11 @@ | |||
1 | [package] | ||
2 | name = "stdx" | ||
3 | version = "0.1.0" | ||
4 | authors = ["rust-analyzer developers"] | ||
5 | edition = "2018" | ||
6 | |||
7 | [lib] | ||
8 | doctest = false | ||
9 | |||
10 | [dependencies] | ||
11 | # Think twice before adding anything here | ||
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs new file mode 100644 index 000000000..8492c17af --- /dev/null +++ b/crates/stdx/src/lib.rs | |||
@@ -0,0 +1,75 @@ | |||
1 | //! Missing batteries for standard libraries. | ||
2 | |||
3 | use std::{cell::Cell, fmt}; | ||
4 | |||
5 | /// Appends formatted string to a `String`. | ||
6 | #[macro_export] | ||
7 | macro_rules! format_to { | ||
8 | (&buf:expr) => (); | ||
9 | ($buf:expr, $lit:literal $($arg:tt)*) => { | ||
10 | { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } | ||
11 | }; | ||
12 | } | ||
13 | |||
14 | pub trait SepBy: Sized { | ||
15 | /// Returns an `impl fmt::Display`, which joins elements via a separator. | ||
16 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self>; | ||
17 | } | ||
18 | |||
19 | impl<I> SepBy for I | ||
20 | where | ||
21 | I: Iterator, | ||
22 | I::Item: fmt::Display, | ||
23 | { | ||
24 | fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self> { | ||
25 | SepByBuilder::new(sep, self) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | pub struct SepByBuilder<'a, I> { | ||
30 | sep: &'a str, | ||
31 | prefix: &'a str, | ||
32 | suffix: &'a str, | ||
33 | iter: Cell<Option<I>>, | ||
34 | } | ||
35 | |||
36 | impl<'a, I> SepByBuilder<'a, I> { | ||
37 | fn new(sep: &'a str, iter: I) -> SepByBuilder<'a, I> { | ||
38 | SepByBuilder { sep, prefix: "", suffix: "", iter: Cell::new(Some(iter)) } | ||
39 | } | ||
40 | |||
41 | pub fn prefix(mut self, prefix: &'a str) -> Self { | ||
42 | self.prefix = prefix; | ||
43 | self | ||
44 | } | ||
45 | |||
46 | pub fn suffix(mut self, suffix: &'a str) -> Self { | ||
47 | self.suffix = suffix; | ||
48 | self | ||
49 | } | ||
50 | |||
51 | /// Set both suffix and prefix. | ||
52 | pub fn surround_with(self, prefix: &'a str, suffix: &'a str) -> Self { | ||
53 | self.prefix(prefix).suffix(suffix) | ||
54 | } | ||
55 | } | ||
56 | |||
57 | impl<I> fmt::Display for SepByBuilder<'_, I> | ||
58 | where | ||
59 | I: Iterator, | ||
60 | I::Item: fmt::Display, | ||
61 | { | ||
62 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
63 | f.write_str(self.prefix)?; | ||
64 | let mut first = true; | ||
65 | for item in self.iter.take().unwrap() { | ||
66 | if !first { | ||
67 | f.write_str(self.sep)?; | ||
68 | } | ||
69 | first = false; | ||
70 | fmt::Display::fmt(&item, f)?; | ||
71 | } | ||
72 | f.write_str(self.suffix)?; | ||
73 | Ok(()) | ||
74 | } | ||
75 | } | ||