Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion engine/src/functions/concat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ fn concat_bytes<'a>(mut accumulator: Cow<'a, [u8]>, args: FunctionArgs<'_, 'a>)
accumulator
}

const EXPECTED_TYPES: [ExpectedType; 2] = [ExpectedType::Array, ExpectedType::Type(Type::Bytes)];
pub(crate) const EXPECTED_TYPES: [ExpectedType; 2] =
[ExpectedType::Array, ExpectedType::Type(Type::Bytes)];

impl FunctionDefinition for ConcatFunction {
fn check_param(
Expand Down
6 changes: 3 additions & 3 deletions engine/src/functions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod all;
mod any;
mod concat;
pub(crate) mod all;
pub(crate) mod any;
pub(crate) mod concat;

use crate::{
filter::CompiledValueResult,
Expand Down
45 changes: 41 additions & 4 deletions engine/src/scheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,15 +628,20 @@ macro_rules! Scheme {

#[test]
fn test_parse_error() {
use crate::types::TypeMismatchError;
use crate::types::{ExpectedTypeList, TypeMismatchError};
use crate::ConcatFunction;
use indoc::indoc;

let scheme = &Scheme! {
let mut scheme = Scheme! {
num: Int,
str: Bytes,
arr: Array(Bool),
};

scheme
.add_function("concat", ConcatFunction::new())
.unwrap();

{
let err = scheme.parse("xyz").unwrap_err();
assert_eq!(
Expand Down Expand Up @@ -768,7 +773,7 @@ fn test_parse_error() {
r#"
Filter parsing error (1:12):
arr and arr
^ expected value of type {Type(Bool)}, but got Array(Bool)
^ expected value of type Bool, but got Array<Bool>
"#
)
);
Expand All @@ -795,7 +800,7 @@ fn test_parse_error() {
r#"
Filter parsing error (1:2):
arr[*]
^^^^^^ expected value of type {Type(Bool)}, but got Array(Bool)
^^^^^^ expected value of type Bool, but got Array<Bool>
"#
)
);
Expand Down Expand Up @@ -872,6 +877,38 @@ fn test_parse_error() {
)
);
}

{
let err = scheme.parse(indoc!(r"concat(0, 0) == 0")).unwrap_err();
assert_eq!(
err,
ParseError {
kind: LexErrorKind::InvalidArgumentType {
index: 0,
mismatch: TypeMismatchError {
expected: ExpectedTypeList::from(
crate::functions::concat::EXPECTED_TYPES.into_iter()
),
actual: Type::Int,
},
},
input: "concat(0, 0) == 0",
line_number: 0,
span_start: 7,
span_len: 1,
}
);
assert_eq!(
err.to_string(),
indoc!(
r#"
Filter parsing error (1:8):
concat(0, 0) == 0
^ invalid type of argument #0: expected value of type Bytes or Array<_>, but got Int
"#
)
);
}
}

#[test]
Expand Down
34 changes: 31 additions & 3 deletions engine/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ impl From<Type> for ExpectedType {
}
}

impl std::fmt::Display for ExpectedType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ExpectedType::Array => write!(f, "Array<_>"),
ExpectedType::Map => write!(f, "Map<_>"),
ExpectedType::Type(ty) => write!(f, "{}", ty),
}
}
}

/// A list of expected types.
#[derive(Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ExpectedTypeList(BTreeSet<ExpectedType>);
Expand Down Expand Up @@ -96,7 +106,25 @@ impl<T: Iterator<Item = ExpectedType>> From<T> for ExpectedTypeList {

impl std::fmt::Display for ExpectedTypeList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
match self.0.len() {
0 => unreachable!(),
1 => write!(f, "{}", self.0.first().unwrap()),
2 => write!(
f,
"{} or {}",
self.0.first().unwrap(),
self.0.last().unwrap()
),
_ => {
let mut iter = self.0.iter();
let first = iter.next().unwrap();
write!(f, "{{{}", first)?;
for expected_type in iter {
write!(f, ", {}", expected_type)?;
}
write!(f, "}}")
}
}
}
}

Expand Down Expand Up @@ -399,8 +427,8 @@ impl std::fmt::Display for Type {
Self::Bytes => write!(f, "Bytes"),
Self::Int => write!(f, "Int"),
Self::Ip => write!(f, "Ip"),
Self::Array(ty) => write!(f, "Array({})", Type::from(*ty)),
Self::Map(ty) => write!(f, "Map({})", Type::from(*ty)),
Self::Array(ty) => write!(f, "Array<{}>", Type::from(*ty)),
Self::Map(ty) => write!(f, "Map<{}>", Type::from(*ty)),
}
}
}
Expand Down