Skip to main content

rustbasic_core/support/
str.rs

1use crate::uuid::Uuid;
2use rand::distr::{Alphanumeric, SampleString};
3
4pub struct Stringable(String);
5
6impl Stringable {
7    pub fn new(val: String) -> Self {
8        Self(val)
9    }
10
11    /// Convert the string to uppercase
12    pub fn upper(mut self) -> Self {
13        self.0 = self.0.to_uppercase();
14        self
15    }
16
17    /// Convert the string to lowercase
18    pub fn lower(mut self) -> Self {
19        self.0 = self.0.to_lowercase();
20        self
21    }
22
23    /// Append a string slice to the end of the string
24    pub fn append(mut self, val: &str) -> Self {
25        self.0.push_str(val);
26        self
27    }
28
29    /// Prepend a string slice to the beginning of the string
30    pub fn prepend(mut self, val: &str) -> Self {
31        self.0.insert_str(0, val);
32        self
33    }
34
35    /// Convert the string to a URL-friendly slug
36    pub fn slug(mut self) -> Self {
37        self.0 = Str::slug(&self.0);
38        self
39    }
40
41    /// Get the portion of the string after the first occurrence of a given value
42    pub fn after(mut self, search: &str) -> Self {
43        self.0 = Str::after(&self.0, search);
44        self
45    }
46
47    /// Get the portion of the string before the first occurrence of a given value
48    pub fn before(mut self, search: &str) -> Self {
49        self.0 = Str::before(&self.0, search);
50        self
51    }
52
53    /// Get the portion of the string between two given values
54    pub fn between(mut self, from: &str, to: &str) -> Self {
55        self.0 = Str::between(&self.0, from, to);
56        self
57    }
58
59    /// Limit the number of characters in the string
60    pub fn limit(mut self, max: usize, end: &str) -> Self {
61        self.0 = Str::limit(&self.0, max, end);
62        self
63    }
64
65    /// Replace occurrences of a search string with a replacement string
66    pub fn replace(mut self, search: &str, replace: &str) -> Self {
67        self.0 = Str::replace(search, replace, &self.0);
68        self
69    }
70
71    /// Retrieve the final String result
72    pub fn get(self) -> String {
73        self.0
74    }
75}
76
77pub struct Str;
78
79impl Str {
80    /// Membuat instance baru stringable yang lancar (Str::of($value))
81    pub fn of(value: &str) -> Stringable {
82        Stringable::new(value.to_string())
83    }
84
85    /// Menghasilkan UUID (versi 4) sebagai String (Str::uuid())
86    pub fn uuid() -> String {
87        Uuid::new_v4().to_string()
88    }
89
90    /// Menghasilkan string acak alfabet/angka dengan panjang tertentu (Str::random())
91    pub fn random(length: usize) -> String {
92        Alphanumeric.sample_string(&mut rand::rng(), length)
93    }
94
95    /// Mengonversi string menjadi slug ramah URL (Str::slug())
96    pub fn slug(title: &str) -> String {
97        title
98            .to_lowercase()
99            .chars()
100            .map(|c| if c.is_alphanumeric() { c } else { '-' })
101            .collect::<String>()
102            .split('-')
103            .filter(|s| !s.is_empty())
104            .collect::<Vec<_>>()
105            .join("-")
106    }
107
108    /// Get the portion of a string after the first occurrence of a given value
109    pub fn after(subject: &str, search: &str) -> String {
110        subject.split_once(search).map(|(_, right)| right).unwrap_or(subject).to_string()
111    }
112
113    /// Get the portion of a string before the first occurrence of a given value
114    pub fn before(subject: &str, search: &str) -> String {
115        subject.split_once(search).map(|(left, _)| left).unwrap_or(subject).to_string()
116    }
117
118    /// Get the portion of a string between two given values
119    pub fn between(subject: &str, from: &str, to: &str) -> String {
120        subject.split(from).nth(1).and_then(|s| s.split(to).next()).unwrap_or("").to_string()
121    }
122
123    /// Determine if a string contains another substring
124    pub fn contains(haystack: &str, needle: &str) -> bool {
125        haystack.contains(needle)
126    }
127
128    /// Determine if a string starts with a given substring
129    pub fn starts_with(subject: &str, needle: &str) -> bool {
130        subject.starts_with(needle)
131    }
132
133    /// Determine if a string ends with a given substring
134    pub fn ends_with(subject: &str, needle: &str) -> bool {
135        subject.ends_with(needle)
136    }
137
138    /// Determine if a string is a valid UUID
139    pub fn is_uuid(value: &str) -> bool {
140        Uuid::parse_str(value).is_ok()
141    }
142
143    /// Convert a string to lowercase
144    pub fn lower(value: &str) -> String {
145        value.to_lowercase()
146    }
147
148    /// Convert a string to uppercase
149    pub fn upper(value: &str) -> String {
150        value.to_uppercase()
151    }
152
153    /// Limit the number of characters in a string
154    pub fn limit(value: &str, max: usize, end: &str) -> String {
155        if value.chars().count() <= max {
156            value.to_string()
157        } else {
158            format!("{}{}", value.chars().take(max).collect::<String>(), end)
159        }
160    }
161
162    /// Replace all occurrences of a search string with a replacement string
163    pub fn replace(search: &str, replace: &str, subject: &str) -> String {
164        subject.replace(search, replace)
165    }
166}