string_more extends String and str with two utility traits:
StringExtfor in-place editing onStringStrExtfor the corresponding immutable operations on string slices
The crate focuses on small, allocation-aware helpers for padding, editing, boundary handling, and simple text analysis.
cargo add string_moreor add it manually:
[dependencies]
string_more = "0.4"See CHANGELOG.md for release notes and breaking changes.
use std::collections::BTreeMap;
use string_more::{StrExt, StringExt};
let centered = "rust".center('-', 2);
assert_eq!(centered, "--rust--");
let mut value = String::from(" rust\t");
value.expand_tabs_in_place(2);
value.trim_in_place();
assert_eq!(value, "rust");
assert_eq!("🦀rust".truncate_to_chars(2), "🦀r");
assert_eq!("foobar".common_prefix("foobaz"), "fooba");
let frequencies = "Hello".byte_frequencies::<BTreeMap<_, _>>();
assert_eq!(frequencies[&b'l'], 2);StringExtmutatesStringin place.StrExtleaves the original value unchanged. Most transformation methods return a newString, while some analysis and slicing helpers return borrowed&strresults.- Most text operations are based on Unicode scalar values (
char), not grapheme clusters. - Methods that accept indices use byte offsets and require valid char boundaries.
- Most text-like inputs accepted by the API can be passed as
char,&str, orStringthrough the sealedEncodeUtf8trait.
char_frequencies counts Unicode scalar values, while byte_frequencies counts UTF-8 bytes:
use std::collections::BTreeMap;
use string_more::StrExt;
let s = "·x·";
let char_frequencies = s.char_frequencies::<BTreeMap<_, _>>();
assert_eq!(char_frequencies[&'·'], 2);
assert_eq!(char_frequencies[&'x'], 1);
let byte_frequencies = s.byte_frequencies::<BTreeMap<_, _>>();
assert_eq!(byte_frequencies[&0xC2], 2);
assert_eq!(byte_frequencies[&0xB7], 2);
assert_eq!(byte_frequencies[&b'x'], 1);trim_start_in_place,trim_end_in_place,trim_in_placefill_start_in_place,fill_end_in_place,center_in_placepad_start_to_in_place,pad_end_to_in_place,center_to_in_placeenclose_in_placeexpand_tabs_in_placestrip_prefix_in_place,strip_suffix_in_placetruncate_to_chars_in_placeshift_in_placereplace_in_place
use string_more::StringExt;
let mut s = String::from(" foobar\t");
s.expand_tabs_in_place(2);
s.trim_in_place();
s.strip_prefix_in_place("foo");
s.enclose_in_place("[", "]");
assert_eq!(s, "[bar]");fill_start,fill_end,centerpad_start_to,pad_end_to,center_toencloseexpand_tabstruncate_to_charsshiftcommon_prefix,common_suffixlongest_common_substringlevenshtein_distance,hamming_distancechar_frequencies,byte_frequenciesnext_char_boundary,previous_char_boundaryjoin
use string_more::StrExt;
assert_eq!("42".pad_start_to(5, '0'), "00042");
assert_eq!("foobar".common_suffix("quxbar"), "bar");
assert_eq!("sparrow".longest_common_substring("crow"), "row");
assert_eq!(", ".join(["one", "two", "three"]), "one, two, three");use string_more::{StrExt, StringExt};
assert_eq!("Hello".fill_start("-", 3), "---Hello");
assert_eq!("Hello".fill_end("-", 3), "Hello---");
assert_eq!("Hello".center("-", 3), "---Hello---");
assert_eq!("42".center_to(5, ' '), " 42 ");
let mut s = String::from("Hello");
s.enclose_in_place("[", "]");
assert_eq!(s, "[Hello]");use string_more::{StrExt, StringExt};
assert_eq!("🦀rust".truncate_to_chars(2), "🦀r");
assert_eq!("foobar".common_prefix("foobaz"), "fooba");
assert_eq!("foobar".common_suffix("quxbar"), "bar");
let mut s = String::from("foobar");
s.strip_prefix_in_place("foo");
assert_eq!(s, "bar");use string_more::{StrExt, StringExt};
assert_eq!("🦀".next_char_boundary(2), 4);
assert_eq!("🦀".previous_char_boundary(2), 0);
let mut s = String::from("HelloWorld!");
s.shift_in_place(5, 1, ' ');
assert_eq!(s, "Hello World!");use string_more::StrExt;
assert_eq!("kitten".levenshtein_distance("sitting"), 3);
assert_eq!("karolin".hamming_distance("kathrin"), Some(3));
assert_eq!("abc🦀".longest_common_substring("zzabcx🦀y"), "abc");This crate contains a small amount of unsafe code in the in-place mutation layer.
The public API is covered by unit tests and doctests.
Contributions are welcome! Feel free to open an issue or submit a pull request.
This crate is licensed under the MIT License. See LICENSE for more details.