mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
add string_or_u64 serialization (#2698)
This commit is contained in:
parent
bd6824ca4c
commit
6949a0d341
2 changed files with 106 additions and 0 deletions
|
@ -159,9 +159,11 @@ pub struct TxKernel {
|
|||
/// Options for a kernel's structure or use
|
||||
pub features: KernelFeatures,
|
||||
/// Fee originally included in the transaction this proof is for.
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub fee: u64,
|
||||
/// This kernel is not valid earlier than lock_height blocks
|
||||
/// The max lock_height of all *inputs* to this transaction
|
||||
#[serde(with = "secp_ser::string_or_u64")]
|
||||
pub lock_height: u64,
|
||||
/// Remainder of the sum of all transaction commitments. If the transaction
|
||||
/// is well formed, amounts components should sum to zero and the excess
|
||||
|
|
|
@ -164,6 +164,104 @@ where
|
|||
serializer.serialize_str(&to_hex(bytes.as_ref().to_vec()))
|
||||
}
|
||||
|
||||
/// Used to ensure u64s are serialised in json
|
||||
/// as strings by default, since it can't be guaranteed that consumers
|
||||
/// will know what to do with u64 literals (e.g. Javascript). However,
|
||||
/// fields using this tag can be deserialized from literals or strings.
|
||||
/// From solutions on:
|
||||
/// https://github.com/serde-rs/json/issues/329
|
||||
pub mod string_or_u64 {
|
||||
use std::fmt;
|
||||
|
||||
use serde::{de, Deserializer, Serializer};
|
||||
|
||||
/// serialize into a string
|
||||
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
T: fmt::Display,
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.collect_str(value)
|
||||
}
|
||||
|
||||
/// deserialize from either literal or string
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<u64, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct Visitor;
|
||||
impl<'a> de::Visitor<'a> for Visitor {
|
||||
type Value = u64;
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
formatter,
|
||||
"a string containing digits or an int fitting into u64"
|
||||
)
|
||||
}
|
||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
|
||||
Ok(v)
|
||||
}
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
s.parse().map_err(de::Error::custom)
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_any(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
/// As above, for Options
|
||||
pub mod opt_string_or_u64 {
|
||||
use std::fmt;
|
||||
|
||||
use serde::{de, Deserializer, Serializer};
|
||||
|
||||
/// serialize into string or none
|
||||
pub fn serialize<T, S>(value: &Option<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
T: fmt::Display,
|
||||
S: Serializer,
|
||||
{
|
||||
match value {
|
||||
Some(v) => serializer.collect_str(v),
|
||||
None => serializer.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
/// deser from 'null', literal or string
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct Visitor;
|
||||
impl<'a> de::Visitor<'a> for Visitor {
|
||||
type Value = Option<u64>;
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
formatter,
|
||||
"null, a string containing digits or an int fitting into u64"
|
||||
)
|
||||
}
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E> {
|
||||
Ok(None)
|
||||
}
|
||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E> {
|
||||
Ok(Some(v))
|
||||
}
|
||||
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
let val: u64 = s.parse().map_err(de::Error::custom)?;
|
||||
Ok(Some(val))
|
||||
}
|
||||
}
|
||||
deserializer.deserialize_any(Visitor)
|
||||
}
|
||||
}
|
||||
|
||||
// Test serialization methods of components that are being used
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
@ -185,6 +283,10 @@ mod test {
|
|||
pub opt_sig: Option<Signature>,
|
||||
#[serde(with = "sig_serde")]
|
||||
pub sig: Signature,
|
||||
#[serde(with = "string_or_u64")]
|
||||
pub num: u64,
|
||||
#[serde(with = "opt_string_or_u64")]
|
||||
pub opt_num: Option<u64>,
|
||||
}
|
||||
|
||||
impl SerTest {
|
||||
|
@ -200,6 +302,8 @@ mod test {
|
|||
pub_key: PublicKey::from_secret_key(&secp, &sk).unwrap(),
|
||||
opt_sig: Some(sig.clone()),
|
||||
sig: sig.clone(),
|
||||
num: 30,
|
||||
opt_num: Some(33),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue