use std::marker::PhantomData;
use either::Either;
pub use starlark_derive::StarlarkTypeRepr;
use crate::typing::Ty;
use crate::values::list::ListType;
use crate::values::none::NoneType;
use crate::values::string::str_type::StarlarkStr;
use crate::values::Heap;
use crate::values::StarlarkValue;
use crate::values::Value;
pub trait StarlarkTypeRepr {
type Canonical: StarlarkTypeRepr;
fn starlark_type_repr() -> Ty;
}
pub struct SetType<T: StarlarkTypeRepr> {
t: PhantomData<T>,
}
impl<T: StarlarkTypeRepr> StarlarkTypeRepr for SetType<T> {
type Canonical = SetType<T::Canonical>;
fn starlark_type_repr() -> Ty {
Ty::set(T::starlark_type_repr())
}
}
impl<'v, T: StarlarkValue<'v>> StarlarkTypeRepr for T {
type Canonical = Self;
fn starlark_type_repr() -> Ty {
Self::get_type_starlark_repr()
}
}
impl StarlarkTypeRepr for String {
type Canonical = StarlarkStr;
fn starlark_type_repr() -> Ty {
StarlarkStr::starlark_type_repr()
}
}
impl StarlarkTypeRepr for &str {
type Canonical = StarlarkStr;
fn starlark_type_repr() -> Ty {
StarlarkStr::starlark_type_repr()
}
}
impl<T: StarlarkTypeRepr> StarlarkTypeRepr for Option<T> {
type Canonical = <Either<NoneType, T> as StarlarkTypeRepr>::Canonical;
fn starlark_type_repr() -> Ty {
Either::<NoneType, T>::starlark_type_repr()
}
}
impl<T: StarlarkTypeRepr> StarlarkTypeRepr for Vec<T> {
type Canonical = <ListType<T> as StarlarkTypeRepr>::Canonical;
fn starlark_type_repr() -> Ty {
ListType::<T::Canonical>::starlark_type_repr()
}
}
impl<TLeft: StarlarkTypeRepr, TRight: StarlarkTypeRepr> StarlarkTypeRepr for Either<TLeft, TRight> {
type Canonical = Either<TLeft::Canonical, TRight::Canonical>;
fn starlark_type_repr() -> Ty {
Ty::union2(TLeft::starlark_type_repr(), TRight::starlark_type_repr())
}
}
#[doc(hidden)]
pub fn type_repr_from_attr_impl<'v, T: StarlarkTypeRepr, E>(
_f: fn(Value<'v>, &'v Heap) -> Result<T, E>,
) -> Ty {
T::starlark_type_repr()
}
#[cfg(test)]
mod tests {
use crate::tests::util::TestComplexValue;
use crate::util::non_static_type_id::non_static_type_id;
use crate::values::type_repr::StarlarkTypeRepr;
use crate::values::FrozenValue;
use crate::values::Value;
#[test]
fn test_canonical_for_complex_value() {
assert_ne!(
non_static_type_id::<<TestComplexValue<Value> as StarlarkTypeRepr>::Canonical>(),
non_static_type_id::<<TestComplexValue<FrozenValue> as StarlarkTypeRepr>::Canonical>(),
);
}
}