Skip to main content

iggy_binary_protocol/requests/system/
get_snapshot.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::WireError;
19use crate::codec::{WireDecode, WireEncode, read_u8};
20use bytes::{BufMut, BytesMut};
21
22/// `GetSnapshot` request.
23///
24/// Wire format:
25/// ```text
26/// [compression:1][types_count:1][snapshot_type:1]*
27/// ```
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct GetSnapshotRequest {
30    /// Compression method code (1=Stored, 2=Deflated, 3=Bzip2, 4=Zstd, 5=Lzma, 6=Xz).
31    pub compression: u8,
32    /// Snapshot type codes (1=FilesystemOverview, 2=ProcessList, 3=ResourceUsage,
33    /// 4=Test, 5=ServerLogs, 6=ServerConfig, 100=All).
34    pub snapshot_types: Vec<u8>,
35}
36
37impl WireEncode for GetSnapshotRequest {
38    fn encoded_size(&self) -> usize {
39        1 + 1 + self.snapshot_types.len()
40    }
41
42    fn encode(&self, buf: &mut BytesMut) {
43        buf.put_u8(self.compression);
44        let count =
45            u8::try_from(self.snapshot_types.len()).expect("snapshot_types count exceeds u8::MAX");
46        buf.put_u8(count);
47        for &code in &self.snapshot_types {
48            buf.put_u8(code);
49        }
50    }
51}
52
53impl WireDecode for GetSnapshotRequest {
54    fn decode(buf: &[u8]) -> Result<(Self, usize), WireError> {
55        let compression = read_u8(buf, 0)?;
56        let types_count = read_u8(buf, 1)? as usize;
57        let mut pos = 2;
58        let mut snapshot_types = Vec::with_capacity(types_count);
59        for _ in 0..types_count {
60            snapshot_types.push(read_u8(buf, pos)?);
61            pos += 1;
62        }
63        Ok((
64            Self {
65                compression,
66                snapshot_types,
67            },
68            pos,
69        ))
70    }
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn roundtrip() {
79        let req = GetSnapshotRequest {
80            compression: 2,
81            snapshot_types: vec![1, 5],
82        };
83        let bytes = req.to_bytes();
84        assert_eq!(bytes.len(), 4); // 1 + 1 + 2
85        let (decoded, consumed) = GetSnapshotRequest::decode(&bytes).unwrap();
86        assert_eq!(consumed, bytes.len());
87        assert_eq!(decoded, req);
88    }
89
90    #[test]
91    fn roundtrip_empty_types() {
92        let req = GetSnapshotRequest {
93            compression: 1,
94            snapshot_types: vec![],
95        };
96        let bytes = req.to_bytes();
97        assert_eq!(bytes.len(), 2);
98        let (decoded, consumed) = GetSnapshotRequest::decode(&bytes).unwrap();
99        assert_eq!(consumed, 2);
100        assert_eq!(decoded, req);
101    }
102
103    #[test]
104    fn roundtrip_all_type() {
105        let req = GetSnapshotRequest {
106            compression: 2,
107            snapshot_types: vec![100],
108        };
109        let bytes = req.to_bytes();
110        let (decoded, consumed) = GetSnapshotRequest::decode(&bytes).unwrap();
111        assert_eq!(consumed, bytes.len());
112        assert_eq!(decoded, req);
113    }
114
115    #[test]
116    fn truncated_returns_error() {
117        let req = GetSnapshotRequest {
118            compression: 2,
119            snapshot_types: vec![1, 2, 3],
120        };
121        let bytes = req.to_bytes();
122        for i in 0..bytes.len() {
123            assert!(
124                GetSnapshotRequest::decode(&bytes[..i]).is_err(),
125                "expected error for truncation at byte {i}"
126            );
127        }
128    }
129}