///|
/// Substring by UTF-16 code-unit offsets (Python-style slicing with clamping).
fn substr(s : String, start : Int, end? : Int) -> String {
let len = s.length()
let end = match end {
Some(e) => if e < 0 { 0 } else if e > len { len } else { e }
None => len
}
let start = if start < 0 { 0 } else if start > end { end } else { start }
s.view(start_offset=start, end_offset=end).to_owned()
}
///|
/// Python's `str.partition(sep)`.
fn partition(s : String, sep : String) -> (String, Bool, String) {
match s.find(sep) {
Some(i) => (substr(s, 0, end=i), true, substr(s, i + sep.length()))
None => (s, false, "")
}
}
///|
/// Python's `str.rpartition(sep)`.
fn rpartition(s : String, sep : String) -> (String, Bool, String) {
match s.rev_find(sep) {
Some(i) => (substr(s, 0, end=i), true, substr(s, i + sep.length()))
None => ("", false, s)
}
}
///|
/// Python's `str.split(sep)` (all occurrences, keeping empty pieces).
fn split_all(s : String, sep : String) -> Array[String] {
s.split(sep).map(v => v.to_owned()).to_array()
}
///|
fn is_ascii_alpha(c : UInt16) -> Bool {
(c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
///|
fn is_ascii_digit(c : UInt16) -> Bool {
c >= '0' && c <= '9'
}
///|
fn is_ascii_hex(c : UInt16) -> Bool {
is_ascii_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
}
///|
fn ascii_lower(s : String) -> String {
let sb = StringBuilder()
for i in 0..= 'A' && c <= 'Z' {
sb.write_char((c.to_int() + 32).unsafe_to_char())
} else {
sb.write_char(c.to_int().unsafe_to_char())
}
}
sb.to_string()
}
///|
/// Python's `repr()` of a `str` (used in error messages).
fn py_str_repr(s : String) -> String {
let quote = if s.contains("'") && !s.contains("\"") { '"' } else { '\'' }
let sb = StringBuilder()
sb.write_char(quote)
for c in s {
if c == quote || c == '\\' {
sb.write_char('\\')
sb.write_char(c)
} else if c == '\n' {
sb.write_string("\\n")
} else if c == '\r' {
sb.write_string("\\r")
} else if c == '\t' {
sb.write_string("\\t")
} else if c.to_int() < 0x20 || (c.to_int() >= 0x7f && c.to_int() < 0xa0) {
let hex = c.to_int().to_string(radix=16)
sb.write_string(if hex.length() < 2 { "\\x0" + hex } else { "\\x" + hex })
} else {
sb.write_char(c)
}
}
sb.write_char(quote)
sb.to_string()
}