use rupg_common::{Error, Result, SqlState};
use rupg_types::Value;
use rupg_types::unicode::{self, NormalForm};
use crate::{Call, Kernel, bad_value};
pub(crate) fn by_src(src: &str) -> Option<Kernel> {
Some(match src {
"unicode_normalize_func" => normalize,
"unicode_is_normalized" => is_normalized,
"unicode_assigned" => assigned,
"unicode_version" => |_, _| Ok(Value::text(unicode::VERSION)),
"icu_unicode_version" => |_, _| Ok(Value::Null),
_ => return None,
})
}
fn form(args: &[Value]) -> Result<NormalForm> {
let text = args.get(1).and_then(Value::as_str).ok_or_else(bad_value)?;
Ok(match text.to_ascii_uppercase().as_str() {
"NFC" => NormalForm::Nfc,
"NFD" => NormalForm::Nfd,
"NFKC" => NormalForm::Nfkc,
"NFKD" => NormalForm::Nfkd,
_ => {
return Err(Error::new(
SqlState::INVALID_PARAMETER_VALUE,
format!("invalid normalization form: {text}"),
));
}
})
}
fn normalize(_: &Call<'_>, args: &[Value]) -> Result<Value> {
let form = form(args)?;
let text = args.first().and_then(Value::as_str).ok_or_else(bad_value)?;
Ok(Value::Text(unicode::normalize_str(form, text)))
}
fn is_normalized(_: &Call<'_>, args: &[Value]) -> Result<Value> {
let form = form(args)?;
let text = args.first().and_then(Value::as_str).ok_or_else(bad_value)?;
Ok(Value::Bool(unicode::normalize_str(form, text) == text))
}
fn assigned(_: &Call<'_>, args: &[Value]) -> Result<Value> {
let text = args.first().and_then(Value::as_str).ok_or_else(bad_value)?;
Ok(Value::Bool(text.chars().all(|c| unicode::is_assigned(u32::from(c)))))
}