Skip to content

Commit

Permalink
Merge pull request #2258 from CosmWasm/aw/deduplicate-serde-impl
Browse files Browse the repository at this point in the history
Deduplicate serde impls for integers
  • Loading branch information
webmaster128 authored Sep 18, 2024
2 parents 1f181c1 + 562a9a7 commit 0580b99
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 311 deletions.
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 {
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| {
E::custom(format_args!("invalid {} '{v}' - {e}", stringify!($t)))
})
}
}

deserializer.deserialize_str(IntVisitor)
}
}
};
}
use impl_int_serde;

#[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

0 comments on commit 0580b99

Please sign in to comment.