ssh_packet/crypto/
lengthed.rs1use std::{io, ops::Deref};
2
3use binrw::{
4 BinRead, BinWrite,
5 meta::{ReadEndian, WriteEndian},
6};
7
8use crate::Packet;
9
10#[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}