vrl/stdlib/
encode_snappy.rs

1use crate::compiler::prelude::*;
2use snap::raw::Encoder;
3
4fn encode_snappy(value: Value) -> Resolved {
5    let value = value.try_bytes()?;
6    let mut encoder = Encoder::new();
7    let result = encoder.compress_vec(&value);
8
9    match result {
10        Ok(buf) => Ok(Value::Bytes(buf.into())),
11        Err(_) => Err("unable to encode value with Snappy encoder".into()),
12    }
13}
14
15#[derive(Clone, Copy, Debug)]
16pub struct EncodeSnappy;
17
18impl Function for EncodeSnappy {
19    fn identifier(&self) -> &'static str {
20        "encode_snappy"
21    }
22
23    fn usage(&self) -> &'static str {
24        "Encodes the `value` to Snappy."
25    }
26
27    fn category(&self) -> &'static str {
28        Category::Codec.as_ref()
29    }
30
31    fn internal_failure_reasons(&self) -> &'static [&'static str] {
32        &["`value` cannot be encoded into a Snappy string."]
33    }
34
35    fn return_kind(&self) -> u16 {
36        kind::BYTES
37    }
38
39    fn examples(&self) -> &'static [Example] {
40        &[example! {
41            title: "Encode to Snappy",
42            source: r#"encode_base64(encode_snappy!("The quick brown fox jumps over 13 lazy dogs."))"#,
43            result: Ok("LKxUaGUgcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgMTMgbGF6eSBkb2dzLg=="),
44        }]
45    }
46
47    fn compile(
48        &self,
49        _state: &state::TypeState,
50        _ctx: &mut FunctionCompileContext,
51        arguments: ArgumentList,
52    ) -> Compiled {
53        let value = arguments.required("value");
54
55        Ok(EncodeSnappyFn { value }.as_expr())
56    }
57
58    fn parameters(&self) -> &'static [Parameter] {
59        const PARAMETERS: &[Parameter] = &[Parameter::required(
60            "value",
61            kind::BYTES,
62            "The string to encode.",
63        )];
64        PARAMETERS
65    }
66}
67
68#[derive(Clone, Debug)]
69struct EncodeSnappyFn {
70    value: Box<dyn Expression>,
71}
72
73impl FunctionExpression for EncodeSnappyFn {
74    fn resolve(&self, ctx: &mut Context) -> Resolved {
75        let value = self.value.resolve(ctx)?;
76
77        encode_snappy(value)
78    }
79
80    fn type_def(&self, _state: &state::TypeState) -> TypeDef {
81        // Always fallible due to the possibility of decoding errors that VRL can't detect
82        TypeDef::bytes().fallible()
83    }
84}
85
86#[cfg(test)]
87mod test {
88    use super::*;
89    use crate::value;
90    use nom::AsBytes;
91
92    fn decode_base64(text: &str) -> Vec<u8> {
93        base64_simd::STANDARD
94            .decode_to_vec(text)
95            .expect("Cannot decode from Base64")
96    }
97
98    test_function![
99        encode_snappy => EncodeSnappy;
100
101        success {
102            args: func_args![value: value!("The quick brown fox jumps over 13 lazy dogs.")],
103            want: Ok(value!(decode_base64("LKxUaGUgcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgMTMgbGF6eSBkb2dzLg==").as_bytes())),
104            tdef: TypeDef::bytes().fallible(),
105        }
106    ];
107}