ssh_packet/arch/
mpint.rs

1use binrw::binrw;
2
3#[cfg(feature = "zeroize")]
4use zeroize::Zeroize;
5
6use super::Bytes;
7
8/// A `mpint` as defined in the SSH protocol.
9///
10/// see <https://datatracker.ietf.org/doc/html/rfc4251#section-5>.
11#[binrw]
12#[derive(Debug, Default, Clone, PartialEq, Eq)]
13#[cfg_attr(feature = "zeroize", derive(Zeroize))]
14pub struct MpInt<'b>(Bytes<'b>);
15
16impl<'b> MpInt<'b> {
17    /// Create a [`MpInt`] from _bytes_.
18    pub fn from_bytes(bytes: impl Into<Bytes<'b>>) -> Self {
19        Self(bytes.into())
20    }
21
22    /// Create a [`MpInt`] from a _slice_, copying it if necessary to ensure it is represented as positive.
23    pub fn positive(value: &'b [u8]) -> Self {
24        match value.first() {
25            Some(byte) if *byte >= 0x80 => {
26                let mut buffer = vec![0u8; value.len() + 1];
27                buffer[1..].copy_from_slice(value);
28
29                Self(Bytes::owned(buffer))
30            }
31            _ => Self(Bytes::borrowed(value)),
32        }
33    }
34
35    /// Obtain an [`MpInt`] from a reference by borrowing the internal buffer.
36    pub fn as_borrow<'a: 'b>(&'a self) -> MpInt<'a> {
37        Self(self.0.as_borrow())
38    }
39}
40
41impl AsRef<[u8]> for MpInt<'_> {
42    fn as_ref(&self) -> &[u8] {
43        &self.0
44    }
45}