///| Convert a string of Unicode symbols to a Punycode string of ASCII-only symbols.
pub fn encode(raw : String) -> String? {
// Basic code point segregation, extract ASCII characters that are
// encoded as-is
let encoded = raw.iter().filter(fn(c) { c.to_int() < 0x7F }).collect()
let basic_length = encoded.length().reinterpret_as_uint()
// Initialize the state
let mut n = initial_n
let mut delta = 0U
let mut bias = initial_bias
let mut h = basic_length
if h > 0 {
encoded.push(delimiter)
}
let input_lenght = raw.length().reinterpret_as_uint()
// Main encoding loop
while h < input_lenght {
// let m = the minimum {non-basic} code point >= n in the input
let mut m = @uint.max_value
for j = 0U; j < input_lenght; j = j + 1U {
let code = raw[j.reinterpret_as_int()].reinterpret_as_uint()
if code >= n && code < m {
m = code
}
}
if m - n > (@uint.max_value - delta) / (h + 1) {
return None // Overflow
}
delta += (m - n) * (h + 1)
n = m
for j = 0U; j < input_lenght; j = j + 1U {
let code = raw[j.reinterpret_as_int()].reinterpret_as_uint()
if code < n {
delta += 1
if delta == 0 {
return None // Overflow
}
}
if code == n {
let mut q = delta
let mut k = base
for {
let t = if k <= bias {
tmin
} else if k >= bias + tmax {
tmax
} else {
k - bias
}
if q < t {
break
}
encoded.push(encode_digit(t + (q - t) % (base - t)))
q = (q - t) / (base - t)
k += base
}
encoded.push(encode_digit(q))
bias = adapt(delta, h + 1, h == basic_length)
delta = 0
h += 1
}
}
delta += 1
n += 1
}
// FIXME(chawyehsu): I was expecting to convert the array to a string
// using `.to_string()` here but it seems it's not the right way to
// do it in MoonBit, `.join("")` doesn't work as expected either.
let mut encoded_str = ""
let mut i = 0
while i < encoded.length() {
encoded_str = encoded_str + encoded[i].to_string()
i += 1
}
Some(encoded_str)
}
///|
fn encode_digit(d : UInt) -> Char {
if d < 26U {
Int::unsafe_to_char(d.reinterpret_as_int() + 97) // a-z
} else if d < 36U {
Int::unsafe_to_char(d.reinterpret_as_int() - 26 + 48) // 0-9
} else {
abort("Invalid digit")
}
}