use core::char;
use core::cmp::Ordering;
use core::num::{ParseFloatError, ParseIntError};
use crate as rune;
use crate::alloc::fmt::TryWrite;
use crate::alloc::prelude::*;
use crate::alloc::string::FromUtf8Error;
use crate::alloc::{String, Vec};
use crate::compile::Named;
use crate::runtime::{
Bytes, Formatter, FromValue, Function, Hasher, Inline, MaybeTypeOf, Panic, Range, RangeFrom,
RangeFull, RangeInclusive, RangeTo, RangeToInclusive, Ref, Repr, ToValue, TypeOf, Value,
VmErrorKind, VmResult,
};
use crate::{Any, ContextError, Module, TypeHash};
#[rune::module(::std::string)]
pub fn module() -> Result<Module, ContextError> {
let mut m = Module::from_meta(self::module_meta)?;
m.ty::<String>()?;
m.function_meta(string_from)?;
m.function_meta(string_from_str)?;
m.function_meta(string_new)?;
m.function_meta(string_with_capacity)?;
m.function_meta(len)?;
m.function_meta(starts_with)?;
m.function_meta(ends_with)?;
m.function_meta(capacity)?;
m.function_meta(clear)?;
m.function_meta(contains)?;
m.function_meta(push)?;
m.function_meta(push_str)?;
m.function_meta(reserve)?;
m.function_meta(reserve_exact)?;
m.function_meta(from_utf8)?;
m.function_meta(as_bytes)?;
m.function_meta(into_bytes)?;
m.function_meta(shrink_to_fit)?;
m.function_meta(char_at)?;
m.function_meta(split)?;
m.function_meta(split_once)?;
m.associated_function("split_str", __rune_fn__split)?;
m.function_meta(trim)?;
m.function_meta(trim_end)?;
m.function_meta(replace)?;
m.function_meta(is_empty)?;
m.function_meta(chars)?;
m.function_meta(get)?;
m.function_meta(parse_int)?;
m.function_meta(parse_float)?;
m.function_meta(parse_char)?;
m.function_meta(to_lowercase)?;
m.function_meta(to_uppercase)?;
m.function_meta(add)?;
m.function_meta(add_assign)?;
m.function_meta(index_get)?;
m.function_meta(clone__meta)?;
m.implement_trait::<String>(rune::item!(::std::clone::Clone))?;
m.function_meta(partial_eq__meta)?;
m.implement_trait::<String>(rune::item!(::std::cmp::PartialEq))?;
m.function_meta(eq__meta)?;
m.implement_trait::<String>(rune::item!(::std::cmp::Eq))?;
m.function_meta(partial_cmp__meta)?;
m.implement_trait::<String>(rune::item!(::std::cmp::PartialOrd))?;
m.function_meta(cmp__meta)?;
m.implement_trait::<String>(rune::item!(::std::cmp::Ord))?;
m.function_meta(hash__meta)?;
m.function_meta(display_fmt__meta)?;
m.function_meta(debug_fmt__meta)?;
m.ty::<Chars>()?;
m.function_meta(Chars::next__meta)?;
m.function_meta(Chars::next_back__meta)?;
m.implement_trait::<Chars>(rune::item!(::std::iter::Iterator))?;
m.implement_trait::<Chars>(rune::item!(::std::iter::DoubleEndedIterator))?;
macro_rules! split {
($ty:ty) => {
m.ty::<Split<$ty>>()?;
m.function_meta(Split::<$ty>::next__meta)?;
m.implement_trait::<Split<$ty>>(rune::item!(::std::iter::Iterator))?;
};
}
split!(Function);
split!(String);
split!(char);
Ok(m)
}
#[rune::function(free, path = String::from_utf8)]
fn from_utf8(bytes: &[u8]) -> VmResult<Result<String, FromUtf8Error>> {
let vec = vm_try!(Vec::try_from(bytes));
VmResult::Ok(String::from_utf8(vec))
}
#[rune::function(instance)]
fn as_bytes(s: &str) -> VmResult<Bytes> {
VmResult::Ok(Bytes::from_vec(vm_try!(Vec::try_from(s.as_bytes()))))
}
#[rune::function(free, path = String::from)]
fn string_from(value: &str) -> VmResult<String> {
VmResult::Ok(vm_try!(String::try_from(value)))
}
#[rune::function(free, path = String::from_str, deprecated = "Use String::from instead")]
fn string_from_str(value: &str) -> VmResult<String> {
VmResult::Ok(vm_try!(String::try_from(value)))
}
#[rune::function(free, path = String::new)]
fn string_new() -> String {
String::new()
}
#[rune::function(free, path = String::with_capacity)]
fn string_with_capacity(capacity: usize) -> VmResult<String> {
VmResult::Ok(vm_try!(String::try_with_capacity(capacity)))
}
#[rune::function(instance)]
fn len(this: &str) -> usize {
this.len()
}
#[rune::function(instance)]
fn starts_with(this: &str, other: &str) -> bool {
this.starts_with(other)
}
#[rune::function(instance)]
fn ends_with(this: &str, other: &str) -> bool {
this.ends_with(other)
}
#[rune::function(instance)]
fn capacity(this: &String) -> usize {
this.capacity()
}
#[rune::function(instance)]
fn clear(this: &mut String) {
this.clear();
}
#[rune::function(instance)]
fn contains(this: &str, other: &str) -> bool {
this.contains(other)
}
#[rune::function(instance)]
fn push(this: &mut String, c: char) -> VmResult<()> {
vm_try!(this.try_push(c));
VmResult::Ok(())
}
#[rune::function(instance)]
fn push_str(this: &mut String, other: &str) -> VmResult<()> {
vm_try!(this.try_push_str(other));
VmResult::Ok(())
}
#[rune::function(instance)]
fn reserve(this: &mut String, additional: usize) -> VmResult<()> {
vm_try!(this.try_reserve(additional));
VmResult::Ok(())
}
#[rune::function(instance)]
fn reserve_exact(this: &mut String, additional: usize) -> VmResult<()> {
vm_try!(this.try_reserve_exact(additional));
VmResult::Ok(())
}
#[rune::function(instance)]
fn into_bytes(s: String) -> Bytes {
Bytes::from_vec(s.into_bytes())
}
#[rune::function(instance)]
fn is_char_boundary(s: &str, index: usize) -> bool {
s.is_char_boundary(index)
}
#[rune::function(instance)]
fn char_at(s: &str, index: usize) -> Option<char> {
if !s.is_char_boundary(index) {
return None;
}
s[index..].chars().next()
}
#[rune::function(keep, instance, protocol = CLONE)]
fn clone(this: &String) -> VmResult<String> {
VmResult::Ok(vm_try!(this.try_clone()))
}
#[rune::function(keep, instance, protocol = PARTIAL_EQ)]
#[inline]
fn partial_eq(this: &str, rhs: &str) -> bool {
this.eq(rhs)
}
#[rune::function(keep, instance, protocol = EQ)]
#[inline]
fn eq(this: &str, rhs: &str) -> bool {
this.eq(rhs)
}
#[rune::function(keep, instance, protocol = PARTIAL_CMP)]
#[inline]
fn partial_cmp(this: &str, rhs: &str) -> Option<Ordering> {
this.partial_cmp(rhs)
}
#[rune::function(keep, instance, protocol = CMP)]
#[inline]
fn cmp(this: &str, rhs: &str) -> Ordering {
this.cmp(rhs)
}
#[rune::function(keep, instance, protocol = HASH)]
fn hash(this: &str, hasher: &mut Hasher) {
hasher.write_str(this);
}
#[rune::function(keep, instance, protocol = DISPLAY_FMT)]
#[inline]
fn display_fmt(this: &str, f: &mut Formatter) -> VmResult<()> {
rune::vm_write!(f, "{this}")
}
#[rune::function(keep, instance, protocol = DEBUG_FMT)]
#[inline]
fn debug_fmt(this: &str, f: &mut Formatter) -> VmResult<()> {
rune::vm_write!(f, "{this:?}")
}
#[rune::function(instance)]
fn shrink_to_fit(s: &mut String) -> VmResult<()> {
vm_try!(s.try_shrink_to_fit());
VmResult::Ok(())
}
#[rune::function(instance, deprecated = "Use String::split instead")]
fn split(this: Ref<str>, value: Value) -> VmResult<Value> {
match value.as_ref() {
Repr::Inline(Inline::Char(c)) => {
VmResult::Ok(vm_try!(rune::to_value(Split::new(this, *c))))
}
Repr::Inline(value) => VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]),
Repr::Dynamic(value) => VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]),
Repr::Any(value) => match value.type_hash() {
String::HASH => {
let s = vm_try!(value.borrow_ref::<String>());
let split = vm_try!(rune::to_value(Split::new(
this,
vm_try!(String::try_from(s.as_str()))
)));
VmResult::Ok(split)
}
Function::HASH => {
let f = vm_try!(value.borrow_ref::<Function>());
let split = vm_try!(rune::to_value(Split::new(this, vm_try!(f.try_clone()))));
VmResult::Ok(split)
}
_ => VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]),
},
}
}
#[rune::function(instance)]
fn split_once(this: &str, value: Value) -> VmResult<Option<(String, String)>> {
let outcome = match value.as_ref() {
Repr::Inline(Inline::Char(pat)) => this.split_once(*pat),
Repr::Inline(value) => {
return VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]);
}
Repr::Dynamic(value) => {
return VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]);
}
Repr::Any(value) => match value.type_hash() {
String::HASH => {
let s = vm_try!(value.borrow_ref::<String>());
this.split_once(s.as_str())
}
Function::HASH => {
let f = vm_try!(value.borrow_ref::<Function>());
let mut err = None;
let outcome = this.split_once(|c: char| match f.call::<bool>((c,)) {
VmResult::Ok(b) => b,
VmResult::Err(e) => {
if err.is_none() {
err = Some(e);
}
false
}
});
if let Some(e) = err.take() {
return VmResult::Err(e);
}
outcome
}
_ => {
return VmResult::err([
VmErrorKind::expected::<String>(value.type_info()),
VmErrorKind::bad_argument(0),
]);
}
},
};
let Some((a, b)) = outcome else {
return VmResult::Ok(None);
};
VmResult::Ok(Some((vm_try!(a.try_to_owned()), vm_try!(b.try_to_owned()))))
}
#[rune::function(instance)]
fn trim(this: &str) -> VmResult<String> {
VmResult::Ok(vm_try!(this.trim().try_to_owned()))
}
#[rune::function(instance)]
fn trim_end(this: &str) -> VmResult<String> {
VmResult::Ok(vm_try!(this.trim_end().try_to_owned()))
}
#[rune::function(instance)]
fn is_empty(this: &str) -> bool {
this.is_empty()
}
#[rune::function(instance)]
fn replace(a: &str, from: &str, to: &str) -> VmResult<String> {
VmResult::Ok(vm_try!(String::try_from(a.replace(from, to))))
}
#[rune::function(instance)]
fn chars(s: Ref<str>) -> Chars {
Chars::new(s)
}
#[rune::function(instance)]
fn get(this: &str, key: Value) -> VmResult<Option<String>> {
use crate::runtime::TypeOf;
let slice = match key.as_any() {
Some(value) => match value.type_hash() {
RangeFrom::HASH => {
let range = vm_try!(value.borrow_ref::<RangeFrom>());
let start = vm_try!(range.start.as_usize());
this.get(start..)
}
RangeFull::HASH => {
_ = vm_try!(value.borrow_ref::<RangeFull>());
this.get(..)
}
RangeInclusive::HASH => {
let range = vm_try!(value.borrow_ref::<RangeInclusive>());
let start = vm_try!(range.start.as_usize());
let end = vm_try!(range.end.as_usize());
this.get(start..=end)
}
RangeToInclusive::HASH => {
let range = vm_try!(value.borrow_ref::<RangeToInclusive>());
let end = vm_try!(range.end.as_usize());
this.get(..=end)
}
RangeTo::HASH => {
let range = vm_try!(value.borrow_ref::<RangeTo>());
let end = vm_try!(range.end.as_usize());
this.get(..end)
}
Range::HASH => {
let range = vm_try!(value.borrow_ref::<Range>());
let start = vm_try!(range.start.as_usize());
let end = vm_try!(range.end.as_usize());
this.get(start..end)
}
_ => {
return VmResult::err(VmErrorKind::UnsupportedIndexGet {
target: String::type_info(),
index: value.type_info(),
})
}
},
_ => {
return VmResult::err(VmErrorKind::UnsupportedIndexGet {
target: String::type_info(),
index: key.type_info(),
})
}
};
let Some(slice) = slice else {
return VmResult::Ok(None);
};
VmResult::Ok(Some(vm_try!(slice.try_to_owned())))
}
#[rune::function(instance, protocol = ADD)]
fn add(a: &str, b: &str) -> VmResult<String> {
let mut string = vm_try!(String::try_with_capacity(a.len() + b.len()));
vm_try!(string.try_push_str(a));
vm_try!(string.try_push_str(b));
VmResult::Ok(string)
}
#[rune::function(instance, protocol = ADD_ASSIGN)]
fn add_assign(this: &mut String, other: &str) -> VmResult<()> {
vm_try!(this.try_push_str(other));
VmResult::Ok(())
}
#[rune::function(instance, protocol = INDEX_GET)]
fn index_get(s: &str, key: Value) -> VmResult<String> {
match vm_try!(__rune_fn__get(s, key)) {
Some(slice) => VmResult::Ok(slice),
None => VmResult::err(Panic::custom("missing string slice")),
}
}
#[rune::function(instance, path = parse::<i64>)]
fn parse_int(s: &str) -> Result<i64, ParseIntError> {
str::parse::<i64>(s)
}
#[rune::function(instance, path = parse::<f64>)]
fn parse_float(s: &str) -> Result<f64, ParseFloatError> {
str::parse::<f64>(s)
}
#[rune::function(instance, path = parse::<char>)]
fn parse_char(s: &str) -> Result<char, char::ParseCharError> {
str::parse::<char>(s)
}
#[rune::function(instance)]
fn to_lowercase(s: &str) -> VmResult<String> {
let mut lowercase = vm_try!(String::try_with_capacity(s.len()));
for (i, c) in s.char_indices() {
if c == 'Σ' {
vm_try!(lowercase.try_push_str(map_uppercase_sigma(s, i)));
} else {
vm_try!(lowercase.try_extend(c.to_lowercase()));
}
}
return VmResult::Ok(lowercase);
fn map_uppercase_sigma(from: &str, i: usize) -> &'static str {
debug_assert!('Σ'.len_utf8() == 2);
let is_word_final = case_ignorable_then_cased(from[..i].chars().rev())
&& !case_ignorable_then_cased(from[i + 2..].chars());
if is_word_final {
"ς"
} else {
"σ"
}
}
fn case_ignorable_then_cased<I: core::iter::Iterator<Item = char>>(mut iter: I) -> bool {
match iter.find(|&c| !unicode::case_ignorable::lookup(c)) {
Some(c) => unicode::cased::lookup(c),
None => false,
}
}
}
#[rune::function(instance)]
fn to_uppercase(s: &str) -> VmResult<String> {
let mut uppercase = vm_try!(String::try_with_capacity(s.len()));
vm_try!(uppercase.try_extend(s.chars().flat_map(|c| c.to_uppercase())));
VmResult::Ok(uppercase)
}
#[derive(Any)]
#[rune(item = ::std::string)]
struct Chars {
string: Ref<str>,
start: usize,
end: usize,
}
impl Chars {
fn new(string: Ref<str>) -> Self {
let end = string.len();
Self {
string,
start: 0,
end,
}
}
#[rune::function(keep, protocol = NEXT)]
fn next(&mut self) -> Option<char> {
let string = self.string.get(self.start..self.end)?;
let c = string.chars().next()?;
self.start += c.len_utf8();
Some(c)
}
#[rune::function(keep, protocol = NEXT_BACK)]
fn next_back(&mut self) -> Option<char> {
let string = self.string.get(self.start..self.end)?;
let c = string.chars().next_back()?;
self.end -= c.len_utf8();
Some(c)
}
}
trait Pattern: 'static + TryClone + Named + FromValue + ToValue + MaybeTypeOf + TypeOf {
fn test(&self, tail: &str) -> VmResult<(bool, usize)>;
fn is_empty(&self) -> bool;
}
impl Pattern for String {
fn test(&self, tail: &str) -> VmResult<(bool, usize)> {
if tail.starts_with(self.as_str()) {
VmResult::Ok((true, self.len()))
} else {
let Some(c) = tail.chars().next() else {
return VmResult::Ok((false, 0));
};
VmResult::Ok((false, c.len_utf8()))
}
}
#[inline]
fn is_empty(&self) -> bool {
String::is_empty(self)
}
}
impl Pattern for char {
fn test(&self, tail: &str) -> VmResult<(bool, usize)> {
let Some(c) = tail.chars().next() else {
return VmResult::Ok((false, 0));
};
VmResult::Ok((c == *self, c.len_utf8()))
}
#[inline]
fn is_empty(&self) -> bool {
false
}
}
impl Pattern for Function {
fn test(&self, tail: &str) -> VmResult<(bool, usize)> {
let Some(c) = tail.chars().next() else {
return VmResult::Ok((false, 0));
};
VmResult::Ok((vm_try!(self.call::<bool>((c,))), c.len_utf8()))
}
#[inline]
fn is_empty(&self) -> bool {
false
}
}
#[derive(Any)]
#[rune(item = ::std::string)]
struct Split<T>
where
T: Pattern,
{
string: Option<Ref<str>>,
pattern: T,
from: usize,
to: usize,
}
impl<T> Split<T>
where
T: Pattern,
{
fn new(string: Ref<str>, pattern: T) -> Self {
Self {
string: Some(string),
pattern,
from: 0,
to: 0,
}
}
#[rune::function(keep, protocol = NEXT)]
fn next(&mut self) -> VmResult<Option<String>> {
let Some(string) = &self.string else {
return VmResult::Ok(None);
};
if self.from == string.len() && self.from == self.to {
self.string = None;
let out = vm_try!("".try_to_owned());
return VmResult::Ok(Some(out));
}
while self.to < string.len() {
let Some(tail) = string.get(self.to..) else {
return VmResult::Ok(None);
};
let (m, len) = vm_try!(self.pattern.test(tail));
if m {
let head = string.get(self.from..self.to).unwrap_or_default();
let out = vm_try!(head.try_to_owned());
if len == 0 {
self.from = self.to;
self.to += tail.chars().next().map_or(0, |c| c.len_utf8());
} else {
self.to += len;
self.from = self.to;
}
return VmResult::Ok(Some(out));
} else {
self.to += len;
}
}
let tail = string.get(self.from..self.to).unwrap_or_default();
self.from = self.to;
let out = vm_try!(tail.try_to_owned());
if !self.pattern.is_empty() {
self.string = None;
}
VmResult::Ok(Some(out))
}
#[rune::function(keep, protocol = INTO_ITER)]
fn into_iter(self) -> Self {
self
}
}
mod unicode {
fn decode_prefix_sum(short_offset_run_header: u32) -> u32 {
short_offset_run_header & ((1 << 21) - 1)
}
fn decode_length(short_offset_run_header: u32) -> usize {
(short_offset_run_header >> 21) as usize
}
#[inline(always)]
fn skip_search<const SOR: usize, const OFFSETS: usize>(
needle: u32,
short_offset_runs: &[u32; SOR],
offsets: &[u8; OFFSETS],
) -> bool {
let last_idx =
match short_offset_runs.binary_search_by_key(&(needle << 11), |header| header << 11) {
Ok(idx) => idx + 1,
Err(idx) => idx,
};
let mut offset_idx = decode_length(short_offset_runs[last_idx]);
let length = if let Some(next) = short_offset_runs.get(last_idx + 1) {
decode_length(*next) - offset_idx
} else {
offsets.len() - offset_idx
};
let prev = last_idx
.checked_sub(1)
.map(|prev| decode_prefix_sum(short_offset_runs[prev]))
.unwrap_or(0);
let total = needle - prev;
let mut prefix_sum = 0;
for _ in 0..(length - 1) {
let offset = offsets[offset_idx];
prefix_sum += offset as u32;
if prefix_sum > total {
break;
}
offset_idx += 1;
}
offset_idx % 2 == 1
}
#[rustfmt::skip]
pub mod case_ignorable {
static SHORT_OFFSET_RUNS: [u32; 35] = [
688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148,
937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643,
1264654383, 1499535675, 1507925040, 1566646003, 1629566000, 1650551536, 1658941263,
1671540720, 1688321181, 1700908800, 1709298023, 1717688832, 1738661888, 1763828398,
1797383403, 1805773008, 1809970171, 1819148289, 1824457200,
];
static OFFSETS: [u8; 875] = [
39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2,
1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35,
1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24,
24, 43, 3, 44, 1, 7, 2, 6, 8, 41, 58, 55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 13, 1, 15, 1,
58, 1, 4, 4, 8, 1, 20, 2, 26, 1, 2, 2, 57, 1, 4, 2, 4, 2, 2, 3, 3, 1, 30, 2, 3, 1, 11, 2,
57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1,
61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1,
5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9,
98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3,
29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118,
3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31,
49, 4, 48, 1, 1, 5, 1, 1, 5, 1, 40, 9, 12, 2, 32, 4, 2, 2, 1, 3, 56, 1, 1, 2, 3, 1, 1, 3,
58, 8, 2, 2, 64, 6, 82, 3, 1, 13, 1, 7, 4, 1, 6, 1, 3, 2, 50, 63, 13, 1, 34, 101, 0, 1, 1,
3, 11, 3, 13, 3, 13, 3, 13, 2, 12, 5, 8, 2, 10, 1, 2, 1, 2, 5, 49, 5, 1, 10, 1, 1, 13, 1,
16, 13, 51, 33, 0, 2, 113, 3, 125, 1, 15, 1, 96, 32, 47, 1, 0, 1, 36, 4, 3, 5, 5, 1, 93, 6,
93, 3, 0, 1, 0, 6, 0, 1, 98, 4, 1, 10, 1, 1, 28, 4, 80, 2, 14, 34, 78, 1, 23, 3, 103, 3, 3,
2, 8, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11, 46, 3, 48, 1, 2, 4,
2, 2, 17, 1, 21, 2, 66, 6, 2, 2, 2, 2, 12, 1, 8, 1, 35, 1, 11, 1, 51, 1, 1, 3, 2, 2, 5, 2,
1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3,
1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3,
0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2,
80, 3, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1,
50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1,
3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2,
238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5,
0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46,
13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2,
3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 17, 6, 15, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17,
64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3,
0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160,
14, 0, 1, 61, 4, 0, 5, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
c as u32,
&SHORT_OFFSET_RUNS,
&OFFSETS,
)
}
}
#[rustfmt::skip]
pub mod cased {
static SHORT_OFFSET_RUNS: [u32; 22] = [
4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208,
392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 492924480, 497144832,
501339814, 578936576, 627171376, 639756544, 643952944, 649261450,
];
static OFFSETS: [u8; 315] = [
65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5,
96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9,
41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 9, 7, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2,
38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13,
5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4,
1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1,
0, 46, 18, 30, 132, 102, 3, 4, 1, 59, 5, 2, 1, 1, 1, 5, 24, 5, 1, 3, 0, 43, 1, 14, 6, 80, 0,
7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1,
7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2,
2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2,
25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6,
0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
c as u32,
&SHORT_OFFSET_RUNS,
&OFFSETS,
)
}
}
}