2024-07-03 00:47:58 +00:00
|
|
|
use crate::Result;
|
|
|
|
|
2024-07-03 23:12:43 +00:00
|
|
|
pub const EMPTY: &str = "";
|
|
|
|
|
2024-07-13 21:02:43 +00:00
|
|
|
/// Constant expression to bypass format! if the argument is a string literal
|
|
|
|
/// but not a format string. If the literal is a format string then String is
|
|
|
|
/// returned otherwise the input (i.e. &'static str) is returned. If multiple
|
|
|
|
/// arguments are provided the first is assumed to be a format string.
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! format_maybe {
|
|
|
|
($s:literal) => {
|
|
|
|
if $crate::is_format!($s) { std::format!($s).into() } else { $s.into() }
|
|
|
|
};
|
|
|
|
|
|
|
|
($($args:expr),*) => {
|
|
|
|
std::format!($($args),*).into()
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Constant expression to decide if a literal is a format string. Note: could
|
|
|
|
/// use some improvement.
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! is_format {
|
|
|
|
($s:literal) => {
|
|
|
|
::const_str::contains!($s, "{") && ::const_str::contains!($s, "}")
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-07-05 07:01:11 +00:00
|
|
|
/// Find the common prefix from a collection of strings and return a slice
|
|
|
|
/// ```
|
|
|
|
/// use conduit_core::utils::string::common_prefix;
|
|
|
|
/// let input = ["conduwuit", "conduit", "construct"];
|
|
|
|
/// common_prefix(&input) == "con";
|
|
|
|
/// ```
|
|
|
|
#[must_use]
|
2024-07-08 16:30:59 +00:00
|
|
|
#[allow(clippy::string_slice)]
|
2024-07-05 07:01:11 +00:00
|
|
|
pub fn common_prefix<'a>(choice: &'a [&str]) -> &'a str {
|
|
|
|
choice.first().map_or(EMPTY, move |best| {
|
|
|
|
choice.iter().skip(1).fold(*best, |best, choice| {
|
|
|
|
&best[0..choice
|
2024-07-08 16:30:59 +00:00
|
|
|
.char_indices()
|
|
|
|
.zip(best.char_indices())
|
2024-07-05 07:01:11 +00:00
|
|
|
.take_while(|&(a, b)| a == b)
|
|
|
|
.count()]
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-07-03 23:12:43 +00:00
|
|
|
#[inline]
|
|
|
|
#[must_use]
|
|
|
|
pub fn split_once_infallible<'a>(input: &'a str, delim: &'_ str) -> (&'a str, &'a str) {
|
|
|
|
input.split_once(delim).unwrap_or((input, EMPTY))
|
|
|
|
}
|
|
|
|
|
2024-07-03 00:47:58 +00:00
|
|
|
/// Parses the bytes into a string.
|
|
|
|
pub fn string_from_bytes(bytes: &[u8]) -> Result<String> {
|
|
|
|
let str: &str = str_from_bytes(bytes)?;
|
|
|
|
Ok(str.to_owned())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parses the bytes into a string.
|
|
|
|
#[inline]
|
|
|
|
pub fn str_from_bytes(bytes: &[u8]) -> Result<&str> { Ok(std::str::from_utf8(bytes)?) }
|