vrl/stdlib/
decode_gzip.rs1use crate::compiler::prelude::*;
2use flate2::read::MultiGzDecoder;
3use std::io::Read;
4
5fn decode_gzip(value: Value) -> Resolved {
6 let value = value.try_bytes()?;
7 let mut buf = Vec::new();
8 let result = MultiGzDecoder::new(std::io::Cursor::new(value)).read_to_end(&mut buf);
9
10 match result {
11 Ok(_) => Ok(Value::Bytes(buf.into())),
12 Err(_) => Err("unable to decode value with Gzip decoder".into()),
13 }
14}
15
16#[derive(Clone, Copy, Debug)]
17pub struct DecodeGzip;
18
19impl Function for DecodeGzip {
20 fn identifier(&self) -> &'static str {
21 "decode_gzip"
22 }
23
24 fn usage(&self) -> &'static str {
25 "Decodes the `value` (a [Gzip](https://www.gzip.org/) string) into its original string."
26 }
27
28 fn category(&self) -> &'static str {
29 Category::Codec.as_ref()
30 }
31
32 fn internal_failure_reasons(&self) -> &'static [&'static str] {
33 &["`value` isn't a valid encoded Gzip string."]
34 }
35
36 fn return_kind(&self) -> u16 {
37 kind::BYTES
38 }
39
40 fn examples(&self) -> &'static [Example] {
41 &[example! {
42 title: "Decode Gzip data",
43 source: r#"decode_gzip!(decode_base64!("H4sIAB8BymMAAyvISU0sTlVISU3OT0lVyE0FAJsZ870QAAAA"))"#,
44 result: Ok("please decode me"),
45 }]
46 }
47
48 fn compile(
49 &self,
50 _state: &state::TypeState,
51 _ctx: &mut FunctionCompileContext,
52 arguments: ArgumentList,
53 ) -> Compiled {
54 let value = arguments.required("value");
55
56 Ok(DecodeGzipFn { value }.as_expr())
57 }
58
59 fn parameters(&self) -> &'static [Parameter] {
60 const PARAMETERS: &[Parameter] = &[Parameter::required(
61 "value",
62 kind::BYTES,
63 "The [Gzip](https://www.gzip.org/) data to decode.",
64 )];
65 PARAMETERS
66 }
67}
68
69#[derive(Clone, Debug)]
70struct DecodeGzipFn {
71 value: Box<dyn Expression>,
72}
73
74impl FunctionExpression for DecodeGzipFn {
75 fn resolve(&self, ctx: &mut Context) -> Resolved {
76 let value = self.value.resolve(ctx)?;
77
78 decode_gzip(value)
79 }
80
81 fn type_def(&self, _: &state::TypeState) -> TypeDef {
82 TypeDef::bytes().fallible()
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use crate::value;
91 use flate2::read::GzEncoder;
92 use nom::AsBytes;
93
94 fn get_encoded_bytes(text: &str) -> Vec<u8> {
95 let mut buf = Vec::new();
96 let mut gz = GzEncoder::new(text.as_bytes(), flate2::Compression::fast());
97 gz.read_to_end(&mut buf)
98 .expect("Cannot encode bytes with Gzip encoder");
99 buf
100 }
101
102 test_function![
103 decode_gzip => DecodeGzip;
104
105 right_gzip {
106 args: func_args![value: value!(get_encoded_bytes("sample").as_bytes())],
107 want: Ok(value!(b"sample")),
108 tdef: TypeDef::bytes().fallible(),
109 }
110
111 wrong_gzip {
112 args: func_args![value: value!("some_bytes")],
113 want: Err("unable to decode value with Gzip decoder"),
114 tdef: TypeDef::bytes().fallible(),
115 }
116 ];
117}