use crate::IsNone;
use regex::Regex;
use std::borrow::Cow;
lazy_static! {
static ref STARTS_OR_ENDS_WITH_WHITESPACE: Regex = Regex::new(r"(^\s+|\s+$)").unwrap();
static ref STARTS_WITH_WHITESPACE: Regex = Regex::new(r"^\s+").unwrap();
static ref ENDS_WITH_WHITESPACE: Regex = Regex::new(r"\s+$").unwrap();
static ref CONTAINS_WHITESPACE: Regex = Regex::new(r"\s+").unwrap();
}
impl IsNone for String {
fn is_none(&self) -> bool {
self.is_empty()
}
}
impl<'a> IsNone for Cow<'a, str> {
fn is_none(&self) -> bool {
self.is_empty()
}
}
pub trait PruneTrim {
fn prune_trim(&self) -> Self;
}
pub trait PruneTrimStart {
fn prune_trim_start(&self) -> Self;
}
pub trait PruneTrimEnd {
fn prune_trim_end(&self) -> Self;
}
pub trait PruneNoWhitespace {
fn prune_no_whitespace(&self) -> Self;
}
impl PruneTrim for String {
fn prune_trim(&self) -> Self {
STARTS_OR_ENDS_WITH_WHITESPACE
.replace_all(&self, "")
.into_owned()
}
}
impl<'a> PruneTrim for Cow<'a, str> {
fn prune_trim(&self) -> Self {
Cow::Owned(
STARTS_OR_ENDS_WITH_WHITESPACE
.replace_all(&self, "")
.into_owned(),
)
}
}
impl<T> PruneTrim for Option<T>
where
T: PruneTrim + IsNone,
{
fn prune_trim(&self) -> Self {
match self {
None => None,
Some(s) => {
let s = s.prune_trim();
if s.is_none() {
None
} else {
Some(s)
}
}
}
}
}
impl<T> PruneTrim for Vec<T>
where
T: PruneTrim,
{
fn prune_trim(&self) -> Self {
self.into_iter().map(PruneTrim::prune_trim).collect()
}
}
impl PruneTrimStart for String {
fn prune_trim_start(&self) -> Self {
STARTS_WITH_WHITESPACE.replace_all(&self, "").into_owned()
}
}
impl<'a> PruneTrimStart for Cow<'a, str> {
fn prune_trim_start(&self) -> Self {
Cow::Owned(STARTS_WITH_WHITESPACE.replace_all(&self, "").into_owned())
}
}
impl<T> PruneTrimStart for Option<T>
where
T: PruneTrimStart + IsNone,
{
fn prune_trim_start(&self) -> Self {
match self {
None => None,
Some(s) => {
let s = s.prune_trim_start();
if s.is_none() {
None
} else {
Some(s)
}
}
}
}
}
impl<T> PruneTrimStart for Vec<T>
where
T: PruneTrimStart,
{
fn prune_trim_start(&self) -> Self {
self.into_iter()
.map(PruneTrimStart::prune_trim_start)
.collect()
}
}
impl PruneTrimEnd for String {
fn prune_trim_end(&self) -> Self {
ENDS_WITH_WHITESPACE.replace_all(&self, "").into_owned()
}
}
impl<'a> PruneTrimEnd for Cow<'a, str> {
fn prune_trim_end(&self) -> Self {
Cow::Owned(ENDS_WITH_WHITESPACE.replace_all(&self, "").into_owned())
}
}
impl<T> PruneTrimEnd for Option<T>
where
T: PruneTrimEnd + IsNone,
{
fn prune_trim_end(&self) -> Self {
match self {
None => None,
Some(s) => {
let s = s.prune_trim_end();
if s.is_none() {
None
} else {
Some(s)
}
}
}
}
}
impl<T> PruneTrimEnd for Vec<T>
where
T: PruneTrimEnd,
{
fn prune_trim_end(&self) -> Self {
self.into_iter().map(PruneTrimEnd::prune_trim_end).collect()
}
}
impl PruneNoWhitespace for String {
fn prune_no_whitespace(&self) -> Self {
CONTAINS_WHITESPACE.replace_all(&self, "").into_owned()
}
}
impl<'a> PruneNoWhitespace for Cow<'a, str> {
fn prune_no_whitespace(&self) -> Self {
Cow::Owned(CONTAINS_WHITESPACE.replace_all(&self, "").into_owned())
}
}
impl<T> PruneNoWhitespace for Option<T>
where
T: PruneNoWhitespace + IsNone,
{
fn prune_no_whitespace(&self) -> Self {
match self {
None => None,
Some(s) => {
let s = s.prune_no_whitespace();
if s.is_none() {
None
} else {
Some(s)
}
}
}
}
}
impl<T> PruneNoWhitespace for Vec<T>
where
T: PruneNoWhitespace,
{
fn prune_no_whitespace(&self) -> Self {
self.into_iter()
.map(PruneNoWhitespace::prune_no_whitespace)
.collect()
}
}
macro_rules! tuple_impls {
($(
($(($idx:tt)),+)
)+) => {
tuple_impls! {
$(
($((T, $idx)),+)
)+
}
};
($(
($(($T:ident, $idx:tt)),+)
)+) => {
$(
impl<T> PruneTrim for ($($T),+) where T: PruneTrim {
fn prune_trim(&self) -> Self {
(
$(self.$idx.prune_trim()),+
)
}
}
impl<T> PruneTrimStart for ($($T),+) where T: PruneTrimStart {
fn prune_trim_start(&self) -> Self {
(
$(self.$idx.prune_trim_start()),+
)
}
}
impl<T> PruneTrimEnd for ($($T),+) where T: PruneTrimEnd {
fn prune_trim_end(&self) -> Self {
(
$(self.$idx.prune_trim_end()),+
)
}
}
impl<T> PruneNoWhitespace for ($($T),+) where T: PruneNoWhitespace {
fn prune_no_whitespace(&self) -> Self {
(
$(self.$idx.prune_no_whitespace()),+
)
}
}
)+
};
}
tuple_impls! {
((0), (1))
((0), (1), (2))
((0), (1), (2), (3))
((0), (1), (2), (3), (4))
((0), (1), (2), (3), (4), (5))
((0), (1), (2), (3), (4), (5), (6))
((0), (1), (2), (3), (4), (5), (6), (7))
((0), (1), (2), (3), (4), (5), (6), (7), (8))
((0), (1), (2), (3), (4), (5), (6), (7), (8), (9))
((0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10))
((0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11))
((0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12))
}