use std::hash::BuildHasher;
use std::hash::Hash;
use std::marker::PhantomData;
use std::num::NonZeroI32;
use std::sync::Arc;
use std::sync::Weak;
use dupe::Dupe;
use indexmap::IndexMap;
use pagable::PagableDeserialize;
use pagable::PagableDeserializer;
use pagable::PagableSerialize;
use pagable::PagableSerializer;
use pagable::arc_erase::ArcErase;
use pagable::arc_erase::ArcEraseDyn;
use pagable::arc_erase::ArcEraseType;
use pagable::arc_erase::StdArcEraseType;
use pagable::arc_erase::WeakErase;
use pagable::arc_erase::deserialize_arc;
use starlark_map::Hashed;
use starlark_map::small_map::SmallMap;
use starlark_map::small_set::SmallSet;
use starlark_syntax::syntax::ast::AssignOp;
use crate::pagable::starlark_deserialize::StarlarkDeserialize;
use crate::pagable::starlark_deserialize::StarlarkDeserializeContext;
use crate::pagable::starlark_deserialize_context::StarlarkDeserializerImpl;
use crate::pagable::starlark_serialize::StarlarkSerialize;
use crate::pagable::starlark_serialize::StarlarkSerializeContext;
use crate::pagable::starlark_serialize_context::StarlarkSerializerImpl;
use crate::values::FrozenStringValue;
use crate::values::FrozenValue;
use crate::values::ThinBoxSliceFrozenValue;
use crate::values::ValueLike;
macro_rules! impl_starlark_via_pagable {
($($ty:ty),* $(,)?) => {
$(
impl StarlarkSerialize for $ty {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
PagableSerialize::pagable_serialize(self, ctx.pagable())?;
Ok(())
}
}
impl StarlarkDeserialize for $ty {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
Ok(<$ty as PagableDeserialize>::pagable_deserialize(ctx.pagable())?)
}
}
)*
};
}
impl_starlark_via_pagable!(
bool, u8, u16, u32, u64, usize, i8, i16, i32, i64, f32, f64, String,
);
impl<T: StarlarkSerialize> StarlarkSerialize for Vec<T> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.len().pagable_serialize(ctx.pagable())?;
for elem in self {
elem.starlark_serialize(ctx)?;
}
Ok(())
}
}
impl<T: StarlarkDeserialize> StarlarkDeserialize for Vec<T> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let len = usize::pagable_deserialize(ctx.pagable())?;
let mut v = Vec::with_capacity(len);
for _ in 0..len {
v.push(T::starlark_deserialize(ctx)?);
}
Ok(v)
}
}
impl<T: StarlarkSerialize + ?Sized> StarlarkSerialize for &T {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
(**self).starlark_serialize(ctx)
}
}
impl<T: StarlarkSerialize> StarlarkSerialize for Box<T> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
(**self).starlark_serialize(ctx)
}
}
impl<T: StarlarkDeserialize> StarlarkDeserialize for Box<T> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
Ok(Box::new(T::starlark_deserialize(ctx)?))
}
}
impl<T: StarlarkSerialize> StarlarkSerialize for Option<T> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
match self {
Some(v) => {
true.pagable_serialize(ctx.pagable())?;
v.starlark_serialize(ctx)?;
}
None => {
false.pagable_serialize(ctx.pagable())?;
}
}
Ok(())
}
}
impl<T: StarlarkDeserialize> StarlarkDeserialize for Option<T> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let is_some = bool::pagable_deserialize(ctx.pagable())?;
if is_some {
Ok(Some(T::starlark_deserialize(ctx)?))
} else {
Ok(None)
}
}
}
impl<A: StarlarkSerialize, B: StarlarkSerialize> StarlarkSerialize for (A, B) {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.0.starlark_serialize(ctx)?;
self.1.starlark_serialize(ctx)?;
Ok(())
}
}
impl<A: StarlarkDeserialize, B: StarlarkDeserialize> StarlarkDeserialize for (A, B) {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let a = A::starlark_deserialize(ctx)?;
let b = B::starlark_deserialize(ctx)?;
Ok((a, b))
}
}
impl<A: StarlarkSerialize, B: StarlarkSerialize, C: StarlarkSerialize> StarlarkSerialize
for (A, B, C)
{
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.0.starlark_serialize(ctx)?;
self.1.starlark_serialize(ctx)?;
self.2.starlark_serialize(ctx)?;
Ok(())
}
}
impl<A: StarlarkDeserialize, B: StarlarkDeserialize, C: StarlarkDeserialize> StarlarkDeserialize
for (A, B, C)
{
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let a = A::starlark_deserialize(ctx)?;
let b = B::starlark_deserialize(ctx)?;
let c = C::starlark_deserialize(ctx)?;
Ok((a, b, c))
}
}
impl<A: StarlarkSerialize, B: StarlarkSerialize, C: StarlarkSerialize, D: StarlarkSerialize>
StarlarkSerialize for (A, B, C, D)
{
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.0.starlark_serialize(ctx)?;
self.1.starlark_serialize(ctx)?;
self.2.starlark_serialize(ctx)?;
self.3.starlark_serialize(ctx)?;
Ok(())
}
}
impl<A: StarlarkDeserialize, B: StarlarkDeserialize, C: StarlarkDeserialize, D: StarlarkDeserialize>
StarlarkDeserialize for (A, B, C, D)
{
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let a = A::starlark_deserialize(ctx)?;
let b = B::starlark_deserialize(ctx)?;
let c = C::starlark_deserialize(ctx)?;
let d = D::starlark_deserialize(ctx)?;
Ok((a, b, c, d))
}
}
impl<K: StarlarkSerialize, V: StarlarkSerialize> StarlarkSerialize for SmallMap<K, V> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.len().pagable_serialize(ctx.pagable())?;
for (k, v) in self.iter() {
k.starlark_serialize(ctx)?;
v.starlark_serialize(ctx)?;
}
Ok(())
}
}
impl<K: SmallMapKeyDeserialize, V: StarlarkDeserialize> StarlarkDeserialize for SmallMap<K, V> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let len = usize::pagable_deserialize(ctx.pagable())?;
let mut map = SmallMap::with_capacity(len);
for _ in 0..len {
let hashed_k = K::starlark_deserialize_hashed(ctx)?;
let v = V::starlark_deserialize(ctx)?;
map.insert_hashed(hashed_k, v);
}
Ok(map)
}
}
impl<T: StarlarkSerialize> StarlarkSerialize for SmallSet<T> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.len().pagable_serialize(ctx.pagable())?;
for v in self.iter() {
v.starlark_serialize(ctx)?;
}
Ok(())
}
}
impl<T: SmallMapKeyDeserialize> StarlarkDeserialize for SmallSet<T> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let len = usize::pagable_deserialize(ctx.pagable())?;
let mut set = SmallSet::with_capacity(len);
for _ in 0..len {
let hashed = T::starlark_deserialize_hashed(ctx)?;
set.insert_hashed(hashed);
}
Ok(set)
}
}
pub trait SmallMapKeyDeserialize: StarlarkDeserialize + Eq + Sized {
fn starlark_deserialize_hashed(
ctx: &mut dyn StarlarkDeserializeContext<'_>,
) -> crate::Result<Hashed<Self>>;
}
macro_rules! impl_small_map_key_hash {
($($ty:ty),* $(,)?) => {
$(
impl SmallMapKeyDeserialize for $ty {
fn starlark_deserialize_hashed(
ctx: &mut dyn StarlarkDeserializeContext<'_>,
) -> crate::Result<Hashed<Self>> {
let k = Self::starlark_deserialize(ctx)?;
Ok(Hashed::new(k))
}
}
)*
};
}
impl_small_map_key_hash!(String, bool, u8, u16, u32, u64, usize, i8, i16, i32, i64);
impl<T> SmallMapKeyDeserialize for Arc<T>
where
Arc<T>: StarlarkDeserialize + Hash + Eq,
{
fn starlark_deserialize_hashed(
ctx: &mut dyn StarlarkDeserializeContext<'_>,
) -> crate::Result<Hashed<Self>> {
let k = Self::starlark_deserialize(ctx)?;
Ok(Hashed::new(k))
}
}
impl SmallMapKeyDeserialize for FrozenValue {
fn starlark_deserialize_hashed(
ctx: &mut dyn StarlarkDeserializeContext<'_>,
) -> crate::Result<Hashed<Self>> {
let fv = FrozenValue::starlark_deserialize(ctx)?;
fv.get_hashed()
}
}
impl SmallMapKeyDeserialize for FrozenStringValue {
fn starlark_deserialize_hashed(
ctx: &mut dyn StarlarkDeserializeContext<'_>,
) -> crate::Result<Hashed<Self>> {
let fsv = FrozenStringValue::starlark_deserialize(ctx)?;
Ok(fsv.get_hashed())
}
}
impl<T: StarlarkSerialize> StarlarkSerialize for Box<[T]> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.len().pagable_serialize(ctx.pagable())?;
for elem in self.iter() {
elem.starlark_serialize(ctx)?;
}
Ok(())
}
}
impl<T: StarlarkDeserialize> StarlarkDeserialize for Box<[T]> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let len = usize::pagable_deserialize(ctx.pagable())?;
let mut v = Vec::with_capacity(len);
for _ in 0..len {
v.push(T::starlark_deserialize(ctx)?);
}
Ok(v.into_boxed_slice())
}
}
impl<'v> StarlarkSerialize for ThinBoxSliceFrozenValue<'v> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.len().pagable_serialize(ctx.pagable())?;
for value in self.iter() {
value.starlark_serialize(ctx)?;
}
Ok(())
}
}
impl<'v> StarlarkDeserialize for ThinBoxSliceFrozenValue<'v> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let len = usize::pagable_deserialize(ctx.pagable())?;
let mut values = Vec::with_capacity(len);
for _ in 0..len {
values.push(FrozenValue::starlark_deserialize(ctx)?);
}
Ok(Self::from_iter(values))
}
}
impl<T: ?Sized> StarlarkSerialize for PhantomData<T> {
fn starlark_serialize(&self, _ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
Ok(())
}
}
impl<T: ?Sized> StarlarkDeserialize for PhantomData<T> {
fn starlark_deserialize(_ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
Ok(PhantomData)
}
}
impl StarlarkSerialize for starlark_syntax::codemap::CodeMap {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
PagableSerialize::pagable_serialize(self, ctx.pagable())?;
Ok(())
}
}
impl StarlarkDeserialize for starlark_syntax::codemap::CodeMap {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
Ok(PagableDeserialize::pagable_deserialize(ctx.pagable())?)
}
}
impl StarlarkSerialize for AssignOp {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
PagableSerialize::pagable_serialize(self, ctx.pagable())?;
Ok(())
}
}
impl StarlarkDeserialize for AssignOp {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
Ok(PagableDeserialize::pagable_deserialize(ctx.pagable())?)
}
}
impl StarlarkSerialize for starlark_syntax::syntax::ast::Visibility {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
PagableSerialize::pagable_serialize(self, ctx.pagable())?;
Ok(())
}
}
impl StarlarkDeserialize for starlark_syntax::syntax::ast::Visibility {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
Ok(PagableDeserialize::pagable_deserialize(ctx.pagable())?)
}
}
impl StarlarkSerialize for NonZeroI32 {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.get().pagable_serialize(ctx.pagable())?;
Ok(())
}
}
impl StarlarkDeserialize for NonZeroI32 {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let v = i32::pagable_deserialize(ctx.pagable())?;
NonZeroI32::new(v)
.ok_or_else(|| crate::Error::new_other(anyhow::anyhow!("expected non-zero i32, got 0")))
}
}
struct StarlarkArcBridge<T: 'static>(Arc<T>);
impl<T: 'static> Clone for StarlarkArcBridge<T> {
fn clone(&self) -> Self {
Self(self.0.dupe())
}
}
impl<T: 'static> Dupe for StarlarkArcBridge<T> {}
struct StarlarkArcBridgeWeak<T: 'static>(Weak<T>);
impl<T: StarlarkSerialize + StarlarkDeserialize + Send + Sync + 'static> WeakErase
for StarlarkArcBridgeWeak<T>
{
fn is_expired(&self) -> bool {
self.0.strong_count() == 0
}
fn upgrade_weak(&self) -> Option<Box<dyn ArcEraseDyn>> {
self.0
.upgrade()
.map(|arc| Box::new(StarlarkArcBridge(arc)) as _)
}
}
impl<T: StarlarkSerialize + StarlarkDeserialize + Send + Sync + 'static> ArcErase
for StarlarkArcBridge<T>
{
type Weak = StarlarkArcBridgeWeak<T>;
fn dupe_strong(&self) -> Self {
self.dupe()
}
fn erase_type() -> impl ArcEraseType {
StdArcEraseType::<Self>::new()
}
fn identity(&self) -> usize {
Arc::as_ptr(&self.0) as *const () as usize
}
fn downgrade(&self) -> Option<Self::Weak> {
Some(StarlarkArcBridgeWeak(Arc::downgrade(&self.0)))
}
fn upgrade_weak(weak: &Self::Weak) -> Option<Self> {
weak.0.upgrade().map(Self)
}
fn serialize_inner(&self, ser: &mut dyn PagableSerializer) -> pagable::Result<()> {
let mut ctx = StarlarkSerializerImpl::recover_from_pagable(ser)
.map_err(|e: crate::Error| e.into_anyhow())?;
<T as StarlarkSerialize>::starlark_serialize(&self.0, &mut ctx)
.map_err(|e: crate::Error| e.into_anyhow())
}
fn deserialize_inner<'de, D: PagableDeserializer<'de> + ?Sized>(
deser: &mut D,
) -> pagable::Result<Self> {
let mut ctx = StarlarkDeserializerImpl::recover_from_pagable(deser.as_dyn())
.map_err(|e: crate::Error| e.into_anyhow())?;
let inner = T::starlark_deserialize(&mut ctx).map_err(|e: crate::Error| e.into_anyhow())?;
Ok(Self(Arc::new(inner)))
}
}
impl<T: StarlarkSerialize + StarlarkDeserialize + Send + Sync + 'static> StarlarkSerialize
for Arc<T>
{
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
let bridge = StarlarkArcBridge(self.clone());
ctx.pagable().serialize_arc(&bridge)?;
Ok(())
}
}
impl<T: StarlarkSerialize + StarlarkDeserialize + Send + Sync + 'static> StarlarkDeserialize
for Arc<T>
{
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let bridge: StarlarkArcBridge<T> = deserialize_arc(ctx.pagable())?;
Ok(bridge.0)
}
}
impl<K: StarlarkSerialize, V: StarlarkSerialize, S> StarlarkSerialize for IndexMap<K, V, S> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
self.len().pagable_serialize(ctx.pagable())?;
for (k, v) in self.iter() {
k.starlark_serialize(ctx)?;
v.starlark_serialize(ctx)?;
}
Ok(())
}
}
impl<K, V, S> StarlarkDeserialize for IndexMap<K, V, S>
where
K: StarlarkDeserialize + Hash + Eq,
V: StarlarkDeserialize,
S: Default + BuildHasher,
{
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let len = usize::pagable_deserialize(ctx.pagable())?;
let mut map: IndexMap<K, V, S> = IndexMap::default();
for _ in 0..len {
let k = K::starlark_deserialize(ctx)?;
let v = V::starlark_deserialize(ctx)?;
map.insert(k, v);
}
Ok(map)
}
}
impl<A: StarlarkSerialize, B: StarlarkSerialize> StarlarkSerialize for either::Either<A, B> {
fn starlark_serialize(&self, ctx: &mut dyn StarlarkSerializeContext) -> crate::Result<()> {
match self {
either::Either::Left(a) => {
0u8.pagable_serialize(ctx.pagable())?;
a.starlark_serialize(ctx)?;
}
either::Either::Right(b) => {
1u8.pagable_serialize(ctx.pagable())?;
b.starlark_serialize(ctx)?;
}
}
Ok(())
}
}
impl<A: StarlarkDeserialize, B: StarlarkDeserialize> StarlarkDeserialize for either::Either<A, B> {
fn starlark_deserialize(ctx: &mut dyn StarlarkDeserializeContext<'_>) -> crate::Result<Self> {
let tag = u8::pagable_deserialize(ctx.pagable())?;
match tag {
0 => Ok(either::Either::Left(A::starlark_deserialize(ctx)?)),
1 => Ok(either::Either::Right(B::starlark_deserialize(ctx)?)),
_ => Err(crate::Error::new_other(anyhow::anyhow!(
"invalid Either tag: {}",
tag
))),
}
}
}