Implement Serialize/Deserialize on WeakBoundedVec (#11713)

* Implement Serialize/Deserialize on WeakBoundedVec

* cargo fmt

* Warn when there are too many elements while deserializing WeakBoundedVec
This commit is contained in:
Keith Yeung
2022-06-21 08:49:43 +02:00
committed by GitHub
parent 9cee3c699d
commit 939c31bfde
@@ -25,6 +25,11 @@ use core::{
ops::{Deref, Index, IndexMut},
slice::SliceIndex,
};
#[cfg(feature = "std")]
use serde::{
de::{Error, SeqAccess, Visitor},
Deserialize, Deserializer, Serialize,
};
use sp_std::{marker::PhantomData, prelude::*};
/// A weakly bounded vector.
@@ -34,9 +39,72 @@ use sp_std::{marker::PhantomData, prelude::*};
///
/// The length of the vec is not strictly bounded. Decoding a vec with more element that the bound
/// is accepted, and some method allow to bypass the restriction with warnings.
#[cfg_attr(feature = "std", derive(Serialize), serde(transparent))]
#[derive(Encode, scale_info::TypeInfo)]
#[scale_info(skip_type_params(S))]
pub struct WeakBoundedVec<T, S>(pub(super) Vec<T>, PhantomData<S>);
pub struct WeakBoundedVec<T, S>(
pub(super) Vec<T>,
#[cfg_attr(feature = "std", serde(skip_serializing))] PhantomData<S>,
);
#[cfg(feature = "std")]
impl<'de, T, S: Get<u32>> Deserialize<'de> for WeakBoundedVec<T, S>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VecVisitor<T, S: Get<u32>>(PhantomData<(T, S)>);
impl<'de, T, S: Get<u32>> Visitor<'de> for VecVisitor<T, S>
where
T: Deserialize<'de>,
{
type Value = Vec<T>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a sequence")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let size = seq.size_hint().unwrap_or(0);
let max = match usize::try_from(S::get()) {
Ok(n) => n,
Err(_) => return Err(A::Error::custom("can't convert to usize")),
};
if size > max {
log::warn!(
target: "runtime",
"length of a bounded vector while deserializing is not respected.",
);
}
let mut values = Vec::with_capacity(size);
while let Some(value) = seq.next_element()? {
values.push(value);
if values.len() > max {
log::warn!(
target: "runtime",
"length of a bounded vector while deserializing is not respected.",
);
}
}
Ok(values)
}
}
let visitor: VecVisitor<T, S> = VecVisitor(PhantomData);
deserializer.deserialize_seq(visitor).map(|v| {
WeakBoundedVec::<T, S>::try_from(v).map_err(|_| Error::custom("out of bounds"))
})?
}
}
impl<T: Decode, S: Get<u32>> Decode for WeakBoundedVec<T, S> {
fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {