use std::str::FromStr;
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OpCode {
Val = 1,
Equals = 2,
StrictEquals = 3,
NotEquals = 4,
StrictNotEquals = 5,
GreaterThan = 6,
GreaterThanEqual = 7,
LessThan = 8,
LessThanEqual = 9,
Not = 10,
BoolCast = 11,
And = 12,
Or = 13,
If = 14,
Add = 16,
Subtract = 17,
Multiply = 18,
Divide = 19,
Modulo = 20,
Max = 21,
Min = 22,
Concat = 23,
Substr = 24,
In = 25,
Merge = 26,
Filter = 27,
Map = 28,
Reduce = 29,
All = 30,
Some = 31,
None = 32,
Missing = 33,
MissingSome = 34,
#[cfg(feature = "datetime")]
Datetime = 44,
#[cfg(feature = "datetime")]
Timestamp = 45,
#[cfg(feature = "datetime")]
ParseDate = 46,
#[cfg(feature = "datetime")]
FormatDate = 47,
#[cfg(feature = "datetime")]
DateDiff = 48,
#[cfg(feature = "datetime")]
Now = 58,
#[cfg(feature = "ext-string")]
Length = 53,
#[cfg(feature = "ext-string")]
StartsWith = 38,
#[cfg(feature = "ext-string")]
EndsWith = 39,
#[cfg(feature = "ext-string")]
Upper = 40,
#[cfg(feature = "ext-string")]
Lower = 41,
#[cfg(feature = "ext-string")]
Trim = 42,
#[cfg(feature = "ext-string")]
Split = 43,
#[cfg(feature = "ext-array")]
Sort = 54,
#[cfg(feature = "ext-array")]
Slice = 55,
#[cfg(feature = "ext-control")]
Exists = 57,
#[cfg(feature = "ext-control")]
Coalesce = 56,
#[cfg(feature = "ext-control")]
Switch = 59,
#[cfg(feature = "ext-control")]
Type = 37,
#[cfg(feature = "error-handling")]
Try = 35,
#[cfg(feature = "error-handling")]
Throw = 36,
#[cfg(feature = "ext-math")]
Abs = 49,
#[cfg(feature = "ext-math")]
Ceil = 50,
#[cfg(feature = "ext-math")]
Floor = 51,
#[cfg(feature = "flagd")]
Fractional = 60,
#[cfg(feature = "flagd")]
SemVer = 61,
}
const OPCODE_NAMES: &[(&str, OpCode)] = &[
("val", OpCode::Val),
("var", OpCode::Val),
("==", OpCode::Equals),
("===", OpCode::StrictEquals),
("!=", OpCode::NotEquals),
("!==", OpCode::StrictNotEquals),
(">", OpCode::GreaterThan),
(">=", OpCode::GreaterThanEqual),
("<", OpCode::LessThan),
("<=", OpCode::LessThanEqual),
("!", OpCode::Not),
("!!", OpCode::BoolCast),
("and", OpCode::And),
("or", OpCode::Or),
("if", OpCode::If),
("?:", OpCode::If),
("+", OpCode::Add),
("-", OpCode::Subtract),
("*", OpCode::Multiply),
("/", OpCode::Divide),
("%", OpCode::Modulo),
("max", OpCode::Max),
("min", OpCode::Min),
("cat", OpCode::Concat),
("substr", OpCode::Substr),
("in", OpCode::In),
("merge", OpCode::Merge),
("filter", OpCode::Filter),
("map", OpCode::Map),
("reduce", OpCode::Reduce),
("all", OpCode::All),
("some", OpCode::Some),
("none", OpCode::None),
("missing", OpCode::Missing),
("missing_some", OpCode::MissingSome),
#[cfg(feature = "datetime")]
("datetime", OpCode::Datetime),
#[cfg(feature = "datetime")]
("timestamp", OpCode::Timestamp),
#[cfg(feature = "datetime")]
("parse_date", OpCode::ParseDate),
#[cfg(feature = "datetime")]
("format_date", OpCode::FormatDate),
#[cfg(feature = "datetime")]
("date_diff", OpCode::DateDiff),
#[cfg(feature = "datetime")]
("now", OpCode::Now),
#[cfg(feature = "ext-string")]
("length", OpCode::Length),
#[cfg(feature = "ext-string")]
("starts_with", OpCode::StartsWith),
#[cfg(feature = "ext-string")]
("ends_with", OpCode::EndsWith),
#[cfg(feature = "ext-string")]
("upper", OpCode::Upper),
#[cfg(feature = "ext-string")]
("lower", OpCode::Lower),
#[cfg(feature = "ext-string")]
("trim", OpCode::Trim),
#[cfg(feature = "ext-string")]
("split", OpCode::Split),
#[cfg(feature = "ext-array")]
("sort", OpCode::Sort),
#[cfg(feature = "ext-array")]
("slice", OpCode::Slice),
#[cfg(feature = "ext-control")]
("exists", OpCode::Exists),
#[cfg(feature = "ext-control")]
("??", OpCode::Coalesce),
#[cfg(feature = "ext-control")]
("switch", OpCode::Switch),
#[cfg(feature = "ext-control")]
("match", OpCode::Switch),
#[cfg(feature = "ext-control")]
("type", OpCode::Type),
#[cfg(feature = "error-handling")]
("try", OpCode::Try),
#[cfg(feature = "error-handling")]
("throw", OpCode::Throw),
#[cfg(feature = "ext-math")]
("abs", OpCode::Abs),
#[cfg(feature = "ext-math")]
("ceil", OpCode::Ceil),
#[cfg(feature = "ext-math")]
("floor", OpCode::Floor),
#[cfg(feature = "flagd")]
("fractional", OpCode::Fractional),
#[cfg(feature = "flagd")]
("sem_ver", OpCode::SemVer),
];
impl FromStr for OpCode {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
for (name, op) in OPCODE_NAMES {
if *name == s {
return Ok(*op);
}
}
Err(())
}
}
impl OpCode {
pub fn as_str(&self) -> &'static str {
match self {
OpCode::Val => "val",
OpCode::Equals => "==",
OpCode::StrictEquals => "===",
OpCode::NotEquals => "!=",
OpCode::StrictNotEquals => "!==",
OpCode::GreaterThan => ">",
OpCode::GreaterThanEqual => ">=",
OpCode::LessThan => "<",
OpCode::LessThanEqual => "<=",
OpCode::Not => "!",
OpCode::BoolCast => "!!",
OpCode::And => "and",
OpCode::Or => "or",
OpCode::If => "if",
OpCode::Add => "+",
OpCode::Subtract => "-",
OpCode::Multiply => "*",
OpCode::Divide => "/",
OpCode::Modulo => "%",
OpCode::Max => "max",
OpCode::Min => "min",
OpCode::Concat => "cat",
OpCode::Substr => "substr",
OpCode::In => "in",
OpCode::Merge => "merge",
OpCode::Filter => "filter",
OpCode::Map => "map",
OpCode::Reduce => "reduce",
OpCode::All => "all",
OpCode::Some => "some",
OpCode::None => "none",
OpCode::Missing => "missing",
OpCode::MissingSome => "missing_some",
#[cfg(feature = "datetime")]
OpCode::Datetime => "datetime",
#[cfg(feature = "datetime")]
OpCode::Timestamp => "timestamp",
#[cfg(feature = "datetime")]
OpCode::ParseDate => "parse_date",
#[cfg(feature = "datetime")]
OpCode::FormatDate => "format_date",
#[cfg(feature = "datetime")]
OpCode::DateDiff => "date_diff",
#[cfg(feature = "datetime")]
OpCode::Now => "now",
#[cfg(feature = "ext-string")]
OpCode::Length => "length",
#[cfg(feature = "ext-string")]
OpCode::StartsWith => "starts_with",
#[cfg(feature = "ext-string")]
OpCode::EndsWith => "ends_with",
#[cfg(feature = "ext-string")]
OpCode::Upper => "upper",
#[cfg(feature = "ext-string")]
OpCode::Lower => "lower",
#[cfg(feature = "ext-string")]
OpCode::Trim => "trim",
#[cfg(feature = "ext-string")]
OpCode::Split => "split",
#[cfg(feature = "ext-array")]
OpCode::Sort => "sort",
#[cfg(feature = "ext-array")]
OpCode::Slice => "slice",
#[cfg(feature = "ext-control")]
OpCode::Exists => "exists",
#[cfg(feature = "ext-control")]
OpCode::Coalesce => "??",
#[cfg(feature = "ext-control")]
OpCode::Switch => "switch",
#[cfg(feature = "ext-control")]
OpCode::Type => "type",
#[cfg(feature = "error-handling")]
OpCode::Try => "try",
#[cfg(feature = "error-handling")]
OpCode::Throw => "throw",
#[cfg(feature = "ext-math")]
OpCode::Abs => "abs",
#[cfg(feature = "ext-math")]
OpCode::Ceil => "ceil",
#[cfg(feature = "ext-math")]
OpCode::Floor => "floor",
#[cfg(feature = "flagd")]
OpCode::Fractional => "fractional",
#[cfg(feature = "flagd")]
OpCode::SemVer => "sem_ver",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn as_str_round_trips_through_from_str() {
for (name, expected) in OPCODE_NAMES {
let parsed = OpCode::from_str(name).expect("OPCODE_NAMES entry must parse");
assert_eq!(
parsed, *expected,
"OPCODE_NAMES entry {name:?} parses to {parsed:?}, expected {expected:?}"
);
let canonical = parsed.as_str();
let reparsed = OpCode::from_str(canonical)
.expect("canonical name from `as_str` must parse via `from_str`");
assert_eq!(
reparsed, *expected,
"canonical {canonical:?} for {expected:?} re-parses to {reparsed:?}"
);
}
}
}