///|
fn trim_text(text : String) -> String {
text.trim().to_owned()
}
///|
fn char_slice(chars : Array[Char], start : Int32, end : Int32) -> String {
String::from_array(chars[start:end])
}
///|
fn split_lines(text : String) -> Array[String] {
text
.split("\n")
.map(line => {
let value = line.to_owned()
if value.has_suffix("\r") {
value[:value.length() - 1].to_owned()
} else {
value
}
})
.to_array()
}
///|
fn ascii_digit(c : Char) -> Int32? {
if c >= '0' && c <= '9' {
Some(c.to_int() - '0'.to_int())
} else {
None
}
}
///|
fn decimal_text(text : String, limit : Int32) -> Int32? {
let chars = text.to_array()
if chars.is_empty() {
return None
}
let mut value = 0
for c in chars {
match ascii_digit(c) {
None => return None
Some(digit) => {
if digit > limit || value > (limit - digit) / 10 {
return None
}
value = value * 10 + digit
}
}
}
Some(value)
}
///|
fn unique_strings(values : Array[String]) -> Array[String] {
let output : Array[String] = []
for value in values {
if !output.contains(value) {
output.push(value)
}
}
output
}
///|
fn join_strings(values : Array[String], separator : String) -> String {
let mut result = ""
for index, value in values {
if index != 0 {
result += separator
}
result += value
}
result
}
///|
fn skip_spaces(chars : Array[Char], from : Int32) -> Int32 {
let mut index = from
while index < chars.length() && (chars[index] == ' ' || chars[index] == '\t') {
index += 1
}
index
}
///|
fn entry_key(entry : Entry) -> String {
// Prefix each component with its length to avoid separator collisions.
let context = entry.context.unwrap_or("")
let present = if entry.context is Some(_) { "1" } else { "0" }
"\{present}:\{context.length()}:\{context}\{entry.id.length()}:\{entry.id}"
}
///|
fn translated_span(entry : Entry, index : Int32) -> Span {
for translation in entry.translations {
if translation.index == index {
return translation.span
}
}
entry.span
}