str_utils/
lib.rs

1/*!
2# str Utils
3
4This crate provides some traits to extend `[u8]`, `str` and `Cow<str>`.
5
6## Examples
7
8```rust
9# #[cfg(feature = "alloc")]
10# extern crate alloc;
11
12# #[cfg(feature = "alloc")]
13# use alloc::borrow::Cow;
14
15use str_utils::*;
16
17assert_eq!(true, "foobar".starts_with_ignore_ascii_case("FoO"));
18assert_eq!(Some(1), "photo.jpg".ends_with_ignore_ascii_case_multiple(&[".png", ".jpg", ".gif"]));
19assert_eq!(true, "http".eq_ignore_ascii_case_with_uppercase("HTTP")); // faster than `eq_ignore_ascii_case`
20assert_eq!(true, "foobar".starts_with_ignore_ascii_case("FoO"));
21
22# #[cfg(feature = "alloc")]
23assert_eq!("here is a ZERO_WIDTH_SPACE -> ​".len() - 3, "here is a ZERO_WIDTH_SPACE -> ​".remove_all_invisible_characters().len());
24
25# #[cfg(feature = "alloc")]
26assert_eq!(r"foo\% b\_r", r"foo% b_r".escape_ascii_characters(b'\\', b"%_"));
27
28assert!(!"AaBb\u{0130}Zz".is_lowercased());
29assert!(!"AaBbZz".is_ascii_lowercased());
30assert!(!"aabbßzz".is_uppercased());
31assert!(!"aabbzz".is_ascii_uppercased());
32
33# #[cfg(feature = "alloc")]
34assert_eq!("aabbi\u{0307}zz", "AaBb\u{0130}Zz".to_lowercase_cow());
35# #[cfg(feature = "alloc")]
36assert_eq!("aabb\u{0130}zz", "AaBb\u{0130}Zz".to_ascii_lowercase_cow());
37# #[cfg(feature = "alloc")]
38assert_eq!("AABBSSZZ", "aabbßzz".to_uppercase_cow());
39# #[cfg(feature = "alloc")]
40assert_eq!("AABBßZZ", "aabbßzz".to_ascii_uppercase_cow());
41
42# #[cfg(feature = "alloc")]
43assert_eq!("Line 1 Line 2 Line 2 Line 3 Line 4 Line 5", "Line 1\r\nLine 2\r\nLine 2\rLine 3\nLine 4\nLine 5".replace_newlines_with_space());
44
45# #[cfg(feature = "alloc")]
46assert_eq!("abc", Cow::from(" abc ").trim_cow()); // the `trim_cow` family of methods can be used on a `Cow<str>` to allow fluent method chaining.
47```
48
49## No Std
50
51Disable the default features to compile this crate without std.
52
53```toml
54[dependencies.str-utils]
55version = "*"
56default-features = false
57```
58*/
59
60#![cfg_attr(not(feature = "std"), no_std)]
61#![cfg_attr(docsrs, feature(doc_cfg))]
62
63// TODO eq_ignore_case_multiple
64// TODO starts_with_ignore_case_multiple
65// TODO ends_with_ignore_case_multiple
66
67#[cfg(feature = "alloc")]
68extern crate alloc;
69
70mod ends_with_ignore_ascii_case;
71mod ends_with_ignore_ascii_case_multiple;
72#[cfg(feature = "alloc")]
73mod ends_with_ignore_case;
74mod ends_with_multiple;
75mod eq_ignore_ascii_case;
76mod eq_ignore_ascii_case_multiple;
77#[cfg(feature = "unicase")]
78mod eq_ignore_case;
79mod eq_multiple;
80#[cfg(feature = "alloc")]
81mod escape_characters;
82mod is_ascii_lowercased;
83mod is_ascii_uppercased;
84mod is_lowercased;
85mod is_uppercased;
86#[cfg(feature = "alloc")]
87mod remove_all_invisible_characters;
88#[cfg(feature = "alloc")]
89mod replace_newlines_with_space;
90mod starts_with_ignore_ascii_case;
91mod starts_with_ignore_ascii_case_multiple;
92#[cfg(feature = "alloc")]
93mod starts_with_ignore_case;
94mod starts_with_multiple;
95#[cfg(feature = "alloc")]
96mod to_lowercase;
97#[cfg(feature = "alloc")]
98mod to_uppercase;
99#[cfg(feature = "alloc")]
100mod trim;
101
102pub use ends_with_ignore_ascii_case::*;
103pub use ends_with_ignore_ascii_case_multiple::*;
104#[cfg(feature = "alloc")]
105pub use ends_with_ignore_case::*;
106pub use ends_with_multiple::*;
107pub use eq_ignore_ascii_case::*;
108pub use eq_ignore_ascii_case_multiple::*;
109#[cfg(feature = "unicase")]
110pub use eq_ignore_case::*;
111pub use eq_multiple::*;
112#[cfg(feature = "alloc")]
113pub use escape_characters::*;
114pub use is_ascii_lowercased::*;
115pub use is_ascii_uppercased::*;
116pub use is_lowercased::*;
117pub use is_uppercased::*;
118#[cfg(feature = "alloc")]
119pub use remove_all_invisible_characters::*;
120#[cfg(feature = "alloc")]
121pub use replace_newlines_with_space::*;
122pub use starts_with_ignore_ascii_case::*;
123pub use starts_with_ignore_ascii_case_multiple::*;
124#[cfg(feature = "alloc")]
125pub use starts_with_ignore_case::*;
126pub use starts_with_multiple::*;
127#[cfg(feature = "alloc")]
128pub use to_lowercase::*;
129#[cfg(feature = "alloc")]
130pub use to_uppercase::*;
131#[cfg(feature = "alloc")]
132pub use trim::*;
133
134#[cfg(feature = "alloc")]
135pub(crate) unsafe fn find_substring_position(parent: &str, sub: &str) -> (usize, usize) {
136    let parent_start_address = parent.as_ptr() as usize;
137
138    let sub_start_address = sub.as_ptr() as usize;
139    let position_len = sub.len();
140
141    let position_start = sub_start_address - parent_start_address;
142
143    (position_start, position_len)
144}
145
146#[cfg(feature = "alloc")]
147pub(crate) unsafe fn into_substring_in_place(
148    mut s: String,
149    (start, len): (usize, usize),
150) -> String {
151    let bytes = s.as_mut_vec();
152
153    bytes.drain(..start);
154    bytes.truncate(len);
155
156    s
157}
158
159#[cfg(feature = "alloc")]
160macro_rules! to_substring_in_place {
161    ($parent:ident, $sub:ident) => {{
162        let position = $crate::find_substring_position($parent.as_str(), $sub);
163
164        $crate::into_substring_in_place($parent, position)
165    }};
166}
167
168#[cfg(feature = "alloc")]
169pub(crate) use to_substring_in_place;