messagepack-async 0.2.3

A simple functional library for read/writing messagepack with tokio.
Documentation
use std::num::TryFromIntError;

use super::Value;

#[derive(Clone, Debug, PartialEq)]
pub enum Int {
    U8(u8),
    U16(u16),
    U32(u32),
    U64(u64),
    I8(i8),
    I16(i16),
    I32(i32),
    I64(i64),
}

impl Int {
    pub fn as_u64(&self) -> Option<u64> {
        use Int::*;
        match self {
            U8(i) => Some((*i).into()),
            U16(i) => Some((*i).into()),
            U32(i) => Some((*i).into()),
            U64(i) => Some(*i),
            I8(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
            I16(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
            I32(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
            I64(i) => (*i >= 0).then(|| (*i).try_into().unwrap()),
        }
    }
}

impl Value {
    /// Attempt to create a new Value::Int for the supplied value
    /// that will be encoded in the least amount of bytes.
    ///
    /// Positive and zero integers will become an unsigned
    /// variant, while negative integers will become a signed
    /// variant.
    pub fn r#int<T>(value: T) -> Result<Self, TryFromIntError>
    where
        T: Ord + Default + Copy + Clone,
        u8: TryFrom<T>,
        u16: TryFrom<T>,
        u32: TryFrom<T>,
        u64: TryFrom<T, Error = TryFromIntError>,
        i8: TryFrom<T>,
        i16: TryFrom<T>,
        i32: TryFrom<T>,
        i64: TryFrom<T, Error = TryFromIntError>,
    {
        if value >= T::default() {
            Value::unsigned_int(value)
        } else {
            Value::signed_int(value)
        }
    }

    /// Attempt to create a new unsigned Value::Int for the supplied
    /// value that will be encoded in the least amount of bytes.
    pub fn unsigned_int<T>(value: T) -> Result<Self, TryFromIntError>
    where
        T: Copy + Clone,
        u8: TryFrom<T>,
        u16: TryFrom<T>,
        u32: TryFrom<T>,
        u64: TryFrom<T, Error = TryFromIntError>,
    {
        u8::try_from(value)
            .map(Value::from)
            .or_else(|_| u16::try_from(value).map(Value::from))
            .or_else(|_| u32::try_from(value).map(Value::from))
            .or_else(|_| u64::try_from(value).map(Value::from))
    }

    /// Attempt to create a new signed Value::Int for the supplied
    /// value that will be encoded in the least amount of bytes.
    pub fn signed_int<T>(value: T) -> Result<Self, TryFromIntError>
    where
        T: Copy + Clone,
        i8: TryFrom<T>,
        i16: TryFrom<T>,
        i32: TryFrom<T>,
        i64: TryFrom<T, Error = TryFromIntError>,
    {
        i8::try_from(value)
            .map(Value::from)
            .or_else(|_| i16::try_from(value).map(Value::from))
            .or_else(|_| i32::try_from(value).map(Value::from))
            .or_else(|_| i64::try_from(value).map(Value::from))
    }
}

impl From<u8> for Int {
    fn from(value: u8) -> Self {
        Int::U8(value)
    }
}

impl From<u16> for Int {
    fn from(value: u16) -> Self {
        Int::U16(value)
    }
}

impl From<u32> for Int {
    fn from(value: u32) -> Self {
        Int::U32(value)
    }
}

impl From<u64> for Int {
    fn from(value: u64) -> Self {
        Int::U64(value)
    }
}

impl From<i8> for Int {
    fn from(value: i8) -> Self {
        Int::I8(value)
    }
}

impl From<i16> for Int {
    fn from(value: i16) -> Self {
        Int::I16(value)
    }
}

impl From<i32> for Int {
    fn from(value: i32) -> Self {
        Int::I32(value)
    }
}

impl From<i64> for Int {
    fn from(value: i64) -> Self {
        Int::I64(value)
    }
}

impl From<u8> for Value {
    fn from(value: u8) -> Self {
        Value::Int(Int::U8(value))
    }
}

impl From<u16> for Value {
    fn from(value: u16) -> Self {
        Value::Int(Int::U16(value))
    }
}

impl From<u32> for Value {
    fn from(value: u32) -> Self {
        Value::Int(Int::U32(value))
    }
}

impl From<u64> for Value {
    fn from(value: u64) -> Self {
        Value::Int(Int::U64(value))
    }
}

impl From<i8> for Value {
    fn from(value: i8) -> Self {
        Value::Int(Int::I8(value))
    }
}

impl From<i16> for Value {
    fn from(value: i16) -> Self {
        Value::Int(Int::I16(value))
    }
}

impl From<i32> for Value {
    fn from(value: i32) -> Self {
        Value::Int(Int::I32(value))
    }
}

impl From<i64> for Value {
    fn from(value: i64) -> Self {
        Value::Int(Int::I64(value))
    }
}