1use crate::compiler::prelude::*;
2use md5::Digest;
3
4fn md5(value: Value) -> Resolved {
5 let value = value.try_bytes()?;
6 Ok(hex::encode(md5::Md5::digest(&value)).into())
7}
8
9#[derive(Clone, Copy, Debug)]
10pub struct Md5;
11
12impl Function for Md5 {
13 fn identifier(&self) -> &'static str {
14 "md5"
15 }
16
17 fn usage(&self) -> &'static str {
18 "Calculates an md5 hash of the `value`."
19 }
20
21 fn category(&self) -> &'static str {
22 Category::Cryptography.as_ref()
23 }
24
25 fn return_kind(&self) -> u16 {
26 kind::BYTES
27 }
28
29 fn parameters(&self) -> &'static [Parameter] {
30 const PARAMETERS: &[Parameter] = &[Parameter::required(
31 "value",
32 kind::BYTES,
33 "The string to calculate the hash for.",
34 )];
35 PARAMETERS
36 }
37
38 fn examples(&self) -> &'static [Example] {
39 &[example! {
40 title: "Create md5 hash",
41 source: r#"md5("foo")"#,
42 result: Ok("acbd18db4cc2f85cedef654fccc4a4d8"),
43 }]
44 }
45
46 fn compile(
47 &self,
48 _state: &state::TypeState,
49 _ctx: &mut FunctionCompileContext,
50 arguments: ArgumentList,
51 ) -> Compiled {
52 let value = arguments.required("value");
53
54 Ok(Md5Fn { value }.as_expr())
55 }
56}
57
58#[derive(Debug, Clone)]
59struct Md5Fn {
60 value: Box<dyn Expression>,
61}
62
63impl FunctionExpression for Md5Fn {
64 fn resolve(&self, ctx: &mut Context) -> Resolved {
65 let value = self.value.resolve(ctx)?;
66 md5(value)
67 }
68
69 fn type_def(&self, _: &state::TypeState) -> TypeDef {
70 TypeDef::bytes().infallible()
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::value;
78
79 test_function![
80 md5 => Md5;
81
82 md5 {
83 args: func_args![value: "foo"],
84 want: Ok(value!("acbd18db4cc2f85cedef654fccc4a4d8")),
85 tdef: TypeDef::bytes().infallible(),
86 }
87 ];
88}