use super::arena::{Arena, ArenaEntry, ArenaIndex, DEFAULT_CAPACITY};
use crate::BoxedComponent;
use crate::ComponentDerive;
use core::cmp;
use core::fmt;
use core::iter;
use core::marker::PhantomData;
use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
use serde::ser::Serializer;
use serde::Serialize;
impl Serialize for ArenaIndex {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
(self.index, self.generation).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ArenaIndex {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let (index, generation) = Deserialize::deserialize(deserializer)?;
Ok(ArenaIndex { index, generation })
}
}
impl<T> Serialize for Arena<T>
where
T: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(self.items.iter().map(|entry| match entry {
ArenaEntry::Occupied { generation, data } => Some((generation, data)),
_ => None,
}))
}
}
impl Arena<BoxedComponent> {
pub fn serialize_components<C: ComponentDerive + Serialize>(
&self,
) -> Vec<Option<(u32, Vec<u8>)>> {
let e = self
.items
.iter()
.map(|entry| match entry {
ArenaEntry::Occupied { generation, data } => Some((
*generation,
bincode::serialize(data.downcast_ref::<C>().unwrap()).unwrap(),
)),
ArenaEntry::Free { .. } => None,
})
.collect();
return e;
}
}
impl<'de, T> Deserialize<'de> for Arena<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(ArenaVisitor::new())
}
}
struct ArenaVisitor<T> {
marker: PhantomData<fn() -> Arena<T>>,
}
impl<T> ArenaVisitor<T> {
fn new() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<T> Arena<T> {
pub fn from_items(mut items: Vec<ArenaEntry<T>>, generation: u32) -> Arena<T> {
if items.len() + 1 < items.capacity() {
let add_cap = items.capacity() - (items.len() + 1);
items.reserve_exact(add_cap);
items.extend(iter::repeat_with(|| ArenaEntry::Free { next_free: None }).take(add_cap));
assert_eq!(items.len(), items.capacity());
}
let mut free_list_head = None;
let mut len = items.len();
for (idx, entry) in items.iter_mut().enumerate().rev() {
if let ArenaEntry::Free { next_free } = entry {
*next_free = free_list_head;
free_list_head = Some(idx);
len -= 1;
}
}
Arena {
items,
generation,
free_list_head,
len,
}
}
}
impl<'de, T> Visitor<'de> for ArenaVisitor<T>
where
T: Deserialize<'de>,
{
type Value = Arena<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a generational arena")
}
fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: SeqAccess<'de>,
{
let init_cap = access.size_hint().unwrap_or(DEFAULT_CAPACITY);
let mut items = Vec::with_capacity(init_cap);
let mut generation = 0;
while let Some(element) = access.next_element::<Option<(u32, T)>>()? {
let item = match element {
Some((gen, data)) => {
generation = cmp::max(generation, gen);
ArenaEntry::Occupied {
generation: gen,
data,
}
}
None => ArenaEntry::Free { next_free: None },
};
items.push(item);
}
return Ok(Arena::from_items(items, generation));
}
}