vrl/stdlib/
decode_snappy.rs1use crate::compiler::prelude::*;
2use snap::raw::Decoder;
3
4fn decode_snappy(value: Value) -> Resolved {
5 let value = value.try_bytes()?;
6 let mut decoder = Decoder::new();
7 let result = decoder.decompress_vec(&value);
8
9 match result {
10 Ok(buf) => Ok(Value::Bytes(buf.into())),
11 Err(_) => Err("unable to decode value with Snappy decoder".into()),
12 }
13}
14
15#[derive(Clone, Copy, Debug)]
16pub struct DecodeSnappy;
17
18impl Function for DecodeSnappy {
19 fn identifier(&self) -> &'static str {
20 "decode_snappy"
21 }
22
23 fn usage(&self) -> &'static str {
24 "Decodes the `value` (a Snappy string) into its original string."
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` isn't a valid encoded 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: "Decode Snappy data",
42 source: r#"decode_snappy!(decode_base64!("LKxUaGUgcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgMTMgbGF6eSBkb2dzLg=="))"#,
43 result: Ok("The quick brown fox jumps over 13 lazy dogs."),
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(DecodeSnappyFn { value }.as_expr())
56 }
57
58 fn parameters(&self) -> &'static [Parameter] {
59 const PARAMETERS: &[Parameter] = &[Parameter::required(
60 "value",
61 kind::BYTES,
62 "The Snappy data to decode.",
63 )];
64 PARAMETERS
65 }
66}
67
68#[derive(Clone, Debug)]
69struct DecodeSnappyFn {
70 value: Box<dyn Expression>,
71}
72
73impl FunctionExpression for DecodeSnappyFn {
74 fn resolve(&self, ctx: &mut Context) -> Resolved {
75 let value = self.value.resolve(ctx)?;
76
77 decode_snappy(value)
78 }
79
80 fn type_def(&self, _: &state::TypeState) -> TypeDef {
81 TypeDef::bytes().fallible()
83 }
84}
85
86#[cfg(test)]
87mod tests {
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 decode_snappy => DecodeSnappy;
100
101 right_snappy {
102 args: func_args![value: value!(decode_base64("LKxUaGUgcXVpY2sgYnJvd24gZm94IGp1bXBzIG92ZXIgMTMgbGF6eSBkb2dzLg==").as_bytes())],
103 want: Ok(value!(b"The quick brown fox jumps over 13 lazy dogs.")),
104 tdef: TypeDef::bytes().fallible(),
105 }
106
107 wrong_snappy {
108 args: func_args![value: value!("some_bytes")],
109 want: Err("unable to decode value with Snappy decoder"),
110 tdef: TypeDef::bytes().fallible(),
111 }
112 ];
113}