Skip to content

Commit

Permalink
Rebase, and add type definition tests
Browse files Browse the repository at this point in the history
Signed-off-by: Luc Perkins <luc@timber.io>
  • Loading branch information
Luc Perkins committed Dec 20, 2020
1 parent c6855b9 commit efa9270
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 20 deletions.
2 changes: 2 additions & 0 deletions lib/remap-functions/Cargo.toml
Expand Up @@ -81,6 +81,7 @@ default = [
"to_bool",
"to_float",
"to_int",
"to_severity",
"to_string",
"to_timestamp",
"tokenize",
Expand Down Expand Up @@ -135,6 +136,7 @@ strip_whitespace = []
to_bool = ["shared/conversion"]
to_float = ["shared/conversion"]
to_int = ["shared/conversion"]
to_severity = []
to_string = []
to_timestamp = ["chrono"]
tokenize = ["shared/tokenize"]
Expand Down
6 changes: 6 additions & 0 deletions lib/remap-functions/src/lib.rs
Expand Up @@ -92,6 +92,8 @@ mod to_bool;
mod to_float;
#[cfg(feature = "to_int")]
mod to_int;
#[cfg(feature = "to_severity")]
mod to_severity;
#[cfg(feature = "to_string")]
mod to_string;
#[cfg(feature = "to_timestamp")]
Expand Down Expand Up @@ -199,6 +201,8 @@ pub use to_bool::ToBool;
pub use to_float::ToFloat;
#[cfg(feature = "to_int")]
pub use to_int::ToInt;
#[cfg(feature = "to_severity")]
pub use to_severity::ToSeverity;
#[cfg(feature = "to_string")]
pub use to_string::ToString;
#[cfg(feature = "to_timestamp")]
Expand Down Expand Up @@ -306,6 +310,8 @@ pub fn all() -> Vec<Box<dyn remap::Function>> {
Box::new(ToFloat),
#[cfg(feature = "to_int")]
Box::new(ToInt),
#[cfg(feature = "to_severity")]
Box::new(ToSeverity),
#[cfg(feature = "to_string")]
Box::new(ToString),
#[cfg(feature = "to_timestamp")]
Expand Down
59 changes: 39 additions & 20 deletions lib/remap-functions/src/to_severity.rs
Expand Up @@ -10,27 +10,27 @@ impl Function for ToSeverity {

fn parameters(&self) -> &'static [Parameter] {
&[Parameter {
keyword: "level",
keyword: "value",
accepts: |v| matches!(v, Value::Bytes(_)),
required: true,
}]
}

fn compile(&self, mut arguments: ArgumentList) -> Result<Box<dyn Expression>> {
let level = arguments.required("level")?.boxed();
let value = arguments.required("value")?.boxed();

Ok(Box::new(ToSeverityFn { level }))
Ok(Box::new(ToSeverityFn { value }))
}
}

#[derive(Debug, Clone)]
struct ToSeverityFn {
level: Box<dyn Expression>,
value: Box<dyn Expression>,
}

impl Expression for ToSeverityFn {
fn execute(&self, state: &mut state::Program, object: &mut dyn Object) -> Result<Value> {
let level_bytes = self.level.execute(state, object)?.try_bytes()?;
let level_bytes = self.value.execute(state, object)?.try_bytes()?;

let level = String::from_utf8_lossy(&level_bytes);

Expand All @@ -53,68 +53,87 @@ impl Expression for ToSeverityFn {
}
}

fn type_def(&self, _: &state::Compiler) -> TypeDef {
TypeDef {
kind: value::Kind::Integer,
..Default::default()
}
fn type_def(&self, state: &state::Compiler) -> TypeDef {
use value::Kind;

self.value
.type_def(state)
.fallible_unless(Kind::Bytes)
.with_constraint(Kind::Integer)
}
}

#[cfg(test)]
mod tests {
use super::*;
use value::Kind;

test_type_def![
value_string_infallible {
expr: |_| IncludesFn {
value: Literal::from("warning").boxed(),
},
def: TypeDef { fallible: false, kind: Kind::Integer, ..Default::default() },
}

value_not_string_fallible {
expr: |_| IncludesFn {
value: Literal::from(27).boxed(),
},
def: TypeDef { fallible: true, kind: Kind::Integer, ..Default::default() },
}
];

test_function![
to_level => ToSeverity;

emergency {
args: func_args![level: value!("emerg")],
args: func_args![value: value!("emerg")],
want: Ok(value!(0)),
}

alert {
args: func_args![level: value!("alert")],
args: func_args![value: value!("alert")],
want: Ok(value!(1)),
}

critical {
args: func_args![level: value!("crit")],
args: func_args![value: value!("crit")],
want: Ok(value!(2)),
}

error {
args: func_args![level: value!("err")],
args: func_args![value: value!("err")],
want: Ok(value!(3)),
}

warning {
args: func_args![level: value!("warn")],
args: func_args![value: value!("warn")],
want: Ok(value!(4)),
}

notice {
args: func_args![level: value!("notice")],
args: func_args![value: value!("notice")],
want: Ok(value!(5)),
}

informational {
args: func_args![level: value!("info")],
args: func_args![value: value!("info")],
want: Ok(value!(6)),
}

debug {
args: func_args![level: value!("debug")],
args: func_args![value: value!("debug")],
want: Ok(value!(7)),
}

invalid_level_1 {
args: func_args![level: value!("oopsie")],
args: func_args![value: value!("oopsie")],
want: Err("function call error: level oopsie not valid"),
}

invalid_level_2 {
args: func_args![level: value!("aww shucks")],
args: func_args![value: value!("aww shucks")],
want: Err("function call error:: level aww schucks not valid"),
}
];
Expand Down

0 comments on commit efa9270

Please sign in to comment.