1#[cfg(feature = "alloc")]
2use alloc::borrow::Cow;
3
4#[cfg(feature = "alloc")]
5use crate::to_substring_in_place;
6
7pub trait TrimLine: Sized {
11 fn trim_line(self) -> Self;
13
14 fn trim_line_start(self) -> Self;
16
17 fn trim_line_end(self) -> Self;
19}
20
21impl TrimLine for &str {
22 #[inline]
23 fn trim_line(self) -> Self {
24 self.trim_line_start().trim_line_end()
25 }
26
27 fn trim_line_start(self) -> Self {
28 let mut start = 0;
29
30 for (p, c) in self.char_indices() {
31 if c == '\n' {
32 start = p + 1;
33 } else if !c.is_whitespace() {
34 return &self[start..];
35 }
36 }
37
38 &self[self.len()..]
39 }
40
41 fn trim_line_end(self) -> Self {
42 let mut end = self.len();
43
44 for (p, c) in self.char_indices().rev() {
45 if c == '\n' {
46 end = p;
47 } else if !c.is_whitespace() {
48 return &self[..end];
49 }
50 }
51
52 &self[..0]
53 }
54}
55
56#[cfg(feature = "alloc")]
57impl<'a> TrimLine for Cow<'a, str> {
58 #[inline]
59 fn trim_line(self) -> Self {
60 match self {
61 Cow::Borrowed(s) => Cow::Borrowed(s.trim_line()),
62 Cow::Owned(s) => {
63 let ss = s.trim_line();
64
65 Cow::Owned(unsafe { to_substring_in_place!(s, ss) })
66 },
67 }
68 }
69
70 #[inline]
71 fn trim_line_start(self) -> Self {
72 match self {
73 Cow::Borrowed(s) => Cow::Borrowed(s.trim_line_start()),
74 Cow::Owned(s) => {
75 let ss = s.trim_line_start();
76
77 Cow::Owned(unsafe { to_substring_in_place!(s, ss) })
78 },
79 }
80 }
81
82 #[inline]
83 fn trim_line_end(self) -> Self {
84 match self {
85 Cow::Borrowed(s) => Cow::Borrowed(s.trim_line_end()),
86 Cow::Owned(s) => {
87 let ss = s.trim_line_end();
88
89 Cow::Owned(unsafe { to_substring_in_place!(s, ss) })
90 },
91 }
92 }
93}