Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deduplicate serde impls for integers #2258

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 2 additions & 38 deletions packages/std/src/math/int128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use core::ops::{
ShrAssign, Sub, SubAssign,
};
use core::str::FromStr;
use serde::{de, ser, Deserialize, Deserializer, Serialize};

use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
Expand All @@ -15,6 +14,7 @@ use crate::{
};

use super::conversion::{forward_try_from, try_from_int_to_int};
use super::impl_int_serde;
use super::num_consts::NumConsts;

/// An implementation of i128 that is using strings for JSON encoding/decoding,
Expand All @@ -33,6 +33,7 @@ use super::num_consts::NumConsts;
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
pub struct Int128(#[schemars(with = "String")] pub(crate) i128);

impl_int_serde!(Int128);
forward_ref_partial_eq!(Int128, Int128);

impl Int128 {
Expand Down Expand Up @@ -537,43 +538,6 @@ impl ShlAssign<u32> for Int128 {
}
forward_ref_op_assign!(impl ShlAssign, shl_assign for Int128, u32);

impl Serialize for Int128 {
/// Serializes as an integer string using base 10
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl<'de> Deserialize<'de> for Int128 {
/// Deserialized from an integer string using base 10
fn deserialize<D>(deserializer: D) -> Result<Int128, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(Int128Visitor)
}
}

struct Int128Visitor;

impl<'de> de::Visitor<'de> for Int128Visitor {
type Value = Int128;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string-encoded integer")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Int128::try_from(v).map_err(|e| E::custom(format_args!("invalid Int128 '{v}' - {e}")))
}
}

impl<A> core::iter::Sum<A> for Int128
where
Self: Add<A, Output = Self>,
Expand Down
40 changes: 2 additions & 38 deletions packages/std/src/math/int256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use core::ops::{
ShrAssign, Sub, SubAssign,
};
use core::str::FromStr;
use serde::{de, ser, Deserialize, Deserializer, Serialize};

use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
Expand All @@ -19,6 +18,7 @@ use crate::{
use bnum::types::{I256, U256};

use super::conversion::{grow_be_int, try_from_int_to_int, try_from_uint_to_int};
use super::impl_int_serde;
use super::num_consts::NumConsts;

/// An implementation of i256 that is using strings for JSON encoding/decoding,
Expand All @@ -44,6 +44,7 @@ use super::num_consts::NumConsts;
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
pub struct Int256(#[schemars(with = "String")] pub(crate) I256);

impl_int_serde!(Int256);
forward_ref_partial_eq!(Int256, Int256);

impl Int256 {
Expand Down Expand Up @@ -612,43 +613,6 @@ impl ShlAssign<u32> for Int256 {
}
forward_ref_op_assign!(impl ShlAssign, shl_assign for Int256, u32);

impl Serialize for Int256 {
/// Serializes as an integer string using base 10
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl<'de> Deserialize<'de> for Int256 {
/// Deserialized from an integer string using base 10
fn deserialize<D>(deserializer: D) -> Result<Int256, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(Int256Visitor)
}
}

struct Int256Visitor;

impl<'de> de::Visitor<'de> for Int256Visitor {
type Value = Int256;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string-encoded integer")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Int256::try_from(v).map_err(|e| E::custom(format_args!("invalid Int256 '{v}' - {e}")))
}
}

impl<A> core::iter::Sum<A> for Int256
where
Self: Add<A, Output = Self>,
Expand Down
40 changes: 2 additions & 38 deletions packages/std/src/math/int512.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use core::ops::{
ShrAssign, Sub, SubAssign,
};
use core::str::FromStr;
use serde::{de, ser, Deserialize, Deserializer, Serialize};

use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
Expand All @@ -18,6 +17,7 @@ use crate::{
use bnum::types::{I512, U512};

use super::conversion::{grow_be_int, try_from_uint_to_int};
use super::impl_int_serde;
use super::num_consts::NumConsts;

/// An implementation of i512 that is using strings for JSON encoding/decoding,
Expand Down Expand Up @@ -47,6 +47,7 @@ use super::num_consts::NumConsts;
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
pub struct Int512(#[schemars(with = "String")] pub(crate) I512);

impl_int_serde!(Int512);
forward_ref_partial_eq!(Int512, Int512);

impl Int512 {
Expand Down Expand Up @@ -611,43 +612,6 @@ impl ShlAssign<u32> for Int512 {
}
forward_ref_op_assign!(impl ShlAssign, shl_assign for Int512, u32);

impl Serialize for Int512 {
/// Serializes as an integer string using base 10
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl<'de> Deserialize<'de> for Int512 {
/// Deserialized from an integer string using base 10
fn deserialize<D>(deserializer: D) -> Result<Int512, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(Int512Visitor)
}
}

struct Int512Visitor;

impl<'de> de::Visitor<'de> for Int512Visitor {
type Value = Int512;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string-encoded integer")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Int512::try_from(v).map_err(|e| E::custom(format!("invalid Int512 '{v}' - {e}")))
}
}

impl<A> core::iter::Sum<A> for Int512
where
Self: Add<A, Output = Self>,
Expand Down
40 changes: 2 additions & 38 deletions packages/std/src/math/int64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use core::ops::{
ShrAssign, Sub, SubAssign,
};
use core::str::FromStr;
use serde::{de, ser, Deserialize, Deserializer, Serialize};

use crate::errors::{DivideByZeroError, DivisionError, OverflowError, OverflowOperation, StdError};
use crate::forward_ref::{forward_ref_binop, forward_ref_op_assign};
Expand All @@ -15,6 +14,7 @@ use crate::{
};

use super::conversion::{forward_try_from, try_from_int_to_int};
use super::impl_int_serde;
use super::num_consts::NumConsts;

/// An implementation of i64 that is using strings for JSON encoding/decoding,
Expand All @@ -33,6 +33,7 @@ use super::num_consts::NumConsts;
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
pub struct Int64(#[schemars(with = "String")] pub(crate) i64);

impl_int_serde!(Int64);
forward_ref_partial_eq!(Int64, Int64);

impl Int64 {
Expand Down Expand Up @@ -516,43 +517,6 @@ impl ShlAssign<u32> for Int64 {
}
forward_ref_op_assign!(impl ShlAssign, shl_assign for Int64, u32);

impl Serialize for Int64 {
/// Serializes as an integer string using base 10
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl<'de> Deserialize<'de> for Int64 {
/// Deserialized from an integer string using base 10
fn deserialize<D>(deserializer: D) -> Result<Int64, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(Int64Visitor)
}
}

struct Int64Visitor;

impl<'de> de::Visitor<'de> for Int64Visitor {
type Value = Int64;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string-encoded integer")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Int64::try_from(v).map_err(|e| E::custom(format_args!("invalid Int64 '{v}' - {e}")))
}
}

impl<A> core::iter::Sum<A> for Int64
where
Self: Add<A, Output = Self>,
Expand Down
47 changes: 47 additions & 0 deletions packages/std/src/math/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,53 @@ pub use uint256::Uint256;
pub use uint512::Uint512;
pub use uint64::Uint64;

macro_rules! impl_int_serde {
($ty:ty) => {
impl ::serde::Serialize for $ty {
/// Serializes as an integer string using base 10
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ::serde::ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl<'de> ::serde::Deserialize<'de> for $ty {
/// Deserialized from an integer string using base 10
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: ::serde::de::Deserializer<'de>,
{
struct IntVisitor;

impl<'de> ::serde::de::Visitor<'de> for IntVisitor {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Was already wondering if we can make this even more private. Great stuff

type Value = $ty;

fn expecting(
&self,
formatter: &mut ::core::fmt::Formatter,
) -> ::core::fmt::Result {
formatter.write_str("string-encoded integer")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: ::serde::de::Error,
{
<_>::try_from(v).map_err(|e| {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧙

E::custom(format_args!("invalid {} '{v}' - {e}", stringify!($t)))
})
}
}

deserializer.deserialize_str(IntVisitor)
}
}
};
}
use impl_int_serde;
webmaster128 marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(test)]
mod tests {
use super::*;
Expand Down
44 changes: 2 additions & 42 deletions packages/std/src/math/uint128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ use core::ops::{
};
use core::str::FromStr;

use serde::{de, ser, Deserialize, Deserializer, Serialize};

use crate::errors::{
CheckedMultiplyFractionError, CheckedMultiplyRatioError, DivideByZeroError, OverflowError,
OverflowOperation, StdError,
Expand All @@ -19,6 +17,7 @@ use crate::{
};

use super::conversion::forward_try_from;
use super::impl_int_serde;
use super::num_consts::NumConsts;

/// A thin wrapper around u128 that is using strings for JSON encoding/decoding,
Expand All @@ -43,6 +42,7 @@ use super::num_consts::NumConsts;
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, schemars::JsonSchema)]
pub struct Uint128(#[schemars(with = "String")] pub(crate) u128);

impl_int_serde!(Uint128);
forward_ref_partial_eq!(Uint128, Uint128);

impl Uint128 {
Expand Down Expand Up @@ -583,46 +583,6 @@ impl<'a> ShlAssign<&'a u32> for Uint128 {
}
}

impl Serialize for Uint128 {
/// Serializes as an integer string using base 10
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}

impl<'de> Deserialize<'de> for Uint128 {
/// Deserialized from an integer string using base 10
fn deserialize<D>(deserializer: D) -> Result<Uint128, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(Uint128Visitor)
}
}

struct Uint128Visitor;

impl<'de> de::Visitor<'de> for Uint128Visitor {
type Value = Uint128;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string-encoded integer")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
match v.parse::<u128>() {
Ok(u) => Ok(Uint128(u)),
Err(e) => Err(E::custom(format_args!("invalid Uint128 '{v}' - {e}"))),
}
}
}

impl<A> core::iter::Sum<A> for Uint128
where
Self: Add<A, Output = Self>,
Expand Down
Loading
Loading