Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use compact_str::CompactString;
|
||||
use regex::Regex;
|
||||
use registry::schema::{
|
||||
enums::{ExpressionConstant, ExpressionVariable},
|
||||
structs::Rate,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{Display, Formatter},
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
str::FromStr,
|
||||
time::Duration,
|
||||
};
|
||||
use trc::MetricType;
|
||||
use utils::cache::CacheItemWeight;
|
||||
|
||||
use crate::expr::if_block::IfBlock;
|
||||
|
||||
pub mod eval;
|
||||
pub mod functions;
|
||||
pub mod if_block;
|
||||
pub mod parser;
|
||||
pub mod tokenizer;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
||||
#[repr(transparent)]
|
||||
pub struct Expression {
|
||||
pub items: Box<[ExpressionItem]>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ExpressionItem {
|
||||
Variable(ExpressionVariable),
|
||||
Global(CompactString),
|
||||
System(SystemVariable),
|
||||
Capture(u32),
|
||||
Constant(Constant),
|
||||
BinaryOperator(BinaryOperator),
|
||||
UnaryOperator(UnaryOperator),
|
||||
Regex(Regex),
|
||||
JmpIf { val: bool, pos: u32 },
|
||||
Function { id: u32, num_args: u32 },
|
||||
ArrayAccess,
|
||||
ArrayBuild(u32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Variable<'x> {
|
||||
String(StringCow<'x>),
|
||||
Integer(i64),
|
||||
Float(f64),
|
||||
Array(Vec<Variable<'x>>),
|
||||
Constant(ExpressionConstant),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StringCow<'x> {
|
||||
Owned(CompactString),
|
||||
Borrowed(&'x str),
|
||||
}
|
||||
|
||||
impl Default for Variable<'_> {
|
||||
fn default() -> Self {
|
||||
Variable::String(StringCow::Borrowed(""))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Constant {
|
||||
Static(ExpressionConstant),
|
||||
Integer(i64),
|
||||
Float(f64),
|
||||
String(CompactString),
|
||||
}
|
||||
|
||||
impl Eq for Constant {}
|
||||
|
||||
impl From<CompactString> for Constant {
|
||||
fn from(value: CompactString) -> Self {
|
||||
Constant::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Constant {
|
||||
fn from(value: bool) -> Self {
|
||||
Constant::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Constant {
|
||||
fn from(value: i64) -> Self {
|
||||
Constant::Integer(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Constant {
|
||||
fn from(value: i32) -> Self {
|
||||
Constant::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i16> for Constant {
|
||||
fn from(value: i16) -> Self {
|
||||
Constant::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Constant {
|
||||
fn from(value: f64) -> Self {
|
||||
Constant::Float(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Constant {
|
||||
fn from(value: usize) -> Self {
|
||||
Constant::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum BinaryOperator {
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
|
||||
Eq,
|
||||
Ne,
|
||||
Lt,
|
||||
Le,
|
||||
Gt,
|
||||
Ge,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum UnaryOperator {
|
||||
Not,
|
||||
Minus,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Token {
|
||||
Variable(ExpressionVariable),
|
||||
Global(CompactString),
|
||||
Capture(u32),
|
||||
Function {
|
||||
name: Cow<'static, str>,
|
||||
id: u32,
|
||||
num_args: u32,
|
||||
},
|
||||
Constant(Constant),
|
||||
System(SystemVariable),
|
||||
Regex(Regex),
|
||||
BinaryOperator(BinaryOperator),
|
||||
UnaryOperator(UnaryOperator),
|
||||
OpenParen,
|
||||
CloseParen,
|
||||
OpenBracket,
|
||||
CloseBracket,
|
||||
Comma,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SystemVariable {
|
||||
Hostname,
|
||||
Domain,
|
||||
NodeId,
|
||||
NodeHostname,
|
||||
NodeRole,
|
||||
Metric(MetricType),
|
||||
}
|
||||
|
||||
impl From<usize> for Variable<'_> {
|
||||
fn from(value: usize) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Variable<'_> {
|
||||
fn from(value: i64) -> Self {
|
||||
Variable::Integer(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for Variable<'_> {
|
||||
fn from(value: u64) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Variable<'_> {
|
||||
fn from(value: i32) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Variable<'_> {
|
||||
fn from(value: u32) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for Variable<'_> {
|
||||
fn from(value: u16) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i16> for Variable<'_> {
|
||||
fn from(value: i16) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Variable<'_> {
|
||||
fn from(value: f64) -> Self {
|
||||
Variable::Float(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> From<&'x str> for Variable<'x> {
|
||||
fn from(value: &'x str) -> Self {
|
||||
Variable::String(StringCow::Borrowed(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompactString> for Variable<'_> {
|
||||
fn from(value: CompactString) -> Self {
|
||||
Variable::String(StringCow::Owned(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> From<Vec<Variable<'x>>> for Variable<'x> {
|
||||
fn from(value: Vec<Variable<'x>>) -> Self {
|
||||
Variable::Array(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Variable<'_> {
|
||||
fn from(value: bool) -> Self {
|
||||
Variable::Integer(value as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Constant>> From<T> for Expression {
|
||||
fn from(value: T) -> Self {
|
||||
Expression {
|
||||
items: Box::new([ExpressionItem::Constant(value.into())]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ExpressionItem {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Variable(l0), Self::Variable(r0)) => l0 == r0,
|
||||
(Self::Constant(l0), Self::Constant(r0)) => l0 == r0,
|
||||
(Self::BinaryOperator(l0), Self::BinaryOperator(r0)) => l0 == r0,
|
||||
(Self::UnaryOperator(l0), Self::UnaryOperator(r0)) => l0 == r0,
|
||||
(Self::Regex(_), Self::Regex(_)) => true,
|
||||
(
|
||||
Self::JmpIf {
|
||||
val: l_val,
|
||||
pos: l_pos,
|
||||
},
|
||||
Self::JmpIf {
|
||||
val: r_val,
|
||||
pos: r_pos,
|
||||
},
|
||||
) => l_val == r_val && l_pos == r_pos,
|
||||
(
|
||||
Self::Function {
|
||||
id: l_id,
|
||||
num_args: l_num_args,
|
||||
},
|
||||
Self::Function {
|
||||
id: r_id,
|
||||
num_args: r_num_args,
|
||||
},
|
||||
) => l_id == r_id && l_num_args == r_num_args,
|
||||
(Self::ArrayBuild(l0), Self::ArrayBuild(r0)) => l0 == r0,
|
||||
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExpressionItem {}
|
||||
|
||||
impl PartialEq for Token {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Variable(l0), Self::Variable(r0)) => l0 == r0,
|
||||
(
|
||||
Self::Function {
|
||||
name: l_name,
|
||||
id: l_id,
|
||||
num_args: l_num_args,
|
||||
},
|
||||
Self::Function {
|
||||
name: r_name,
|
||||
id: r_id,
|
||||
num_args: r_num_args,
|
||||
},
|
||||
) => l_name == r_name && l_id == r_id && l_num_args == r_num_args,
|
||||
(Self::Constant(l0), Self::Constant(r0)) => l0 == r0,
|
||||
(Self::Regex(_), Self::Regex(_)) => true,
|
||||
(Self::BinaryOperator(l0), Self::BinaryOperator(r0)) => l0 == r0,
|
||||
(Self::UnaryOperator(l0), Self::UnaryOperator(r0)) => l0 == r0,
|
||||
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Token {}
|
||||
|
||||
impl From<()> for Constant {
|
||||
fn from(_: ()) -> Self {
|
||||
Constant::Integer(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> TryFrom<Variable<'x>> for () {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(_: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> TryFrom<Variable<'x>> for Duration {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Variable::Integer(value) if value > 0 => Ok(Duration::from_millis(value as u64)),
|
||||
Variable::Float(value) if value > 0.0 => Ok(Duration::from_millis(value as u64)),
|
||||
Variable::String(value) if !value.is_empty() => {
|
||||
registry::types::duration::Duration::from_str(value.as_str())
|
||||
.map(|v| v.into_inner())
|
||||
.map_err(|_| ())
|
||||
}
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StringCow<'_> {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match self {
|
||||
StringCow::Owned(s) => s.as_str(),
|
||||
StringCow::Borrowed(s) => s,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
match self {
|
||||
StringCow::Owned(s) => s.as_bytes(),
|
||||
StringCow::Borrowed(s) => s.as_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
StringCow::Owned(s) => s.is_empty(),
|
||||
StringCow::Borrowed(s) => s.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
StringCow::Owned(s) => s.len(),
|
||||
StringCow::Borrowed(s) => s.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_owned(self) -> CompactString {
|
||||
match self {
|
||||
StringCow::Owned(s) => s,
|
||||
StringCow::Borrowed(s) => s.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> From<Cow<'x, str>> for StringCow<'x> {
|
||||
fn from(value: Cow<'x, str>) -> Self {
|
||||
match value {
|
||||
Cow::Borrowed(s) => StringCow::Borrowed(s),
|
||||
Cow::Owned(s) => StringCow::Owned(s.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompactString> for StringCow<'_> {
|
||||
fn from(value: CompactString) -> Self {
|
||||
StringCow::Owned(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for StringCow<'_> {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for StringCow<'_> {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_str().as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StringCow<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
StringCow::Owned(s) => write!(f, "{}", s),
|
||||
StringCow::Borrowed(s) => write!(f, "{}", s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Duration> for Constant {
|
||||
fn from(value: Duration) -> Self {
|
||||
Constant::Integer(value.as_millis() as i64)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> TryFrom<Variable<'x>> for Rate {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Variable::Array(items) if items.len() == 2 => {
|
||||
let requests = items[0].to_integer().ok_or(())?;
|
||||
let period = items[1].to_integer().ok_or(())?;
|
||||
|
||||
if requests > 0 && period > 0 {
|
||||
Ok(Rate {
|
||||
count: requests as u64,
|
||||
period: registry::types::duration::Duration::from_millis(period as u64),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> TryFrom<Variable<'x>> for Ipv4Addr {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Variable::String(value) => value.as_str().parse().map_err(|_| ()),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> TryFrom<Variable<'x>> for Ipv6Addr {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Variable::String(value) => value.as_str().parse().map_err(|_| ()),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x> TryFrom<Variable<'x>> for IpAddr {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Variable::String(value) => value.as_str().parse().map_err(|_| ()),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x, T: TryFrom<Variable<'x>>> TryFrom<Variable<'x>> for Vec<T>
|
||||
where
|
||||
Result<Vec<T>, ()>: FromIterator<Result<T, <T as TryFrom<Variable<'x>>>::Error>>,
|
||||
{
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Variable<'x>) -> Result<Self, Self::Error> {
|
||||
value
|
||||
.into_array()
|
||||
.into_iter()
|
||||
.map(|v| T::try_from(v))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheItemWeight for Expression {
|
||||
fn weight(&self) -> u64 {
|
||||
self.items.len() as u64 * std::mem::size_of::<ExpressionItem>() as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheItemWeight for IfBlock {
|
||||
fn weight(&self) -> u64 {
|
||||
std::mem::size_of::<IfBlock>() as u64
|
||||
+ self
|
||||
.if_then
|
||||
.iter()
|
||||
.map(|if_then| if_then.expr.weight() + if_then.then.weight())
|
||||
.sum::<u64>()
|
||||
+ self.default.weight()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user