Skip to main content

windjammer_runtime/
strings.rs

1//! String utilities
2//!
3//! Windjammer's `std::strings` module maps to these functions.
4
5/// Convert to uppercase
6pub fn to_upper<S: AsRef<str>>(s: S) -> String {
7    s.as_ref().to_uppercase()
8}
9
10/// Convert to lowercase
11pub fn to_lower<S: AsRef<str>>(s: S) -> String {
12    s.as_ref().to_lowercase()
13}
14
15/// Trim whitespace
16pub fn trim<S: AsRef<str>>(s: S) -> String {
17    s.as_ref().trim().to_string()
18}
19
20/// Split string by delimiter
21pub fn split<S: AsRef<str>>(s: S, delimiter: &str) -> Vec<String> {
22    s.as_ref().split(delimiter).map(|s| s.to_string()).collect()
23}
24
25/// Join strings with delimiter
26pub fn join(parts: &[String], delimiter: &str) -> String {
27    parts.join(delimiter)
28}
29
30/// Check if string contains substring
31pub fn contains<S: AsRef<str>>(s: S, substring: &str) -> bool {
32    s.as_ref().contains(substring)
33}
34
35/// Check if string starts with prefix
36pub fn starts_with<S: AsRef<str>>(s: S, prefix: &str) -> bool {
37    s.as_ref().starts_with(prefix)
38}
39
40/// Check if string ends with suffix
41pub fn ends_with<S: AsRef<str>>(s: S, suffix: &str) -> bool {
42    s.as_ref().ends_with(suffix)
43}
44
45/// Replace all occurrences
46pub fn replace<S: AsRef<str>>(s: S, from: &str, to: &str) -> String {
47    s.as_ref().replace(from, to)
48}
49
50/// Get substring from start to end index (exclusive)
51pub fn substring<S: AsRef<str>>(s: S, start: usize, end: usize) -> String {
52    s.as_ref()
53        .chars()
54        .skip(start)
55        .take(end.saturating_sub(start))
56        .collect()
57}
58
59/// Get string length
60pub fn len<S: AsRef<str>>(s: S) -> usize {
61    s.as_ref().len()
62}
63
64/// Check if string is empty
65pub fn is_empty<S: AsRef<str>>(s: S) -> bool {
66    s.as_ref().is_empty()
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_case_conversion() {
75        assert_eq!(to_upper("hello"), "HELLO");
76        assert_eq!(to_lower("WORLD"), "world");
77    }
78
79    #[test]
80    fn test_trim() {
81        assert_eq!(trim("  hello  "), "hello");
82    }
83
84    #[test]
85    fn test_split_join() {
86        let parts = split("a,b,c", ",");
87        assert_eq!(parts, vec!["a", "b", "c"]);
88        assert_eq!(join(&parts, "-"), "a-b-c");
89    }
90
91    #[test]
92    fn test_contains() {
93        assert!(contains("hello world", "world"));
94        assert!(!contains("hello", "goodbye"));
95    }
96
97    #[test]
98    fn test_replace() {
99        assert_eq!(replace("hello world", "world", "rust"), "hello rust");
100    }
101}