#![cfg_attr(docsrs, doc(cfg(feature = "borsh")))] use alloc::vec::Vec; use core::hash::BuildHasher; use core::hash::Hash; use core::mem::size_of; use borsh::error::ERROR_ZST_FORBIDDEN; use borsh::io::{Error, ErrorKind, Read, Result, Write}; use borsh::{BorshDeserialize, BorshSerialize}; use crate::map::IndexMap; use crate::set::IndexSet; impl BorshSerialize for IndexMap where K: BorshSerialize, V: BorshSerialize, { #[inline] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; let iterator = self.iter(); u32::try_from(iterator.len()) .map_err(|_| ErrorKind::InvalidData)? .serialize(writer)?; for (key, value) in iterator { key.serialize(writer)?; value.serialize(writer)?; } Ok(()) } } impl BorshDeserialize for IndexMap where K: BorshDeserialize + Eq + Hash, V: BorshDeserialize, S: BuildHasher + Default, { #[inline] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; let vec = >::deserialize_reader(reader)?; Ok(vec.into_iter().collect::>()) } } impl BorshSerialize for IndexSet where T: BorshSerialize, { #[inline] fn serialize(&self, writer: &mut W) -> Result<()> { check_zst::()?; let iterator = self.iter(); u32::try_from(iterator.len()) .map_err(|_| ErrorKind::InvalidData)? .serialize(writer)?; for item in iterator { item.serialize(writer)?; } Ok(()) } } impl BorshDeserialize for IndexSet where T: BorshDeserialize + Eq + Hash, S: BuildHasher + Default, { #[inline] fn deserialize_reader(reader: &mut R) -> Result { check_zst::()?; let vec = >::deserialize_reader(reader)?; Ok(vec.into_iter().collect::>()) } } fn check_zst() -> Result<()> { if size_of::() == 0 { return Err(Error::new(ErrorKind::InvalidData, ERROR_ZST_FORBIDDEN)); } Ok(()) } #[cfg(test)] mod borsh_tests { use super::*; #[test] fn map_borsh_roundtrip() { let original_map: IndexMap = { let mut map = IndexMap::new(); map.insert(1, 2); map.insert(3, 4); map.insert(5, 6); map }; let serialized_map = borsh::to_vec(&original_map).unwrap(); let deserialized_map: IndexMap = BorshDeserialize::try_from_slice(&serialized_map).unwrap(); assert_eq!(original_map, deserialized_map); } #[test] fn set_borsh_roundtrip() { let original_map: IndexSet = [1, 2, 3, 4, 5, 6].into_iter().collect(); let serialized_map = borsh::to_vec(&original_map).unwrap(); let deserialized_map: IndexSet = BorshDeserialize::try_from_slice(&serialized_map).unwrap(); assert_eq!(original_map, deserialized_map); } }