use crate::common::SECS_PER_HOUR;
use crate::DateTimeError;
use std::convert::TryFrom;
pub const MAX_DATE_FIELDS: usize = 25;
pub const MAX_TOKEN_LEN: usize = 10;
const DAGO: &[u8] = b"ago";
const DCURRENT: &[u8] = b"current";
const EPOCH: &[u8] = b"epoch";
const INVALID: &[u8] = b"invalid";
pub const EARLY: &[u8] = b"-infinity";
pub const LATE: &[u8] = b"infinity";
const NOW: &[u8] = b"now";
const TODAY: &[u8] = b"today";
const TOMORROW: &[u8] = b"tomorrow";
const YESTERDAY: &[u8] = b"yesterday";
const ZULU: &[u8] = b"zulu";
const DMICROSEC: &[u8] = b"usecond";
const DMILLISEC: &[u8] = b"msecond";
const DSECOND: &[u8] = b"second";
const DMINUTE: &[u8] = b"minute";
const DHOUR: &[u8] = b"hour";
const DDAY: &[u8] = b"day";
const DWEEK: &[u8] = b"week";
const DMONTH: &[u8] = b"month";
const DQUARTER: &[u8] = b"quarter";
const DYEAR: &[u8] = b"year";
const DDECADE: &[u8] = b"decade";
const DCENTURY: &[u8] = b"century";
const DMILLENNIUM: &[u8] = b"millennium";
const DA_D: &[u8] = b"ad";
const DB_C: &[u8] = b"bc";
const DTIMEZONE: &[u8] = b"timezone";
pub struct DateToken {
pub token: &'static [u8],
pub ty: TokenType,
pub value: i32,
}
impl<'a> DateToken {
pub const fn new(token: &'static [u8], ty: TokenType, value: i32) -> Self {
Self { token, ty, value }
}
}
pub const AM: i32 = 0;
pub const PM: i32 = 1;
pub const HR24: i32 = 2;
const AD: i32 = 0;
pub const BC: i32 = 1;
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq)]
#[repr(u8)]
pub enum TokenType {
RESERV = 0,
MONTH = 1,
YEAR = 2,
DAY = 3,
#[allow(dead_code)]
JULIAN = 4,
TZ = 5,
DTZ = 6,
#[allow(dead_code)]
DYNTZ = 7,
IgnoreDtf = 8,
AMPM = 9,
HOUR = 10,
MINUTE = 11,
SECOND = 12,
MILLISECOND = 13,
MICROSECOND = 14,
DOY = 15,
DOW = 16,
UNITS = 17,
ADBC = 18,
AGO = 19,
#[allow(dead_code)]
AbsBefore = 20,
#[allow(dead_code)]
AbsAfter = 21,
#[allow(dead_code)]
ISODATE = 22,
ISOTIME = 23,
WEEK = 24,
DECADE = 25,
CENTURY = 26,
MILLENNIUM = 27,
DTZMOD = 28,
UnknownField = 31,
}
impl TokenType {
#[inline]
pub const fn mask(self) -> i32 {
0x01i32 << (self as i32)
}
}
impl TryFrom<u8> for TokenType {
type Error = DateTimeError;
#[inline]
fn try_from(value: u8) -> Result<Self, Self::Error> {
if value >= 31 {
Err(DateTimeError::invalid(format!(
"Invalid token type {:?}",
value
)))
} else {
Ok(unsafe { std::mem::transmute(value) })
}
}
}
pub const DTK_ALL_SECS_M: i32 =
TokenType::SECOND.mask() | TokenType::MILLISECOND.mask() | TokenType::MICROSECOND.mask();
pub const DTK_YEAR_M: i32 = TokenType::YEAR.mask();
pub const DTK_MONTH_M: i32 = TokenType::MONTH.mask();
pub const DTK_DAY_M: i32 = TokenType::DAY.mask();
pub const DTK_YEAR_MONTH_M: i32 = TokenType::YEAR.mask() | TokenType::MONTH.mask();
pub const DTK_MONTH_DAY_M: i32 = TokenType::MONTH.mask() | TokenType::DAY.mask();
pub const DTK_DATE_M: i32 =
TokenType::YEAR.mask() | TokenType::MONTH.mask() | TokenType::DAY.mask();
pub const DTK_TIME_M: i32 = TokenType::HOUR.mask() | TokenType::MINUTE.mask() | DTK_ALL_SECS_M;
#[allow(dead_code)]
pub const DTK_TIME_ZONE_M: i32 = TokenType::TZ.mask();
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq)]
#[repr(i32)]
pub enum TokenField {
Number = 0,
String = 1,
Date = 2,
Time = 3,
Tz = 4,
#[allow(dead_code)]
Ago = 5,
Special = 6,
Invalid = 7,
Current = 8,
Early = 9,
Late = 10,
Epoch = 11,
Now = 12,
Yesterday = 13,
Today = 14,
Tomorrow = 15,
Zulu = 16,
Delta = 17,
Second = 18,
Minute = 19,
Hour = 20,
Day = 21,
Week = 22,
Month = 23,
Quarter = 24,
Year = 25,
Decade = 26,
Century = 27,
Millennium = 28,
Millisec = 29,
Microsec = 30,
Julian = 31,
Dow = 32,
Doy = 33,
TzHour = 34,
TzMinute = 35,
#[allow(dead_code)]
Isoyear = 36,
Isodow = 37,
}
impl TokenField {
#[inline]
pub const fn value(self) -> i32 {
self as i32
}
}
impl TryFrom<i32> for TokenField {
type Error = DateTimeError;
#[inline]
fn try_from(value: i32) -> Result<Self, Self::Error> {
if value < 0 && value > 37 {
Err(DateTimeError::invalid(format!(
"Invalid token field {:?}",
value
)))
} else {
Ok(unsafe { std::mem::transmute(value) })
}
}
}
use TokenField::*;
use TokenType::*;
const DATE_TOKEN_TABLE: [DateToken; 280] = [
DateToken::new(EARLY, RESERV, Early.value()), DateToken::new(b"acsst", DTZ, 37800), DateToken::new(b"acst", DTZ, -14400), DateToken::new(b"act", TZ, -18000), DateToken::new(DA_D, ADBC, AD), DateToken::new(b"adt", DTZ, -10800), DateToken::new(b"aesst", DTZ, 39600), DateToken::new(b"aest", TZ, 36000), DateToken::new(b"aft", TZ, 16200), DateToken::new(b"ahst", TZ, -36000), DateToken::new(b"akdt", DTZ, -28800), DateToken::new(b"akst", DTZ, -32400), DateToken::new(b"allballs", RESERV, Zulu.value()), DateToken::new(b"almst", TZ, 25200), DateToken::new(b"almt", TZ, 21600), DateToken::new(b"am", AMPM, AM),
DateToken::new(b"amst", DTZ, 18000), DateToken::new(b"amt", TZ, 14400), DateToken::new(b"anast", DTZ, 46800), DateToken::new(b"anat", TZ, 43200), DateToken::new(b"apr", MONTH, 4),
DateToken::new(b"april", MONTH, 4),
DateToken::new(b"art", TZ, -10800), DateToken::new(b"ast", TZ, -14400), DateToken::new(b"at", IgnoreDtf, 0), DateToken::new(b"aug", MONTH, 8),
DateToken::new(b"august", MONTH, 8),
DateToken::new(b"awsst", DTZ, 32400), DateToken::new(b"awst", TZ, 28800), DateToken::new(b"awt", DTZ, -10800),
DateToken::new(b"azost", DTZ, 0), DateToken::new(b"azot", TZ, -3600), DateToken::new(b"azst", DTZ, 18000), DateToken::new(b"azt", TZ, 14400), DateToken::new(DB_C, ADBC, BC), DateToken::new(b"bdst", TZ, 7200), DateToken::new(b"bdt", TZ, 21600), DateToken::new(b"bnt", TZ, 28800), DateToken::new(b"bort", TZ, 28800), DateToken::new(b"bot", TZ, -14400), DateToken::new(b"bra", TZ, -10800), DateToken::new(b"bst", DTZ, 3600), DateToken::new(b"bt", TZ, 10800), DateToken::new(b"btt", TZ, 21600), DateToken::new(b"cadt", DTZ, 37800), DateToken::new(b"cast", TZ, 34200), DateToken::new(b"cat", TZ, -36000), DateToken::new(b"cct", TZ, 28800), DateToken::new(b"cdt", DTZ, -18000), DateToken::new(b"cest", DTZ, 7200), DateToken::new(b"cet", TZ, 3600), DateToken::new(b"cetdst", DTZ, 7200), DateToken::new(b"chadt", DTZ, 49500), DateToken::new(b"chast", TZ, 45900), DateToken::new(b"ckt", TZ, 43200), DateToken::new(b"clst", DTZ, -10800), DateToken::new(b"clt", TZ, -14400), DateToken::new(b"cot", TZ, -18000), DateToken::new(b"cst", TZ, -21600), DateToken::new(DCURRENT, RESERV, Current.value()), DateToken::new(b"cvt", TZ, 25200), DateToken::new(b"cxt", TZ, 25200), DateToken::new(b"d", UNITS, Day.value()), DateToken::new(b"davt", TZ, 25200), DateToken::new(b"ddut", TZ, 36000), DateToken::new(b"dec", MONTH, 12),
DateToken::new(b"december", MONTH, 12),
DateToken::new(b"dnt", TZ, 3600), DateToken::new(b"dow", UNITS, Dow.value()), DateToken::new(b"doy", UNITS, Doy.value()), DateToken::new(b"dst", DTZMOD, SECS_PER_HOUR),
DateToken::new(b"easst", DTZ, -18000), DateToken::new(b"east", TZ, -21600), DateToken::new(b"eat", TZ, 10800), DateToken::new(b"edt", DTZ, -14400), DateToken::new(b"eest", DTZ, 10800), DateToken::new(b"eet", TZ, 7200), DateToken::new(b"eetdst", DTZ, 10800), DateToken::new(b"egst", DTZ, 0), DateToken::new(b"egt", TZ, -3600), DateToken::new(EPOCH, RESERV, Epoch.value()), DateToken::new(b"est", TZ, -18000), DateToken::new(b"fe", MONTH, 2),
DateToken::new(b"february", MONTH, 2),
DateToken::new(b"fjst", DTZ, -46800), DateToken::new(b"fjt", TZ, -43200), DateToken::new(b"fkst", DTZ, -10800), DateToken::new(b"fkt", TZ, -7200), DateToken::new(b"fri", DOW, 5),
DateToken::new(b"friday", DOW, 5),
DateToken::new(b"fst", TZ, 3600), DateToken::new(b"fwt", DTZ, 7200), DateToken::new(b"galt", TZ, -21600), DateToken::new(b"gamt", TZ, -32400), DateToken::new(b"gest", DTZ, 18000), DateToken::new(b"get", TZ, 14400), DateToken::new(b"gft", TZ, -10800), DateToken::new(b"gilt", TZ, 43200), DateToken::new(b"gmt", TZ, 0), DateToken::new(b"gst", TZ, 36000), DateToken::new(b"gyt", TZ, -14400), DateToken::new(b"h", UNITS, Hour.value()), DateToken::new(b"hdt", DTZ, -32400), DateToken::new(b"hkt", TZ, 28800), DateToken::new(b"hst", TZ, -36000), DateToken::new(b"ict", TZ, 25200), DateToken::new(b"idle", TZ, 43200), DateToken::new(b"idlw", TZ, -43200), DateToken::new(LATE, RESERV, Late.value()), DateToken::new(INVALID, RESERV, Invalid.value()), DateToken::new(b"iot", TZ, 18000), DateToken::new(b"irkst", DTZ, 32400), DateToken::new(b"irkt", TZ, 28800), DateToken::new(b"irt", TZ, 12600), DateToken::new(b"isodow", UNITS, Isodow.value()), DateToken::new(b"ist", TZ, 7200), DateToken::new(b"it", TZ, 12600), DateToken::new(b"j", UNITS, Julian.value()),
DateToken::new(b"jan", MONTH, 1),
DateToken::new(b"january", MONTH, 1),
DateToken::new(b"javt", TZ, 25200), DateToken::new(b"jayt", TZ, 32400), DateToken::new(b"jd", UNITS, Julian.value()),
DateToken::new(b"jst", TZ, 32400), DateToken::new(b"jt", TZ, 27000), DateToken::new(b"jul", MONTH, 7),
DateToken::new(b"julian", UNITS, Julian as i32),
DateToken::new(b"july", MONTH, 7),
DateToken::new(b"jun", MONTH, 6),
DateToken::new(b"june", MONTH, 6),
DateToken::new(b"kdt", DTZ, 36000), DateToken::new(b"kgst", DTZ, 21600), DateToken::new(b"kgt", TZ, 18000), DateToken::new(b"kost", TZ, 43200), DateToken::new(b"krast", DTZ, 25200), DateToken::new(b"krat", TZ, 28800), DateToken::new(b"kst", TZ, 32400), DateToken::new(b"lhdt", DTZ, 39600), DateToken::new(b"lhst", TZ, 37800), DateToken::new(b"ligt", TZ, 36000), DateToken::new(b"lint", TZ, 50400), DateToken::new(b"lkt", TZ, 21600), DateToken::new(b"m", UNITS, Month.value()), DateToken::new(b"magst", DTZ, 43200), DateToken::new(b"magt", TZ, 39600), DateToken::new(b"mar", MONTH, 3),
DateToken::new(b"march", MONTH, 3),
DateToken::new(b"mart", TZ, -34200), DateToken::new(b"mawt", TZ, 21600), DateToken::new(b"may", MONTH, 5),
DateToken::new(b"mdt", DTZ, -21600), DateToken::new(b"mest", DTZ, 7200), DateToken::new(b"met", TZ, 3600), DateToken::new(b"metdst", DTZ, 7200), DateToken::new(b"mewt", TZ, 3600), DateToken::new(b"mez", TZ, 3600), DateToken::new(b"mht", TZ, 43200), DateToken::new(b"mm", UNITS, Minute.value()), DateToken::new(b"mmt", TZ, 23400), DateToken::new(b"mon", DOW, 1),
DateToken::new(b"monday", DOW, 1),
DateToken::new(b"mpt", TZ, 36000), DateToken::new(b"msd", DTZ, 14400), DateToken::new(b"msk", TZ, 10800), DateToken::new(b"mst", TZ, -25200), DateToken::new(b"mt", TZ, 30600), DateToken::new(b"mut", TZ, 14400), DateToken::new(b"mvt", TZ, 18000), DateToken::new(b"myt", TZ, 28800), DateToken::new(b"nct", TZ, 39600), DateToken::new(b"ndt", DTZ, -9000), DateToken::new(b"nft", TZ, -12600), DateToken::new(b"nor", TZ, 3600), DateToken::new(b"nov", MONTH, 11),
DateToken::new(b"november", MONTH, 11),
DateToken::new(b"novst", DTZ, 25200), DateToken::new(b"novt", TZ, 21600), DateToken::new(NOW, RESERV, Now.value()), DateToken::new(b"npt", TZ, 20700), DateToken::new(b"nst", TZ, -12600), DateToken::new(b"nt", TZ, -39600), DateToken::new(b"nut", TZ, -39600), DateToken::new(b"nzdt", DTZ, 46800), DateToken::new(b"nzst", TZ, 43200), DateToken::new(b"nzt", TZ, 43200), DateToken::new(b"oct", MONTH, 10),
DateToken::new(b"october", MONTH, 10),
DateToken::new(b"omsst", DTZ, 25200), DateToken::new(b"omst", TZ, 21600), DateToken::new(b"on", IgnoreDtf, 0), DateToken::new(b"pdt", DTZ, -25200), DateToken::new(b"pet", TZ, -18000), DateToken::new(b"petst", DTZ, 46800), DateToken::new(b"pett", TZ, 43200), DateToken::new(b"pgt", TZ, 36000), DateToken::new(b"phot", TZ, 46800), DateToken::new(b"pht", TZ, 28800), DateToken::new(b"pkt", TZ, 18000), DateToken::new(b"pm", AMPM, PM),
DateToken::new(b"pmdt", DTZ, -7200), DateToken::new(b"pont", TZ, 39600), DateToken::new(b"pst", TZ, -28800), DateToken::new(b"pwt", TZ, 32400), DateToken::new(b"pyst", DTZ, -10800), DateToken::new(b"pyt", TZ, -14400), DateToken::new(b"ret", DTZ, 14400), DateToken::new(b"s", UNITS, Second.value()), DateToken::new(b"sadt", DTZ, 37800), DateToken::new(b"sast", TZ, 34200), DateToken::new(b"sat", DOW, 6),
DateToken::new(b"saturday", DOW, 6),
DateToken::new(b"sct", DTZ, 14400), DateToken::new(b"sep", MONTH, 9),
DateToken::new(b"sept", MONTH, 9),
DateToken::new(b"september", MONTH, 9),
DateToken::new(b"set", TZ, -3600), DateToken::new(b"sst", DTZ, 7200), DateToken::new(b"sun", DOW, 0),
DateToken::new(b"sunday", DOW, 0),
DateToken::new(b"swt", TZ, 3600), DateToken::new(b"t", ISOTIME, Time.value()), DateToken::new(b"tft", TZ, 18000), DateToken::new(b"that", TZ, -36000), DateToken::new(b"thu", DOW, 4),
DateToken::new(b"thur", DOW, 4),
DateToken::new(b"thurs", DOW, 4),
DateToken::new(b"thursday", DOW, 4),
DateToken::new(b"tjt", TZ, 18000), DateToken::new(b"tkt", TZ, -36000), DateToken::new(b"tmt", TZ, 18000), DateToken::new(TODAY, RESERV, Today.value()), DateToken::new(TOMORROW, RESERV, Tomorrow.value()), DateToken::new(b"tot", TZ, 46800), DateToken::new(b"truk", TZ, 36000), DateToken::new(b"tue", DOW, 2),
DateToken::new(b"tues", DOW, 2),
DateToken::new(b"tuesday", DOW, 2),
DateToken::new(b"tvt", TZ, 43200), DateToken::new(b"ulast", DTZ, 32400), DateToken::new(b"ulat", TZ, 28800), DateToken::new(b"undefined", RESERV, Invalid as i32), DateToken::new(b"ut", TZ, 0),
DateToken::new(b"utc", TZ, 0),
DateToken::new(b"uyst", DTZ, -7200), DateToken::new(b"uyt", TZ, -10800), DateToken::new(b"uzst", DTZ, 21600), DateToken::new(b"uzt", TZ, 18000), DateToken::new(b"vet", TZ, -14400), DateToken::new(b"vlast", DTZ, 39600), DateToken::new(b"vlat", TZ, 36000), DateToken::new(b"vut", TZ, 39600), DateToken::new(b"wadt", DTZ, 28800), DateToken::new(b"wakt", TZ, 43200), DateToken::new(b"wast", TZ, 25200), DateToken::new(b"wat", TZ, -3600), DateToken::new(b"wdt", DTZ, 32400), DateToken::new(b"wed", DOW, 3),
DateToken::new(b"wednesday", DOW, 3),
DateToken::new(b"weds", DOW, 3),
DateToken::new(b"west", DTZ, 3600), DateToken::new(b"wet", TZ, 0), DateToken::new(b"wetdst", DTZ, 3600), DateToken::new(b"wft", TZ, 43200), DateToken::new(b"wgst", DTZ, -7200), DateToken::new(b"wgt", TZ, -10800), DateToken::new(b"wst", TZ, 28800), DateToken::new(b"y", UNITS, Year.value()), DateToken::new(b"yakst", DTZ, 36000), DateToken::new(b"yakt", TZ, 32400), DateToken::new(b"yapt", TZ, 36000), DateToken::new(b"ydt", DTZ, -28800), DateToken::new(b"yekst", DTZ, 21600), DateToken::new(b"yekt", TZ, 18000), DateToken::new(YESTERDAY, RESERV, Yesterday.value()), DateToken::new(b"yst", TZ, -32400), DateToken::new(b"z", TZ, 0), DateToken::new(b"zp4", TZ, -14400), DateToken::new(b"zp5", TZ, -18000), DateToken::new(b"zp6", TZ, -21600), DateToken::new(ZULU, TZ, 0), ];
const DELTA_TOKEN_TABLE: [DateToken; 63] = [
DateToken::new(b"@", IgnoreDtf, 0), DateToken::new(DAGO, AGO, 0), DateToken::new(b"c", UNITS, Century.value()), DateToken::new(b"cent", UNITS, Century.value()), DateToken::new(b"centuries", UNITS, Century.value()), DateToken::new(DCENTURY, UNITS, Century.value()), DateToken::new(b"d", UNITS, Day.value()), DateToken::new(DDAY, UNITS, Day.value()), DateToken::new(b"days", UNITS, Day.value()), DateToken::new(b"dec", UNITS, Decade.value()), DateToken::new(DDECADE, UNITS, Decade.value()), DateToken::new(b"decades", UNITS, Decade.value()), DateToken::new(b"decs", UNITS, Decade.value()), DateToken::new(b"h", UNITS, Hour.value()), DateToken::new(DHOUR, UNITS, Hour.value()), DateToken::new(b"hours", UNITS, Hour.value()), DateToken::new(b"hr", UNITS, Hour.value()), DateToken::new(b"hrs", UNITS, Hour.value()), DateToken::new(INVALID, RESERV, Invalid.value()), DateToken::new(b"m", UNITS, Minute.value()), DateToken::new(b"microsecon", UNITS, Microsec.value()), DateToken::new(b"mil", UNITS, Millennium.value()), DateToken::new(b"millennia", UNITS, Millennium.value()), DateToken::new(DMILLENNIUM, UNITS, Millennium.value()), DateToken::new(b"millisecon", UNITS, Millisec.value()), DateToken::new(b"mils", UNITS, Millennium.value()), DateToken::new(b"min", UNITS, Minute.value()), DateToken::new(b"mins", UNITS, Minute.value()), DateToken::new(DMINUTE, UNITS, Minute.value()), DateToken::new(b"minutes", UNITS, Minute.value()), DateToken::new(b"mon", UNITS, Month.value()), DateToken::new(b"mons", UNITS, Month.value()), DateToken::new(DMONTH, UNITS, Month.value()), DateToken::new(b"months", UNITS, Month.value()),
DateToken::new(b"ms", UNITS, Millisec.value()),
DateToken::new(b"msec", UNITS, Millisec.value()),
DateToken::new(DMILLISEC, UNITS, Millisec.value()),
DateToken::new(b"mseconds", UNITS, Millisec.value()),
DateToken::new(b"msecs", UNITS, Millisec.value()),
DateToken::new(b"qtr", UNITS, Quarter.value()), DateToken::new(DQUARTER, UNITS, Quarter.value()), DateToken::new(b"s", UNITS, Second.value()),
DateToken::new(b"sec", UNITS, Second.value()),
DateToken::new(DSECOND, UNITS, Second.value()),
DateToken::new(b"seconds", UNITS, Second.value()),
DateToken::new(b"secs", UNITS, Second.value()),
DateToken::new(DTIMEZONE, UNITS, Tz.value()), DateToken::new(b"timezone_h", UNITS, TzHour.value()), DateToken::new(b"timezone_m", UNITS, TzMinute.value()), DateToken::new(b"undefined", RESERV, Invalid.value()), DateToken::new(b"us", UNITS, Microsec.value()), DateToken::new(b"usec", UNITS, Microsec.value()), DateToken::new(DMICROSEC, UNITS, Microsec.value()), DateToken::new(b"useconds", UNITS, Microsec.value()), DateToken::new(b"usecs", UNITS, Microsec.value()), DateToken::new(b"w", UNITS, Week.value()), DateToken::new(DWEEK, UNITS, Week.value()), DateToken::new(b"weeks", UNITS, Week.value()), DateToken::new(b"y", UNITS, Year.value()), DateToken::new(DYEAR, UNITS, Year.value()), DateToken::new(b"years", UNITS, Year.value()), DateToken::new(b"yr", UNITS, Year.value()), DateToken::new(b"yrs", UNITS, Year.value()), ];
#[inline]
fn date_token_binary_search<'a, 'b>(key: &'a [u8], base: &'b [DateToken]) -> Option<&'b DateToken> {
let new_key = if key.len() > MAX_TOKEN_LEN {
&key[0..MAX_TOKEN_LEN]
} else {
key
};
let ret = base.binary_search_by_key(&new_key, |date_token| date_token.token);
match ret {
Ok(token) => Some(&base[token]),
Err(_) => None,
}
}
#[inline]
pub fn search_date_token(key: &[u8]) -> Option<&'static DateToken> {
date_token_binary_search(key, &DATE_TOKEN_TABLE)
}
#[inline]
pub fn search_delta_token<'a>(key: &'a [u8]) -> Option<&'static DateToken> {
date_token_binary_search(key, &DELTA_TOKEN_TABLE)
}