ssh_packet/
packet.rs

1use binrw::{
2    BinRead, BinWrite,
3    meta::{ReadEndian, WriteEndian},
4};
5
6/// A packet _deserialization_ & _serialization_ helper.
7///
8/// see <https://datatracker.ietf.org/doc/html/rfc4253#section-6>.
9#[derive(Debug, Clone)]
10pub struct Packet(pub Vec<u8>);
11
12impl Packet {
13    /// Maximum size for a SSH packet, coincidentally this is
14    /// the maximum size for a TCP packet.
15    pub const MAX_SIZE: usize = u16::MAX as usize;
16
17    /// Minimum size for a SSH packet, coincidentally this is
18    /// the largest block cipher's block-size.
19    pub const MIN_SIZE: usize = 16;
20
21    /// Try to deserialize the [`Packet`] into `T`.
22    pub fn to<T: for<'a> BinRead<Args<'a> = ()> + ReadEndian>(&self) -> Result<T, binrw::Error> {
23        T::read(&mut std::io::Cursor::new(&self.0))
24    }
25}
26
27impl std::ops::Deref for Packet {
28    type Target = [u8];
29
30    fn deref(&self) -> &Self::Target {
31        &self.0
32    }
33}
34
35/// Allow types implementing [`BinWrite`] to be easily converted to a [`Packet`].
36pub trait IntoPacket {
37    /// Convert the current type to a [`Packet`].
38    fn into_packet(self) -> Packet;
39}
40
41impl IntoPacket for Packet {
42    fn into_packet(self) -> Packet {
43        self
44    }
45}
46
47impl<T: for<'a> BinWrite<Args<'a> = ()> + WriteEndian> IntoPacket for &T {
48    fn into_packet(self) -> Packet {
49        let mut buffer = std::io::Cursor::new(Vec::new());
50        self.write(&mut buffer)
51            .expect("failed to convert `impl BinWrite` type to Packet");
52
53        Packet(buffer.into_inner())
54    }
55}