Skip to content

Commit 831a13a

Browse files
Yu-zhbobzhang
authored andcommitted
refactor(@string.View): API update
1 parent 9924189 commit 831a13a

11 files changed

+248
-257
lines changed

builtin/builtin.mbti

+1-1
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,8 @@ impl String {
605605
op_get(String, Int) -> Char
606606
substring(String, start~ : Int = .., end? : Int) -> String
607607
to_string(String) -> String
608+
unsafe_char_at(String, Int) -> Char
608609
unsafe_charcode_at(String, Int) -> Int
609-
unsafe_codepoint_at(String, Int) -> Char
610610
}
611611

612612
impl Option {

builtin/console.mbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ fn base64_encode_string_codepoint(s : String) -> String {
117117
for i = 0, utf16_index = 0
118118
i < codepoint_length
119119
i = i + 1, utf16_index = utf16_index + 1 {
120-
let c = s.unsafe_codepoint_at(utf16_index).to_int()
120+
let c = s.unsafe_char_at(utf16_index).to_int()
121121
if c > 0xFFFF {
122122
data[i * 4] = (c & 0xFF).to_byte()
123123
data[i * 4 + 1] = ((c >> 8) & 0xFF).to_byte()

builtin/string.mbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ pub fn String::codepoint_at(self : String, index : Int) -> Char {
133133
134134
///|
135135
/// Returns the Unicode code point at the given index without bounds checking.
136-
pub fn String::unsafe_codepoint_at(self : String, index : Int) -> Char {
136+
pub fn String::unsafe_char_at(self : String, index : Int) -> Char {
137137
let c1 = self.unsafe_charcode_at(index)
138138
if is_leading_surrogate(c1) {
139139
let c2 = self.unsafe_charcode_at(index + 1)

builtin/string_test.mbt

+5-5
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,13 @@ test "codepoint_at emoji" {
8787
}
8888

8989
///|
90-
test "unsafe_codepoint_at" {
90+
test "unsafe_char_at" {
9191
let s = "a👋b"
92-
inspect!(s.unsafe_codepoint_at(0), content="a")
93-
inspect!(s.unsafe_codepoint_at(1), content="👋")
92+
inspect!(s.unsafe_char_at(0), content="a")
93+
inspect!(s.unsafe_char_at(1), content="👋")
9494
// invalid char cannot be inspected
95-
inspect!(s.unsafe_codepoint_at(2).to_int(), content="56395")
96-
inspect!(s.unsafe_codepoint_at(3), content="b")
95+
inspect!(s.unsafe_char_at(2).to_int(), content="56395")
96+
inspect!(s.unsafe_char_at(3), content="b")
9797
}
9898

9999
///|

strconv/decimal.mbt

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ fn parse_decimal_from_view(str : @string.View) -> Decimal!StrConvError {
152152
rest => rest
153153
}
154154
// finish
155-
guard rest.length_eq(0) else { syntax_err!() }
155+
guard rest is [] else { syntax_err!() }
156156
d..trim()
157157
}
158158

string/deprecated.mbt

+104
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,107 @@ pub fn View::op_as_view(self : View, start~ : Int = 0, end? : Int) -> View {
139139
pub fn View::length(self : View) -> Int {
140140
self.char_length()
141141
}
142+
143+
///|
144+
#deprecated("use View::char_length_eq instead")
145+
pub fn length_eq(self : View, len : Int) -> Bool {
146+
self.char_length_eq(len)
147+
}
148+
149+
///|
150+
#deprecated("use View::char_length_ge instead")
151+
pub fn length_ge(self : View, len : Int) -> Bool {
152+
self.char_length_ge(len)
153+
}
154+
155+
///|
156+
/// Returns the character at the given index from the end of the string.
157+
///
158+
/// # Examples
159+
///
160+
/// ```moonbit
161+
/// let s = "Hello🤣🤣🤣"
162+
/// inspect!(s.rev_get(0), content="🤣")
163+
/// inspect!(s.rev_get(4), content="l")
164+
/// ```
165+
///
166+
/// # Panics
167+
///
168+
/// @alert unsafe "Panics if the index is out of bounds."
169+
#deprecated("use String::rev_iter().nth(index).unwrap() instead")
170+
pub fn String::rev_get(self : String, index : Int) -> Char {
171+
guard index >= 0
172+
self.nth_char(-index - 1)
173+
}
174+
175+
///|
176+
/// Test if the length of the string is equal to the given length.
177+
///
178+
/// This has O(n) complexity where n is the length in the parameter.
179+
#deprecated("use String::char_length_eq instead")
180+
pub fn String::length_eq(self : String, len : Int) -> Bool {
181+
self.char_length_eq(len)
182+
}
183+
184+
///|
185+
/// Test if the length of the string is greater than or equal to the given length.
186+
///
187+
/// This has O(n) complexity where n is the length in the parameter.
188+
#deprecated("use String::char_length_ge instead")
189+
pub fn String::length_ge(self : String, len : Int) -> Bool {
190+
self.char_length_ge(len)
191+
}
192+
193+
///|
194+
/// Return the character at the given index.
195+
///
196+
/// The time complexity is O(n) where n is the given index, as it needs to scan
197+
/// through the UTF-16 code units to find the nth Unicode character.
198+
///
199+
/// # Example
200+
///
201+
/// ```
202+
/// let str = "Hello🤣🤣🤣"
203+
/// let view = str[1:6]
204+
/// inspect!(view[0], content="e")
205+
/// inspect!(view[4], content="🤣")
206+
/// ```
207+
#deprecated("use View::iter().nth(index).unwrap() instead")
208+
pub fn View::op_get(self : View, index : Int) -> Char {
209+
guard index >= 0
210+
self.str.nth_char(index, start_offset=self.start, end_offset=self.end)
211+
}
212+
213+
///|
214+
/// Returns the character at the given index from the end of the view.
215+
///
216+
/// The time complexity is O(n) where n is the given index, as it needs to scan
217+
/// through the UTF-16 code units to find the nth Unicode character.
218+
///
219+
/// # Example
220+
///
221+
/// ```
222+
/// let str = "Hello🤣🤣🤣"
223+
/// let view = str[1:6]
224+
/// inspect!(view.rev_get(0), content="🤣")
225+
/// inspect!(view.rev_get(4), content="e")
226+
/// ```
227+
#deprecated("use View::rev_iter().nth(index).unwrap() instead")
228+
pub fn rev_get(self : View, index : Int) -> Char {
229+
guard index >= 0
230+
self.str.nth_char(-index - 1, start_offset=self.start, end_offset=self.end)
231+
}
232+
233+
///|
234+
fn String::nth_char(
235+
self : String,
236+
i : Int,
237+
start_offset~ : Int = 0,
238+
end_offset~ : Int = self.length()
239+
) -> Char {
240+
if self.offset_of_nth_char(i, start_offset~, end_offset~) is Some(index) {
241+
self.unsafe_char_at(index)
242+
} else {
243+
abort("index out of bounds")
244+
}
245+
}

string/string.mbt

+63-92
Original file line numberDiff line numberDiff line change
@@ -678,98 +678,6 @@ pub fn pad_end(self : String, total_width : Int, padding_char : Char) -> String
678678
}
679679
}
680680
681-
///|
682-
/// Returns the character at the given index from the end of the string.
683-
///
684-
/// # Examples
685-
///
686-
/// ```moonbit
687-
/// let s = "Hello🤣🤣🤣"
688-
/// inspect!(s.rev_get(0), content="🤣")
689-
/// inspect!(s.rev_get(4), content="l")
690-
/// ```
691-
///
692-
/// # Panics
693-
///
694-
/// @alert unsafe "Panics if the index is out of bounds."
695-
pub fn String::rev_get(self : String, index : Int) -> Char {
696-
guard index >= 0 else { abort("index out of bounds") }
697-
for utf16_offset = self.length() - 1, char_count = 0
698-
utf16_offset >= 0 && char_count < index
699-
utf16_offset = utf16_offset - 1, char_count = char_count + 1 {
700-
let c1 = self.unsafe_charcode_at(utf16_offset)
701-
if is_trailing_surrogate(c1) && utf16_offset - 1 >= 0 {
702-
let c2 = self.unsafe_charcode_at(utf16_offset - 1)
703-
if is_leading_surrogate(c2) {
704-
continue utf16_offset - 2, char_count + 1
705-
} else {
706-
abort("invalid surrogate pair")
707-
}
708-
}
709-
} else {
710-
guard char_count == index && utf16_offset >= 0 else {
711-
abort("index out of bounds")
712-
}
713-
let c1 = self.unsafe_charcode_at(utf16_offset)
714-
if is_trailing_surrogate(c1) && utf16_offset - 1 >= 0 {
715-
let c2 = self.unsafe_charcode_at(utf16_offset - 1)
716-
if is_leading_surrogate(c2) {
717-
code_point_of_surrogate_pair(c2, c1)
718-
} else {
719-
abort("invalid surrogate pair")
720-
}
721-
} else {
722-
Char::from_int(c1)
723-
}
724-
}
725-
}
726-
727-
///|
728-
/// Test if the length of the string is equal to the given length.
729-
///
730-
/// This has O(n) complexity where n is the length in the parameter.
731-
pub fn String::length_eq(self : String, len : Int) -> Bool {
732-
let codeunit_len = self.length()
733-
for index = 0, count = 0
734-
index < codeunit_len && count < len
735-
index = index + 1, count = count + 1 {
736-
let c1 = self.unsafe_charcode_at(index)
737-
if is_leading_surrogate(c1) && index + 1 < codeunit_len {
738-
let c2 = self.unsafe_charcode_at(index + 1)
739-
if is_trailing_surrogate(c2) {
740-
continue index + 2, count + 1
741-
} else {
742-
abort("invalid surrogate pair")
743-
}
744-
}
745-
} else {
746-
count == len && index == codeunit_len
747-
}
748-
}
749-
750-
///|
751-
/// Test if the length of the string is greater than or equal to the given length.
752-
///
753-
/// This has O(n) complexity where n is the length in the parameter.
754-
pub fn String::length_ge(self : String, len : Int) -> Bool {
755-
let codeunit_len = self.length()
756-
for index = 0, count = 0
757-
index < codeunit_len && count < len
758-
index = index + 1, count = count + 1 {
759-
let c1 = self.unsafe_charcode_at(index)
760-
if is_leading_surrogate(c1) && index + 1 < codeunit_len {
761-
let c2 = self.unsafe_charcode_at(index + 1)
762-
if is_trailing_surrogate(c2) {
763-
continue index + 2, count + 1
764-
} else {
765-
abort("invalid surrogate pair")
766-
}
767-
}
768-
} else {
769-
count >= len
770-
}
771-
}
772-
773681
///|
774682
/// Returns the index of the n-th (zero-indexed) character within the range [start, end).
775683
fn String::offset_of_nth_char_forward(
@@ -854,3 +762,66 @@ pub fn String::offset_of_nth_char(
854762
self.offset_of_nth_char_backward(-i, start_offset~, end_offset~)
855763
}
856764
}
765+
766+
///|
767+
/// Returns the Unicode character at the given index.
768+
pub fn String::char_at(self : String, index : Int) -> Char {
769+
guard index >= 0 && index < self.length() else {
770+
abort("index out of bounds")
771+
}
772+
self.unsafe_char_at(index)
773+
}
774+
775+
///|
776+
/// Test if the length of the string is equal to the given length.
777+
///
778+
/// This has O(n) complexity where n is the length in the parameter.
779+
pub fn String::char_length_eq(
780+
self : String,
781+
len : Int,
782+
start_offset~ : Int = 0,
783+
end_offset~ : Int = self.length()
784+
) -> Bool {
785+
for index = start_offset, count = 0
786+
index < end_offset && count < len
787+
index = index + 1, count = count + 1 {
788+
let c1 = self.unsafe_charcode_at(index)
789+
if is_leading_surrogate(c1) && index + 1 < end_offset {
790+
let c2 = self.unsafe_charcode_at(index + 1)
791+
if is_trailing_surrogate(c2) {
792+
continue index + 2, count + 1
793+
} else {
794+
abort("invalid surrogate pair")
795+
}
796+
}
797+
} else {
798+
count == len && index == end_offset
799+
}
800+
}
801+
802+
///|
803+
/// Test if the length of the string is greater than or equal to the given length.
804+
///
805+
/// This has O(n) complexity where n is the length in the parameter.
806+
pub fn String::char_length_ge(
807+
self : String,
808+
len : Int,
809+
start_offset~ : Int = 0,
810+
end_offset~ : Int = self.length()
811+
) -> Bool {
812+
for index = start_offset, count = 0
813+
index < end_offset && count < len
814+
index = index + 1, count = count + 1 {
815+
let c1 = self.unsafe_charcode_at(index)
816+
if is_leading_surrogate(c1) && index + 1 < end_offset {
817+
let c2 = self.unsafe_charcode_at(index + 1)
818+
if is_trailing_surrogate(c2) {
819+
continue index + 2, count + 1
820+
} else {
821+
abort("invalid surrogate pair")
822+
}
823+
}
824+
} else {
825+
count >= len
826+
}
827+
}

string/string.mbti

+16
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ fn iter2(String) -> Iter2[Int, Char]
3535

3636
fn last_index_of(String, String, from~ : Int = ..) -> Int
3737

38+
#deprecated
3839
fn length_eq(StringView, Int) -> Bool
3940

41+
#deprecated
4042
fn length_ge(StringView, Int) -> Bool
4143

4244
fn pad_end(String, Int, Char) -> String
@@ -53,6 +55,7 @@ fn rev(String) -> String
5355

5456
fn rev_fold[A](String, init~ : A, (A, Char) -> A) -> A
5557

58+
#deprecated
5659
fn rev_get(StringView, Int) -> Char
5760

5861
fn rev_iter(String) -> Iter[Char]
@@ -86,21 +89,31 @@ type StringView
8689
impl StringView {
8790
char_at(Self, Int) -> Char
8891
char_length(Self) -> Int
92+
char_length_eq(Self, Int) -> Bool
93+
char_length_ge(Self, Int) -> Bool
8994
charcode_at(Self, Int) -> Int
9095
iter(Self) -> Iter[Char]
9196
#deprecated
9297
length(Self) -> Int
98+
#deprecated
9399
length_eq(Self, Int) -> Bool
100+
#deprecated
94101
length_ge(Self, Int) -> Bool
95102
offset_of_nth_char(Self, Int) -> Int?
96103
#deprecated
97104
op_as_view(Self, start~ : Int = .., end? : Int) -> Self
105+
#deprecated
98106
op_get(Self, Int) -> Char
107+
#deprecated
99108
rev_get(Self, Int) -> Char
109+
rev_iter(Self) -> Iter[Char]
100110
}
101111
impl Show for StringView
102112

103113
impl String {
114+
char_at(String, Int) -> Char
115+
char_length_eq(String, Int, start_offset~ : Int = .., end_offset~ : Int = ..) -> Bool
116+
char_length_ge(String, Int, start_offset~ : Int = .., end_offset~ : Int = ..) -> Bool
104117
#deprecated
105118
concat(Array[String], separator~ : String = ..) -> String
106119
contains(String, String) -> Bool
@@ -119,7 +132,9 @@ impl String {
119132
iter(String) -> Iter[Char]
120133
iter2(String) -> Iter2[Int, Char]
121134
last_index_of(String, String, from~ : Int = ..) -> Int
135+
#deprecated
122136
length_eq(String, Int) -> Bool
137+
#deprecated
123138
length_ge(String, Int) -> Bool
124139
offset_of_nth_char(String, Int, start_offset~ : Int = .., end_offset~ : Int = ..) -> Int?
125140
#deprecated
@@ -131,6 +146,7 @@ impl String {
131146
replace_all(String, old~ : String, new~ : String) -> String
132147
rev(String) -> String
133148
rev_fold[A](String, init~ : A, (A, Char) -> A) -> A
149+
#deprecated
134150
rev_get(String, Int) -> Char
135151
rev_iter(String) -> Iter[Char]
136152
split(String, String) -> Iter[String]

0 commit comments

Comments
 (0)