From 3a9ac87dc1447a75bda3063955d79eea27bf47f6 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 27 Feb 2023 22:35:56 -0800 Subject: [PATCH] change serde format for BigUint to use a hex string instead of an array of u32 chunks --- register_allocator/src/loc_set.rs | 81 +++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 9 deletions(-) diff --git a/register_allocator/src/loc_set.rs b/register_allocator/src/loc_set.rs index 7f987f6..71dd620 100644 --- a/register_allocator/src/loc_set.rs +++ b/register_allocator/src/loc_set.rs @@ -5,11 +5,11 @@ use crate::{ }; use enum_map::{enum_map, EnumMap}; use num_bigint::BigUint; -use num_traits::Zero; +use num_traits::{Num, Zero}; use once_cell::race::OnceBox; -use serde::{Deserialize, Serialize}; +use serde::{de, Deserialize, Serialize}; use std::{ - borrow::Borrow, + borrow::{Borrow, Cow}, cell::Cell, collections::{ btree_map::{self, Entry}, @@ -32,25 +32,88 @@ fn zero_biguint<'a>() -> &'a BigUint { ) } -#[derive(Deserialize)] -struct LocSetSerialized { - starts_map: BTreeMap>, +#[derive(Debug, Clone)] +struct BigUintAsHexString<'a>(Cow<'a, BigUint>); + +impl<'de, 'a> Deserialize<'de> for BigUintAsHexString<'a> { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let text = String::deserialize(deserializer)?; + if let Some(text) = text.strip_prefix("0x") { + Ok(Self(Cow::Owned( + BigUint::from_str_radix(text, 0x10).map_err(::custom)?, + ))) + } else { + Err(::custom( + "expected hex string to start with `0x`", + )) + } + } +} + +impl Serialize for BigUintAsHexString<'_> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + format!("{:#x}", &*self.0).serialize(serializer) + } +} + +#[derive(Deserialize, Serialize)] +struct LocSetSerialized<'a> { + starts_map: BTreeMap>>, } -impl TryFrom for LocSet { +impl TryFrom> for LocSet { type Error = Error; fn try_from(value: LocSetSerialized) -> Result { - Self::from_starts_map(value.starts_map) + Self::from_starts_map( + value + .starts_map + .into_iter() + .map(|(k, mut v)| { + let v = enum_map! { + k => v.remove(&k).map_or_else(BigUint::zero, |v| v.0.into_owned()) + }; + (k, v) + }) + .collect(), + ) } } -#[derive(Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Default, PartialEq, Eq, Hash, Deserialize)] #[serde(try_from = "LocSetSerialized")] pub struct LocSet { starts_map: BTreeMap>, } +impl Serialize for LocSet { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + LocSetSerialized { + starts_map: self + .starts_map + .iter() + .map(|(&k, v)| { + let v = v + .iter() + .map(|(k, v)| (k, BigUintAsHexString(Cow::Borrowed(v)))) + .collect::>(); + (k, v) + }) + .collect(), + } + .serialize(serializer) + } +} + impl<'a> arbitrary::Arbitrary<'a> for LocSet { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { u.arbitrary_iter()?.collect() -- 2.30.2