ssh-parser 0.5.0

Parser for the SSH protocol
Documentation
use nom::bits::{bits, streaming::take as btake};
use nom::error::Error;
use nom::sequence::pair;
use nom::IResult;
use num_bigint::{BigInt, BigUint, Sign};
use num_traits::identities::Zero;
use std::convert::From;
use std::ops::{AddAssign, Shl, Shr};

struct MpUint(BigUint);

impl AddAssign for MpUint {
    fn add_assign(&mut self, other: MpUint) {
        *self = MpUint(&self.0 + other.0);
    }
}

impl Shr<usize> for MpUint {
    type Output = MpUint;

    fn shr(self, shift: usize) -> MpUint {
        MpUint(&self.0 >> shift)
    }
}

impl Shl<usize> for MpUint {
    type Output = MpUint;

    fn shl(self, shift: usize) -> MpUint {
        MpUint(&self.0 << shift)
    }
}

impl From<u8> for MpUint {
    fn from(i: u8) -> MpUint {
        MpUint(BigUint::from(i))
    }
}

pub fn parse_ssh_mpint(i: &[u8]) -> IResult<&[u8], BigInt> {
    if i.is_empty() {
        Ok((i, BigInt::zero()))
    } else {
        let (i, b) = bits(pair(
            btake::<_, _, _, Error<_>>(1usize),
            btake((i.len() * 8usize - 1) as usize),
        ))(i)?;
        let sign: u8 = b.0;
        let number = MpUint(b.1);
        let bi = BigInt::from_biguint(if sign == 0 { Sign::Plus } else { Sign::Minus }, number.0);
        Ok((i, bi))
    }
}

#[test]
fn test_positive_mpint() {
    let e = [
        0x04, 0xe7, 0x59, 0x2a, 0xe1, 0xb9, 0xb6, 0xbe, 0x7c, 0x81, 0x5f, 0xc8, 0x3d, 0x55, 0x7b,
        0x8f, 0xc7, 0x09, 0x1d, 0x71, 0x6c, 0xed, 0x68, 0x45, 0x6c, 0x31, 0xc7, 0xf3, 0x65, 0x98,
        0xa5, 0x44, 0x7d, 0xa4, 0x28, 0xdd, 0xe7, 0x3a, 0xd9, 0xa1, 0x0e, 0x4b, 0x75, 0x3a, 0xde,
        0x33, 0x99, 0x6e, 0x41, 0x7d, 0xea, 0x88, 0xe9, 0x90, 0xe3, 0x5a, 0x27, 0xf8, 0x38, 0x09,
        0x01, 0x66, 0x46, 0xd4, 0xdc,
    ];
    let expected = Ok((
        b"" as &[u8],
        BigInt::new(
            Sign::Plus,
            vec![
                1715918044, 4164421889, 2430818855, 2112522473, 865693249, 1265973982, 987341070,
                2754141671, 2560967805, 835187557, 3983033708, 152924524, 1434161095, 2170538045,
                3115761276, 3881380577, 4,
            ],
        ),
    ));
    let num = parse_ssh_mpint(&e);
    assert_eq!(num, expected);
}