use crate::BoundedVec;
use core::fmt;
use serde::{
de::{self, SeqAccess, Visitor},
Deserialize, Deserializer, Serialize,
};
use std::marker::PhantomData;
impl<T: Serialize, const UPP: usize, const LOW: usize> Serialize for BoundedVec<T, LOW, UPP> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.as_vec().serialize(serializer)
}
}
impl<'de, T, const LOW: usize, const UPP: usize> Deserialize<'de> for BoundedVec<T, LOW, UPP>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct BoundedVecVisitor<T> {
marker: PhantomData<T>,
}
impl<'de, T, const LOW: usize, const UPP: usize> Visitor<'de>
for BoundedVecVisitor<(T, [(); LOW], [(); UPP])>
where
T: Deserialize<'de>,
{
type Value = BoundedVec<T, LOW, UPP>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a sequence with length between {LOW} and {UPP}")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de, Error: >,
{
let size_hint = seq.size_hint();
let capacity = size_hint_cautious::<T>(size_hint);
let mut values = Vec::<T>::with_capacity(capacity.min(UPP));
loop {
match seq.next_element() {
Ok(Some(_)) if values.len() == UPP => {
return Err(de::Error::custom(format!(
"a sequence length is larger than {UPP}"
)))
}
Ok(Some(v)) => values.push(v),
Ok(None) => break,
Err(e) => return Err(e),
}
}
values.try_into().map_err(|_| {
de::Error::custom(format!("a sequence length is not between {LOW} and {UPP}"))
})
}
}
let visitor = BoundedVecVisitor {
marker: PhantomData,
};
deserializer.deserialize_seq(visitor)
}
}
pub fn size_hint_cautious<Element>(hint: Option<usize>) -> usize {
const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
if size_of::<Element>() == 0 {
0
} else {
hint.unwrap_or(0)
.min(MAX_PREALLOC_BYTES / size_of::<Element>())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bvec;
use ron::{from_str, to_string};
#[test]
fn serialize() {
let vec: BoundedVec<i32, 0, 10> = bvec![1, 2, 3];
assert_eq!(to_string(&vec), Ok("[1,2,3]".to_owned()));
let vec: BoundedVec<i32, 0, 10> = bvec![];
assert_eq!(to_string(&vec), Ok("[]".to_owned()));
}
#[test]
fn deserialize() {
let vec: Result<BoundedVec<i32, 0, 3>, _> = from_str("[1,2,3]");
assert_eq!(vec, Ok(bvec![1, 2, 3]));
}
#[test]
fn deserialize_too_high() {
let vec: Result<BoundedVec<i32, 0, 3>, _> = from_str("[1,2,3,4]");
assert!(vec.is_err())
}
#[test]
fn deserialize_too_low() {
let vec: Result<BoundedVec<i32, 1, 3>, _> = from_str("[]");
assert!(vec.is_err())
}
}