use messagepack_core::{
Encode,
encode::{Error, float::EncodeMinimizeFloat, int::EncodeMinimizeInt},
io::IoWrite,
};
use num_traits::{ToPrimitive, float::FloatCore};
pub trait NumEncoder<W: IoWrite> {
fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<W::Error>>;
fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<W::Error>>;
}
pub struct Exact;
impl<W: IoWrite> NumEncoder<W> for Exact {
fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
v.encode(writer)
}
}
pub struct LosslessMinimize;
impl LosslessMinimize {
fn encode_int<T: ToPrimitive, W: IoWrite>(
v: T,
writer: &mut W,
) -> Result<usize, Error<<W as IoWrite>::Error>> {
EncodeMinimizeInt(v).encode(writer)
}
fn encode_float<T: Into<EncodeMinimizeFloat>, W: IoWrite>(
v: T,
writer: &mut W,
) -> Result<usize, Error<<W as IoWrite>::Error>> {
let encoder: EncodeMinimizeFloat = v.into();
let size = encoder.encode(writer)?;
Ok(size)
}
}
impl<W: IoWrite> NumEncoder<W> for LosslessMinimize {
fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_float(v, writer)
}
fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_float(v, writer)
}
}
pub struct AggressiveMinimize;
impl AggressiveMinimize {
fn encode_int<T: ToPrimitive, W: IoWrite>(
v: T,
writer: &mut W,
) -> Result<usize, Error<<W as IoWrite>::Error>> {
EncodeMinimizeInt(v).encode(writer)
}
fn encode_float<T: FloatCore + Into<EncodeMinimizeFloat>, W: IoWrite>(
v: T,
writer: &mut W,
) -> Result<usize, Error<<W as IoWrite>::Error>> {
if v.is_finite() && v.fract().is_zero() {
let size = Self::encode_int(v, writer).or_else(|_| v.into().encode(writer))?;
Ok(size)
} else {
let size = v.into().encode(writer)?;
Ok(size)
}
}
}
impl<W: IoWrite> NumEncoder<W> for AggressiveMinimize {
fn encode_i8(v: i8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i16(v: i16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i32(v: i32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i64(v: i64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_i128(v: i128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u8(v: u8, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u16(v: u16, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u32(v: u32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u64(v: u64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_u128(v: u128, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_int(v, writer)
}
fn encode_f32(v: f32, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_float(v, writer)
}
fn encode_f64(v: f64, writer: &mut W) -> Result<usize, Error<<W as IoWrite>::Error>> {
Self::encode_float(v, writer)
}
}