ssh_packet/crypto/
lengthed.rs

1use std::{io, ops::Deref};
2
3use binrw::{
4    BinRead, BinWrite,
5    meta::{ReadEndian, WriteEndian},
6};
7
8use crate::Packet;
9
10/// An helper to prefix a serializable value with it's `size`.
11#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
12pub struct Lengthed<T>(pub T);
13
14impl<T> Deref for Lengthed<T> {
15    type Target = T;
16
17    fn deref(&self) -> &Self::Target {
18        &self.0
19    }
20}
21
22impl<T> From<T> for Lengthed<T> {
23    fn from(value: T) -> Self {
24        Self(value)
25    }
26}
27
28impl<T> BinRead for Lengthed<T>
29where
30    T: BinRead,
31{
32    type Args<'a> = T::Args<'a>;
33
34    fn read_options<R: std::io::Read + std::io::Seek>(
35        reader: &mut R,
36        endian: binrw::Endian,
37        args: Self::Args<'_>,
38    ) -> binrw::BinResult<Self> {
39        let size = u32::read_be(reader)?;
40        let len = (size as usize).min(Packet::MAX_SIZE);
41
42        let mut buf = Vec::with_capacity(len);
43        reader.read_exact(&mut buf[..len])?;
44
45        T::read_options(&mut io::Cursor::new(&buf), endian, args).map(Self)
46    }
47}
48
49impl<T> ReadEndian for Lengthed<T>
50where
51    T: ReadEndian,
52{
53    const ENDIAN: binrw::meta::EndianKind = T::ENDIAN;
54}
55
56impl<T> BinWrite for Lengthed<T>
57where
58    T: BinWrite,
59{
60    type Args<'a> = T::Args<'a>;
61
62    fn write_options<W: std::io::Write + std::io::Seek>(
63        &self,
64        writer: &mut W,
65        endian: binrw::Endian,
66        args: Self::Args<'_>,
67    ) -> binrw::BinResult<()> {
68        let mut buf = Vec::with_capacity(Packet::MAX_SIZE);
69        self.0
70            .write_options(&mut io::Cursor::new(&mut buf), endian, args)?;
71
72        let len = buf.len();
73        let size: u32 = len.min(Packet::MAX_SIZE) as u32;
74
75        size.write_be(writer)?;
76        Ok(writer.write_all(&buf)?)
77    }
78}
79
80impl<T> WriteEndian for Lengthed<T>
81where
82    T: WriteEndian,
83{
84    const ENDIAN: binrw::meta::EndianKind = T::ENDIAN;
85}