use std::cmp::Ordering;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Write;
use allocative::Allocative;
use erased_serde::Serialize;
use starlark_derive::starlark_internal_vtable;
use starlark_map::StarlarkHashValue;
use crate::any::ProvidesStaticType;
use crate::collections::Hashed;
use crate::collections::StarlarkHasher;
use crate::docs::DocItem;
use crate::docs::DocMember;
use crate::docs::DocProperty;
use crate::environment::Methods;
use crate::eval::Arguments;
use crate::eval::Evaluator;
use crate::private::Private;
use crate::typing::Ty;
use crate::typing::TyBasic;
use crate::typing::TypingBinOp;
use crate::values::demand::Demand;
use crate::values::error::ControlError;
use crate::values::function::FUNCTION_TYPE;
use crate::values::Freeze;
use crate::values::FrozenStringValue;
use crate::values::FrozenValue;
use crate::values::Heap;
use crate::values::Trace;
use crate::values::Value;
use crate::values::ValueError;
pub trait ComplexValue<'v>: StarlarkValue<'v> + Trace<'v> + Freeze
where
<Self as Freeze>::Frozen: StarlarkValue<'static>,
{
}
impl<'v, V> ComplexValue<'v> for V
where
V: StarlarkValue<'v> + Trace<'v> + Freeze,
<V as Freeze>::Frozen: StarlarkValue<'static>,
{
}
#[starlark_internal_vtable]
#[allow(non_upper_case_globals, non_snake_case)] pub trait StarlarkValue<'v>:
'v + ProvidesStaticType<'v> + Allocative + Debug + Display + Serialize + Sized
{
type Canonical: StarlarkValue<'v> = Self;
const TYPE: &'static str = panic!("This field is implemented by #[starlark_value] proc macro");
fn get_type_value_static() -> FrozenStringValue {
panic!("This function is implemented by #[starlark_value] proc macro")
}
fn get_type_starlark_repr() -> Ty {
Ty::starlark_value::<Self>()
}
#[doc(hidden)]
#[starlark_internal_vtable(skip)]
fn please_use_starlark_type_macro() {
panic!("This function is implemented by #[starlark_value] proc macro")
}
#[doc(hidden)]
#[starlark_internal_vtable(skip)]
fn is_special(_private: Private) -> bool {
false
}
#[doc(hidden)]
fn type_matches_value(&self, _value: Value<'v>, _private: Private) -> bool {
unreachable!("`type_matches_value` should only be called on special types")
}
fn get_methods() -> Option<&'static Methods>
where
Self: Sized,
{
None
}
fn documentation(&self) -> DocItem
where
Self: Sized,
{
let ty = self
.typechecker_ty()
.unwrap_or_else(|| Self::get_type_starlark_repr());
DocItem::Member(DocMember::Property(DocProperty {
docs: None,
typ: ty,
}))
}
fn typechecker_ty(&self) -> Option<Ty> {
None
}
#[doc(hidden)]
fn eval_type(&self) -> Option<Ty> {
None
}
fn collect_repr(&self, collector: &mut String) {
write!(collector, "{}", self).unwrap()
}
fn collect_repr_cycle(&self, collector: &mut String) {
write!(collector, "<{}...>", Self::TYPE).unwrap()
}
fn name_for_call_stack(&self, me: Value<'v>) -> String {
me.to_repr()
}
fn to_bool(&self) -> bool {
true
}
fn write_hash(&self, hasher: &mut StarlarkHasher) -> crate::Result<()> {
if Self::TYPE == FUNCTION_TYPE {
let _ = hasher;
Ok(())
} else {
Err(crate::Error::new_other(ControlError::NotHashableValue(
Self::TYPE.to_owned(),
)))
}
}
#[doc(hidden)]
fn get_hash(&self, _private: Private) -> crate::Result<StarlarkHashValue> {
let mut hasher = StarlarkHasher::new();
self.write_hash(&mut hasher)?;
Ok(hasher.finish_small())
}
fn equals(&self, _other: Value<'v>) -> crate::Result<bool> {
Ok(false)
}
fn compare(&self, other: Value<'v>) -> crate::Result<Ordering> {
ValueError::unsupported_with(self, "compare", other)
}
fn invoke(
&self,
_me: Value<'v>,
_args: &Arguments<'v, '_>,
_eval: &mut Evaluator<'v, '_, '_>,
) -> crate::Result<Value<'v>> {
ValueError::unsupported(self, "call()")
}
fn at(&self, index: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "[]", index)
}
fn at2(
&self,
_index0: Value<'v>,
_index1: Value<'v>,
_heap: &'v Heap,
_private: Private,
) -> crate::Result<Value<'v>> {
ValueError::unsupported(self, "[,]")
}
fn slice(
&self,
_start: Option<Value<'v>>,
_stop: Option<Value<'v>>,
_stride: Option<Value<'v>>,
_heap: &'v Heap,
) -> crate::Result<Value<'v>> {
ValueError::unsupported(self, "[::]")
}
#[starlark_internal_vtable(skip)]
fn iterate_collect(&self, _heap: &'v Heap) -> crate::Result<Vec<Value<'v>>> {
ValueError::unsupported(self, "(iter)")
}
unsafe fn iterate(&self, _me: Value<'v>, heap: &'v Heap) -> crate::Result<Value<'v>> {
Ok(heap.alloc_tuple(&self.iterate_collect(heap)?))
}
unsafe fn iter_size_hint(&self, _index: usize) -> (usize, Option<usize>) {
(0, None)
}
unsafe fn iter_next(&self, _index: usize, _heap: &'v Heap) -> Option<Value<'v>> {
panic!(
"iter_next called on non-iterable value of type {}",
Self::TYPE
)
}
unsafe fn iter_stop(&self) {
panic!(
"iter_stop called on non-iterable value of type {}",
Self::TYPE
)
}
fn length(&self) -> crate::Result<i32> {
ValueError::unsupported(self, "len()")
}
fn attr_ty(_name: &str) -> Option<Ty> {
Some(Ty::any())
}
fn get_attr(&self, _attribute: &str, _heap: &'v Heap) -> Option<Value<'v>> {
None
}
fn get_attr_hashed(&self, attribute: Hashed<&str>, heap: &'v Heap) -> Option<Value<'v>> {
self.get_attr(attribute.key(), heap)
}
fn has_attr(&self, attribute: &str, heap: &'v Heap) -> bool {
self.get_attr(attribute, heap).is_some()
}
fn dir_attr(&self) -> Vec<String> {
Vec::new()
}
fn is_in(&self, other: Value<'v>) -> crate::Result<bool> {
ValueError::unsupported_owned(other.get_type(), "in", Some(Self::TYPE))
}
fn plus(&self, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported(self, "+")
}
fn minus(&self, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported(self, "-")
}
fn radd(&self, _lhs: Value<'v>, _heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
None
}
fn add(&self, _rhs: Value<'v>, _heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
None
}
fn sub(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "-", other)
}
fn rmul(&self, lhs: Value<'v>, heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
let _ignore = (lhs, heap);
None
}
fn mul(&self, _rhs: Value<'v>, _heap: &'v Heap) -> Option<crate::Result<Value<'v>>> {
None
}
fn div(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "/", other)
}
fn percent(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "%", other)
}
fn floor_div(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "//", other)
}
fn bit_and(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "&", other)
}
fn bit_or(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "|", other)
}
fn bit_xor(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "^", other)
}
fn bit_not(&self, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported(self, "~")
}
fn left_shift(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, "<<", other)
}
fn right_shift(&self, other: Value<'v>, _heap: &'v Heap) -> crate::Result<Value<'v>> {
ValueError::unsupported_with(self, ">>", other)
}
fn bin_op_ty(_op: TypingBinOp, _rhs: &TyBasic) -> Option<Ty> {
None
}
fn rbin_op_ty(_lhs: &TyBasic, _op: TypingBinOp) -> Option<Ty> {
None
}
fn export_as(
&self,
_variable_name: &str,
_eval: &mut Evaluator<'v, '_, '_>,
) -> crate::Result<()> {
Ok(())
}
fn set_at(&self, _index: Value<'v>, _new_value: Value<'v>) -> crate::Result<()> {
Err(crate::Error::new_other(
ValueError::CannotMutateImmutableValue,
))
}
fn set_attr(&self, attribute: &str, _new_value: Value<'v>) -> crate::Result<()> {
ValueError::unsupported(self, &format!(".{}=", attribute))
}
fn provide(&'v self, demand: &mut Demand<'_, 'v>) {
let _ = demand;
}
fn try_freeze_static(&self) -> Option<FrozenValue> {
None
}
}