str-utils 0.3.7

This crate provides some traits to extend `[u8]`, `str` and `Cow<str>`.
Documentation
#[cfg(feature = "alloc")]
use alloc::borrow::Cow;

#[cfg(feature = "alloc")]
use crate::to_substring_in_place;

/// To extend `str` and `Cow<str>` with methods that trim empty lines.
///
/// Lines are separated only by LF (`\n`), and a line is empty when all of its characters are Unicode whitespace.
pub trait TrimLine: Sized {
    /// Trims empty lines from both ends of the string.
    fn trim_line(self) -> Self;

    /// Trims empty lines from the start of the string.
    fn trim_line_start(self) -> Self;

    /// Trims empty lines from the end of the string.
    fn trim_line_end(self) -> Self;
}

impl TrimLine for &str {
    #[inline]
    fn trim_line(self) -> Self {
        self.trim_line_start().trim_line_end()
    }

    fn trim_line_start(self) -> Self {
        let mut start = 0;

        for (p, c) in self.char_indices() {
            if c == '\n' {
                start = p + 1;
            } else if !c.is_whitespace() {
                return &self[start..];
            }
        }

        &self[self.len()..]
    }

    fn trim_line_end(self) -> Self {
        let mut end = self.len();

        for (p, c) in self.char_indices().rev() {
            if c == '\n' {
                end = p;
            } else if !c.is_whitespace() {
                return &self[..end];
            }
        }

        &self[..0]
    }
}

#[cfg(feature = "alloc")]
impl<'a> TrimLine for Cow<'a, str> {
    #[inline]
    fn trim_line(self) -> Self {
        match self {
            Cow::Borrowed(s) => Cow::Borrowed(s.trim_line()),
            Cow::Owned(s) => {
                let ss = s.trim_line();

                Cow::Owned(unsafe { to_substring_in_place!(s, ss) })
            },
        }
    }

    #[inline]
    fn trim_line_start(self) -> Self {
        match self {
            Cow::Borrowed(s) => Cow::Borrowed(s.trim_line_start()),
            Cow::Owned(s) => {
                let ss = s.trim_line_start();

                Cow::Owned(unsafe { to_substring_in_place!(s, ss) })
            },
        }
    }

    #[inline]
    fn trim_line_end(self) -> Self {
        match self {
            Cow::Borrowed(s) => Cow::Borrowed(s.trim_line_end()),
            Cow::Owned(s) => {
                let ss = s.trim_line_end();

                Cow::Owned(unsafe { to_substring_in_place!(s, ss) })
            },
        }
    }
}