Skip to main content

naia_shared/connection/
decoder.rs

1cfg_if! {
2    if #[cfg(feature = "zstd_support")]
3    {
4        use zstd::bulk::Decompressor;
5
6        use super::compression_config::CompressionMode;
7
8        #[derive(Clone)]
9        pub struct Decoder {
10            result: Vec<u8>,
11            decoder: Option<Decompressor<'static>>,
12        }
13
14        impl Decoder {
15            pub fn new(compression_mode: CompressionMode) -> Self {
16                let decoder = match compression_mode {
17                    CompressionMode::Training(_) => None,
18                    CompressionMode::Default(_) => {
19                        Some(Decompressor::new().expect("error creating Decompressor"))
20                    }
21                    CompressionMode::Dictionary(_, dictionary) => Some(
22                        Decompressor::with_dictionary(&dictionary).expect("error creating Decompressor"),
23                    ),
24                };
25
26                Self {
27                    decoder,
28                    result: Vec::new(),
29                }
30            }
31
32            pub fn decode(&mut self, payload: &[u8]) -> &[u8] {
33                // First byte is the is_compressed flag (written by encoder)
34                let (is_compressed, data) = match payload.split_first() {
35                    Some((&flag, rest)) => (flag != 0, rest),
36                    None => {
37                        self.result = Vec::new();
38                        return &self.result;
39                    }
40                };
41
42                if is_compressed {
43                    if let Some(decoder) = &mut self.decoder {
44                        self.result = decoder
45                            .decompress(
46                                data,
47                                Decompressor::<'static>::upper_bound(data)
48                                    .expect("upper bound decode error"),
49                            )
50                            .expect("decode error");
51                        return &self.result;
52                    }
53                }
54                // Not compressed (or no decoder configured): return raw data
55                self.result = data.to_vec();
56                &self.result
57            }
58        }
59    }
60    else
61    {
62        use super::compression_config::CompressionMode;
63
64        /// Packet decoder (no-op variant: passes payload through unchanged).
65        #[derive(Clone)]
66        pub struct Decoder {
67            result: Vec<u8>,
68        }
69
70        impl Decoder {
71            /// Creates a no-op decoder (compression mode is ignored in this build variant).
72            pub fn new(_: CompressionMode) -> Self {
73                Self {
74                    result: Vec::new(),
75                }
76            }
77
78            /// Returns the payload unchanged (no-op decompression).
79            pub fn decode(&mut self, payload: &[u8]) -> &[u8] {
80                self.result = payload.to_vec();
81                &self.result
82            }
83        }
84    }
85}