///|
fn property_range_index(
starts : FixedArray[Int32],
ends : FixedArray[Int32],
cp : Int32,
) -> Int32 {
if cp < 0 || cp > 0x10FFFF {
return -1
}
let mut low = 0
let mut high = starts.length()
while low < high {
let mid = low + (high - low) / 2
if starts[mid] <= cp {
low = mid + 1
} else {
high = mid
}
}
if low > 0 && cp <= ends[low - 1] {
low - 1
} else {
-1
}
}
///|
/// Complete Script property; invalid inputs use the Unknown fallback.
pub fn unicode_script(cp : Int32) -> String {
let index = property_range_index(full_script_starts, full_script_ends, cp)
if index < 0 {
"Unknown"
} else {
full_script_values[index]
}
}
///|
/// Long canonical names; missing extensions inherit Script, per UAX #24.
pub fn script_extensions(cp : Int32) -> Array[String] {
let index = property_range_index(
script_extension_starts, script_extension_ends, cp,
)
if index < 0 {
[unicode_script(cp)]
} else {
script_extension_values[index]
.split(" ")
.map(fn(name) { name.to_string() })
.collect()
}
}
///|
/// Literal per-codepoint property lookup; absent values are Restricted.
pub fn identifier_status_allowed(cp : Int32) -> Bool {
property_range_index(identifier_allowed_starts, identifier_allowed_ends, cp) >=
0
}
///|
/// Unique zero representative of an Nd family; no normalization is applied.
pub fn decimal_zero(cp : Int32) -> Int32? {
let mut low = 0
let mut high = decimal_zeros.length()
while low < high {
let mid = low + (high - low) / 2
if decimal_zeros[mid] <= cp {
low = mid + 1
} else {
high = mid
}
}
if low > 0 && cp <= decimal_zeros[low - 1] + 9 {
Some(decimal_zeros[low - 1])
} else {
None
}
}