// Port of Monaco/VS Code's CharacterClassifier.
//
// Source: vscode/src/vs/editor/common/core/characterClassifier.ts
// with toUint8 from vscode/src/vs/base/common/uint.ts
// (checked-in vscode submodule).
//
// A fast character classifier: a dense Uint8 map for ASCII (0..255) plus a
// sparse map for the rest. Values are clamped to a byte.
///|
fn to_uint8(v : Int32) -> Int32 {
v.clamp(min=0, max=255)
}
///|
/// Classifies char codes into small integer buckets.
struct CharacterClassifier {
ascii_map : Array[Int32]
map : Map[Int32, Int32]
default_value : Int32
}
///|
pub fn CharacterClassifier::CharacterClassifier(
default_value : Int32,
) -> CharacterClassifier {
let dv = to_uint8(default_value)
{ ascii_map: Array::make(256, dv), map: Map([]), default_value: dv, }
}
///|
pub fn CharacterClassifier::set(
self : CharacterClassifier,
char_code : Int32,
value : Int32,
) -> Unit {
let v = to_uint8(value)
if char_code >= 0 && char_code < 256 {
self.ascii_map[char_code] = v
} else {
self.map[char_code] = v
}
}
///|
pub fn CharacterClassifier::get(
self : CharacterClassifier,
char_code : Int32,
) -> Int32 {
if char_code >= 0 && char_code < 256 {
self.ascii_map[char_code]
} else {
// Mirrors upstream `this._map.get(charCode) || this._defaultValue`: a stored
// 0 (falsy) also falls back to the default value.
match self.map.get(char_code) {
Some(v) => if v != 0 { v } else { self.default_value }
None => self.default_value
}
}
}
///|
/// A set of char codes, backed by a `CharacterClassifier`.
struct CharacterSet {
actual : CharacterClassifier
}
///|
fn CharacterSet::new_impl() -> CharacterSet {
{ actual: CharacterClassifier(0), }
}
///|
fn CharacterSet::add_impl(self : CharacterSet, char_code : Int32) -> Unit {
self.actual.set(char_code, 1)
}
///|
fn CharacterSet::has_impl(self : CharacterSet, char_code : Int32) -> Bool {
self.actual.get(char_code) == 1
}