memorypack 1.2.1

A rust implementation of Cysharp/MemoryPack
Documentation
use crate::error::MemoryPackError;
use std::any::Any;
use std::collections::HashMap;

pub struct MemoryPackWriterOptionalState {
    next_id: u32,
    object_to_ref: HashMap<usize, u32>,
}

impl MemoryPackWriterOptionalState {
    pub fn new() -> Self {
        Self {
            next_id: 0,
            object_to_ref: HashMap::new(),
        }
    }

    pub fn reset(&mut self) {
        self.object_to_ref.clear();
        self.next_id = 0;
    }

    pub fn get_or_add_reference<T: ?Sized>(&mut self, value: &T) -> (bool, u32) {
        let ptr = value as *const T as *const () as usize;

        if let Some(&id) = self.object_to_ref.get(&ptr) {
            (true, id)
        } else {
            let id = self.next_id;
            self.next_id += 1;
            self.object_to_ref.insert(ptr, id);
            (false, id)
        }
    }
}

impl Default for MemoryPackWriterOptionalState {
    fn default() -> Self {
        Self::new()
    }
}

pub struct MemoryPackReaderOptionalState {
    ref_to_object: HashMap<u32, Box<dyn Any>>,
}

impl MemoryPackReaderOptionalState {
    pub fn new() -> Self {
        Self {
            ref_to_object: HashMap::new(),
        }
    }

    pub fn reset(&mut self) {
        self.ref_to_object.clear();
    }

    pub fn get_object_reference<T: 'static + Clone>(&self, id: u32) -> Result<T, MemoryPackError> {
        self.ref_to_object
            .get(&id)
            .and_then(|boxed: &Box<dyn Any>| boxed.downcast_ref::<T>())
            .cloned()
            .ok_or_else(|| {
                MemoryPackError::DeserializationError(format!(
                    "Object is not found in this reference id: {}",
                    id
                ))
            })
    }

    pub fn add_object_reference<T: 'static>(
        &mut self,
        id: u32,
        value: T,
    ) -> Result<(), MemoryPackError> {
        if self.ref_to_object.contains_key(&id) {
            return Err(MemoryPackError::DeserializationError(format!(
                "Object is already added, id: {}",
                id
            )));
        }
        self.ref_to_object.insert(id, Box::new(value));
        Ok(())
    }

    pub fn update_object_reference<T: 'static>(
        &mut self,
        id: u32,
        value: T,
    ) -> Result<(), MemoryPackError> {
        if let Some(entry) = self.ref_to_object.get_mut(&id) {
            *entry = Box::new(value);
            Ok(())
        } else {
            Err(MemoryPackError::DeserializationError(format!(
                "Object not found for update, id: {}",
                id
            )))
        }
    }
}

impl Default for MemoryPackReaderOptionalState {
    fn default() -> Self {
        Self::new()
    }
}