diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-12-30 15:13:28 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-12-30 16:45:41 +0100 |
| commit | f70cea508cd30fa40770ea989fe2a19e715a357b (patch) | |
| tree | 731bb96b375dc8fd0f7e5a2a7e1d1fe5cb2a600e /src/model/str.rs | |
| parent | fe1f4400693690b68db5a7ec0976ba998624a740 (diff) | |
Remove index syntax in favor of accessor methods
Diffstat (limited to 'src/model/str.rs')
| -rw-r--r-- | src/model/str.rs | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/src/model/str.rs b/src/model/str.rs index d1bf9d23..9196a35a 100644 --- a/src/model/str.rs +++ b/src/model/str.rs @@ -42,16 +42,40 @@ impl Str { self } - /// The codepoints the string consists of. - pub fn codepoints(&self) -> Array { - self.as_str().chars().map(|c| Value::Str(c.into())).collect() - } - /// The grapheme clusters the string consists of. pub fn graphemes(&self) -> Array { self.as_str().graphemes(true).map(|s| Value::Str(s.into())).collect() } + /// Extract the first grapheme cluster. + pub fn first(&self) -> StrResult<Self> { + self.0 + .graphemes(true) + .next() + .map(Into::into) + .ok_or_else(string_is_empty) + } + + /// Extract the last grapheme cluster. + pub fn last(&self) -> StrResult<Self> { + self.0 + .graphemes(true) + .next_back() + .map(Into::into) + .ok_or_else(string_is_empty) + } + + /// Extract the grapheme cluster at the given index. + pub fn at(&self, index: i64) -> StrResult<Self> { + let len = self.len(); + let grapheme = self + .locate(index) + .filter(|&index| index <= self.0.len()) + .and_then(|index| self.0[index..].graphemes(true).next()) + .ok_or_else(|| out_of_bounds(index, len))?; + Ok(grapheme.into()) + } + /// Extract a contigous substring. pub fn slice(&self, start: i64, end: Option<i64>) -> StrResult<Self> { let len = self.len(); @@ -270,6 +294,12 @@ fn out_of_bounds(index: i64, len: i64) -> String { format!("string index out of bounds (index: {}, len: {})", index, len) } +/// The error message when the string is empty. +#[cold] +fn string_is_empty() -> EcoString { + "string is empty".into() +} + /// Convert an item of std's `match_indices` to a dictionary. fn match_to_dict((start, text): (usize, &str)) -> Dict { dict! { |
