1#![no_std]
21#![forbid(unsafe_code)]
22#![doc(html_root_url = "https://docs.rs/trim-newlines/0.1.0")]
23
24#[cfg(doctest)]
26#[doc = include_str!("../README.md")]
27struct ReadmeDoctests;
28
29fn is_newline(c: char) -> bool {
30 c == '\r' || c == '\n'
31}
32
33#[must_use]
41pub fn trim_newlines(string: &str) -> &str {
42 string.trim_matches(is_newline)
43}
44
45#[must_use]
52pub fn trim_newlines_start(string: &str) -> &str {
53 string.trim_start_matches(is_newline)
54}
55
56#[must_use]
63pub fn trim_newlines_end(string: &str) -> &str {
64 string.trim_end_matches(is_newline)
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn both_ends() {
73 assert_eq!(trim_newlines("\n\nfoo\n\n"), "foo");
74 assert_eq!(trim_newlines("\r\n\r\nbar\r\n"), "bar");
75 assert_eq!(trim_newlines("\r\rmid\r\r"), "mid");
76 assert_eq!(trim_newlines("no"), "no");
77 assert_eq!(trim_newlines(""), "");
78 }
79
80 #[test]
81 fn start_only() {
82 assert_eq!(trim_newlines_start("\n\nfoo\n\n"), "foo\n\n");
83 assert_eq!(trim_newlines_start("\r\n\r\nbar\r\n"), "bar\r\n");
84 assert_eq!(trim_newlines_start("no"), "no");
85 }
86
87 #[test]
88 fn end_only() {
89 assert_eq!(trim_newlines_end("\n\nfoo\n\n"), "\n\nfoo");
90 assert_eq!(trim_newlines_end("\r\n\r\nbar\r\n"), "\r\n\r\nbar");
91 assert_eq!(trim_newlines_end("no"), "no");
92 }
93
94 #[test]
95 fn only_trims_newlines_not_other_whitespace() {
96 assert_eq!(trim_newlines(" spaced "), " spaced ");
97 assert_eq!(trim_newlines("\tfoo\t"), "\tfoo\t");
98 assert_eq!(trim_newlines("\n \nx\n \n"), " \nx\n ");
100 assert_eq!(trim_newlines_start("\n \nx\n \n"), " \nx\n \n");
101 assert_eq!(trim_newlines_end("\n \nx\n \n"), "\n \nx\n ");
102 }
103
104 #[test]
105 fn all_newlines() {
106 assert_eq!(trim_newlines("\n\r\n\r"), "");
107 assert_eq!(trim_newlines_start("\n\r\n\r"), "");
108 assert_eq!(trim_newlines_end("\n\r\n\r"), "");
109 }
110}