Skip to content
Snippets Groups Projects
Unverified Commit bacd7b80 authored by Shaopeng Wang's avatar Shaopeng Wang Committed by GitHub
Browse files

Update fixedu128 serde impl. (#87)

parent 2f70d290
No related branches found
No related tags found
No related merge requests found
......@@ -212,30 +212,12 @@ impl_perthing_into_fixed_u128!(Perquintill);
#[cfg(feature = "std")]
impl FixedU128 {
fn str_with_precision(&self) -> String {
format!("{}.{}", &self.0 / DIV, &self.0 % DIV)
}
fn from_str_with_precision(s: &str) -> Result<Self, &'static str> {
let err = "invalid string input";
let vec_str: Vec<&str> = s.split(".").collect();
// parsing to decimal and fractional parts
let (decimal_str, fractional_str) = match vec_str.as_slice() {
&[d] => (d, "0"),
&[d, f] => (d, f),
_ => return Err(err),
};
let decimal: u128 = decimal_str.parse().map_err(|_| err)?;
let decimal_with_precision = decimal.checked_mul(DIV).ok_or(err)?;
// width = 18; precision = 18
let padded_fractional_string = format!("{:0<18.18}", fractional_str);
let fractional_with_precision: u128 = padded_fractional_string.parse().map_err(|_| err)?;
let parts = decimal_with_precision
.checked_add(fractional_with_precision)
.ok_or(err)?;
fn u128_str(&self) -> String {
format!("{}", &self.0)
}
fn try_from_u128_str(s: &str) -> Result<Self, &'static str> {
let parts: u128 = s.parse().map_err(|_| "invalid string input")?;
Ok(Self::from_parts(parts))
}
}
......@@ -248,7 +230,7 @@ impl Serialize for FixedU128 {
where
S: Serializer,
{
serializer.serialize_str(&self.str_with_precision())
serializer.serialize_str(&self.u128_str())
}
}
......@@ -261,7 +243,7 @@ impl<'de> Deserialize<'de> for FixedU128 {
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
FixedU128::from_str_with_precision(&s).map_err(|err_str| de::Error::custom(err_str))
FixedU128::try_from_u128_str(&s).map_err(|err_str| de::Error::custom(err_str))
}
}
......@@ -416,43 +398,11 @@ mod tests {
assert_eq!(a.recip(), None);
}
#[test]
fn from_str_with_precision_should_work() {
assert_eq!(
FixedU128::from_str_with_precision("1").unwrap(),
FixedU128::from_natural(1)
);
assert_eq!(
FixedU128::from_str_with_precision("1.0").unwrap(),
FixedU128::from_natural(1)
);
assert_eq!(
FixedU128::from_str_with_precision("0.1").unwrap(),
FixedU128::from_rational(1, 10)
);
assert_eq!(
FixedU128::from_str_with_precision("2.5").unwrap(),
FixedU128::from_rational(5, 2)
);
assert_eq!(
FixedU128::from_str_with_precision("0.1000000000000000111").unwrap(),
FixedU128::from_rational(100000000000000011u128, 1000000000000000000u128)
);
assert!(FixedU128::from_str_with_precision(".").is_err());
assert!(FixedU128::from_str_with_precision("").is_err());
assert!(FixedU128::from_str_with_precision("1.1.1").is_err());
assert!(FixedU128::from_str_with_precision("a.1").is_err());
assert!(FixedU128::from_str_with_precision("1.a").is_err());
// 340282366920938463464 == u128::max_value() / DIV + 1; overflows
assert!(FixedU128::from_str_with_precision("340282366920938463464").is_err());
}
#[test]
fn serialize_deserialize_should_work() {
let two_point_five = FixedU128::from_rational(5, 2);
let serialized = serde_json::to_string(&two_point_five).unwrap();
assert_eq!(serialized, "\"2.500000000000000000\"");
assert_eq!(serialized, "\"2500000000000000000\"");
let deserialized: FixedU128 = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized, two_point_five);
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment