ssh_packet/arch/
bytes.rs

1use std::ops::Deref;
2
3use binrw::{BinRead, BinWrite};
4
5#[cfg(feature = "zeroize")]
6use zeroize::Zeroize;
7
8#[derive(Debug, Clone)]
9#[cfg_attr(feature = "zeroize", derive(Zeroize))]
10enum Inner<'b> {
11    Owned(Vec<u8>),
12
13    #[cfg_attr(feature = "zeroize", zeroize(skip))]
14    Borrowed(&'b [u8]),
15}
16
17/// A `string` as defined in the SSH protocol.
18///
19/// see <https://datatracker.ietf.org/doc/html/rfc4251#section-5>.
20#[derive(Debug, Clone)]
21#[cfg_attr(feature = "zeroize", derive(Zeroize))]
22pub struct Bytes<'b> {
23    inner: Inner<'b>,
24}
25
26impl<'b> Default for Bytes<'b> {
27    fn default() -> Self {
28        Self {
29            inner: Inner::Owned(Default::default()),
30        }
31    }
32}
33
34impl<'b> Bytes<'b> {
35    /// Create [`Bytes`] from a _vector_.
36    pub const fn owned(value: Vec<u8>) -> Self {
37        Self {
38            inner: Inner::Owned(value),
39        }
40    }
41
42    /// Create [`Bytes`] from a _slice_.
43    pub const fn borrowed(value: &'b [u8]) -> Self {
44        Self {
45            inner: Inner::Borrowed(value),
46        }
47    }
48
49    /// Obtain [`Bytes`] from a reference by borrowing the internal buffer.
50    pub fn as_borrow<'a: 'b>(&'a self) -> Bytes<'a> {
51        Bytes::borrowed(self)
52    }
53
54    /// Extract the buffer into a [`Vec`].
55    pub fn into_vec(self) -> Vec<u8> {
56        match self.inner {
57            Inner::Owned(vec) => vec,
58            Inner::Borrowed(slice) => slice.to_vec(),
59        }
60    }
61}
62
63impl Deref for Bytes<'_> {
64    type Target = [u8];
65
66    fn deref(&self) -> &Self::Target {
67        match self.inner {
68            Inner::Owned(ref vec) => vec,
69            Inner::Borrowed(slice) => slice,
70        }
71    }
72}
73
74impl AsRef<[u8]> for Bytes<'_> {
75    fn as_ref(&self) -> &[u8] {
76        self
77    }
78}
79
80impl PartialEq for Bytes<'_> {
81    fn eq(&self, other: &Bytes<'_>) -> bool {
82        **self == **other
83    }
84}
85
86impl Eq for Bytes<'_> {}
87
88impl From<Vec<u8>> for Bytes<'_> {
89    fn from(value: Vec<u8>) -> Self {
90        Self::owned(value)
91    }
92}
93
94impl<'b> From<&'b [u8]> for Bytes<'b> {
95    fn from(value: &'b [u8]) -> Self {
96        Self::borrowed(value)
97    }
98}
99
100impl BinRead for Bytes<'_> {
101    type Args<'a> = ();
102
103    fn read_options<R: std::io::Read + std::io::Seek>(
104        reader: &mut R,
105        endian: binrw::Endian,
106        args: Self::Args<'_>,
107    ) -> binrw::BinResult<Self> {
108        let size = u32::read_be(reader)?;
109
110        BinRead::read_options(
111            reader,
112            endian,
113            binrw::VecArgs {
114                count: size as usize,
115                inner: args,
116            },
117        )
118        .map(Self::owned)
119    }
120}
121
122impl BinWrite for Bytes<'_> {
123    type Args<'a> = ();
124
125    fn write_options<W: std::io::Write + std::io::Seek>(
126        &self,
127        writer: &mut W,
128        endian: binrw::Endian,
129        args: Self::Args<'_>,
130    ) -> binrw::BinResult<()> {
131        let buf = &**self;
132        let size = buf.len() as u32;
133
134        size.write_be(writer)?;
135        buf.write_options(writer, endian, args)
136    }
137}