From b764c38436fcb9426eb7da3be4f5fbcd63b316f5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 28 Mar 2020 11:01:25 +0100 Subject: Start stdx This crate will hold everything to small to be worth publishing --- crates/stdx/Cargo.toml | 11 ++++++++ crates/stdx/src/lib.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 crates/stdx/Cargo.toml create mode 100644 crates/stdx/src/lib.rs (limited to 'crates/stdx') 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 @@ +[package] +name = "stdx" +version = "0.1.0" +authors = ["rust-analyzer developers"] +edition = "2018" + +[lib] +doctest = false + +[dependencies] +# 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..a01ca6d4d --- /dev/null +++ b/crates/stdx/src/lib.rs @@ -0,0 +1,75 @@ +//! Missing batteries for standard libraries. + +use std::{cell::Cell, fmt}; + +/// Appends formatted string to a `String`. +#[macro_export] +macro_rules! format_to { + (&buf:expr) => (); + ($buf:expr, $lit:literal $($arg:tt)*) => { + { use ::std::fmt::Write as _; let _ = ::std::write!($buf, $lit $($arg)*); } + }; +} + +pub trait SepBy: Sized { + /// Returns an `impl fmt::Display`, which joins elements via a separator. + fn sep_by<'a>(self, sep: &'a str) -> SepByBuilder<'a, Self>; +} + +impl SepBy for I +where + I: Iterator, + I::Item: fmt::Display, +{ + fn sep_by<'a>(self, sep: &'a std::primitive::str) -> SepByBuilder<'a, Self> { + SepByBuilder::new(sep, self) + } +} + +pub struct SepByBuilder<'a, I> { + sep: &'a str, + prefix: &'a str, + suffix: &'a str, + iter: Cell>, +} + +impl<'a, I> SepByBuilder<'a, I> { + fn new(sep: &'a str, iter: I) -> SepByBuilder<'a, I> { + SepByBuilder { sep, prefix: "", suffix: "", iter: Cell::new(Some(iter)) } + } + + pub fn prefix(mut self, prefix: &'a str) -> Self { + self.prefix = prefix; + self + } + + pub fn suffix(mut self, suffix: &'a str) -> Self { + self.suffix = suffix; + self + } + + /// Set both suffix and prefix. + pub fn surround_with(self, prefix: &'a str, suffix: &'a str) -> Self { + self.prefix(prefix).suffix(suffix) + } +} + +impl fmt::Display for SepByBuilder<'_, I> +where + I: Iterator, + I::Item: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.prefix)?; + let mut first = true; + for item in self.iter.take().unwrap() { + if !first { + f.write_str(self.sep)?; + } + first = false; + fmt::Display::fmt(&item, f)?; + } + f.write_str(self.suffix)?; + Ok(()) + } +} -- cgit v1.2.3