use std::{cell::RefCell, marker, marker::PhantomData};
use gazebo::prelude::*;
use crate::{
collections::{
vec_map::{Bucket, VecMap},
SmallMap,
},
values::{Freezer, FrozenStringValue, FrozenValue, StringValue, Value},
};
pub trait Freeze {
type Frozen;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<Self::Frozen>;
}
impl Freeze for String {
type Frozen = String;
fn freeze(self, _freezer: &Freezer) -> anyhow::Result<String> {
Ok(self)
}
}
impl Freeze for i32 {
type Frozen = i32;
fn freeze(self, _freezer: &Freezer) -> anyhow::Result<i32> {
Ok(self)
}
}
impl Freeze for usize {
type Frozen = usize;
fn freeze(self, _freezer: &Freezer) -> anyhow::Result<usize> {
Ok(self)
}
}
impl Freeze for bool {
type Frozen = bool;
fn freeze(self, _freezer: &Freezer) -> anyhow::Result<bool> {
Ok(self)
}
}
impl<'v, T: 'static> Freeze for marker::PhantomData<&'v T> {
type Frozen = PhantomData<&'static T>;
fn freeze(self, _freezer: &Freezer) -> anyhow::Result<PhantomData<&'static T>> {
Ok(marker::PhantomData)
}
}
impl<T> Freeze for Vec<T>
where
T: Freeze,
{
type Frozen = Vec<T::Frozen>;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<Vec<T::Frozen>> {
self.into_try_map(|v| v.freeze(freezer))
}
}
impl<T> Freeze for RefCell<T>
where
T: Freeze,
{
type Frozen = T::Frozen;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<T::Frozen> {
self.into_inner().freeze(freezer)
}
}
impl<T> Freeze for Option<T>
where
T: Freeze,
{
type Frozen = Option<T::Frozen>;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<Option<T::Frozen>> {
self.into_try_map(|v| v.freeze(freezer))
}
}
impl<K, V> Freeze for VecMap<K, V>
where
K: Freeze,
V: Freeze,
{
type Frozen = VecMap<K::Frozen, V::Frozen>;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<Self::Frozen> {
let buckets = self.buckets.into_try_map(|Bucket { hash, key, value }| {
let key = key.freeze(freezer)?;
let value = value.freeze(freezer)?;
anyhow::Ok(Bucket { hash, key, value })
})?;
Ok(VecMap { buckets })
}
}
impl<K, V> Freeze for SmallMap<K, V>
where
K: Freeze,
V: Freeze,
{
type Frozen = SmallMap<K::Frozen, V::Frozen>;
fn freeze(mut self, freezer: &Freezer) -> anyhow::Result<SmallMap<K::Frozen, V::Frozen>> {
self.maybe_drop_index();
let (entries, index) = self.into_raw_parts();
let entries = entries.freeze(freezer)?;
unsafe { Ok(SmallMap::from_raw_parts(entries, index)) }
}
}
impl<'v> Freeze for Value<'v> {
type Frozen = FrozenValue;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<FrozenValue> {
freezer.freeze(self)
}
}
impl Freeze for FrozenValue {
type Frozen = FrozenValue;
fn freeze(self, _freezer: &Freezer) -> anyhow::Result<FrozenValue> {
Ok(self)
}
}
impl<'v> Freeze for StringValue<'v> {
type Frozen = FrozenStringValue;
fn freeze(self, freezer: &Freezer) -> anyhow::Result<FrozenStringValue> {
self.freeze(freezer)
}
}