watermelon-proto 0.1.8

#[no_std] NATS Core Sans-IO protocol implementation
Documentation
macro_rules! parse_unsigned {
    ($name:ident, $num:ty) => {
        pub(crate) fn $name(buf: &[u8]) -> Result<$num, ParseUintError> {
            let mut val: $num = 0;

            for &b in buf {
                if !b.is_ascii_digit() {
                    return Err(ParseUintError::InvalidByte(b));
                }

                val = val.checked_mul(10).ok_or(ParseUintError::Overflow)?;
                val = val
                    .checked_add(<$num>::from(b - b'0'))
                    .ok_or(ParseUintError::Overflow)?;
            }

            Ok(val)
        }
    };
}

parse_unsigned!(parse_u16, u16);
parse_unsigned!(parse_u64, u64);
parse_unsigned!(parse_usize, usize);

#[derive(Debug, thiserror::Error)]
pub enum ParseUintError {
    #[error("invalid byte {0:?}")]
    InvalidByte(u8),
    #[error("overflow")]
    Overflow,
}

#[cfg(test)]
mod tests {
    use alloc::string::ToString;

    use claims::assert_ok_eq;

    use super::{parse_u16, parse_u64, parse_usize};

    #[test]
    fn parse_u16_range() {
        for n in 0..=u16::MAX {
            let s = n.to_string();
            assert_ok_eq!(parse_u16(s.as_bytes()), n);
            assert_ok_eq!(parse_usize(s.as_bytes()), usize::from(n));
            assert_ok_eq!(parse_u64(s.as_bytes()), u64::from(n));
        }
    }
}