use std::fmt;
use std::fmt::Display;
use std::ops::Deref;
use crate as starlark;
use crate::coerce::coerce;
use crate::typing::Ty;
use crate::values::list::value::display_list;
use crate::values::list::value::FrozenListData;
use crate::values::list::value::ListGen;
use crate::values::type_repr::StarlarkTypeRepr;
use crate::values::types::list::value::ListData;
use crate::values::Coerce;
use crate::values::FrozenValue;
use crate::values::UnpackValue;
use crate::values::Value;
use crate::values::ValueLike;
#[repr(transparent)]
#[derive(Coerce)]
pub struct ListRef<'v> {
pub(crate) content: [Value<'v>],
}
#[repr(transparent)]
#[derive(Coerce)]
pub struct FrozenListRef {
pub(crate) content: [FrozenValue],
}
impl<'v> ListRef<'v> {
pub const TYPE: &'static str = ListData::TYPE;
pub(crate) fn new<'a>(slice: &'a [Value<'v>]) -> &'a ListRef<'v> {
coerce(slice)
}
pub fn content(&self) -> &[Value<'v>] {
&self.content
}
pub fn iter<'a>(&'a self) -> impl ExactSizeIterator<Item = Value<'v>> + 'a
where
'v: 'a,
{
self.content.iter().copied()
}
pub fn from_value(x: Value<'v>) -> Option<&'v ListRef<'v>> {
if x.unpack_frozen().is_some() {
x.downcast_ref::<ListGen<FrozenListData>>()
.map(|x| ListRef::new(coerce(x.0.content())))
} else {
let ptr = x.downcast_ref::<ListGen<ListData>>()?;
Some(ListRef::new(ptr.0.content()))
}
}
pub fn from_frozen_value<'f>(x: FrozenValue) -> Option<&'f ListRef<'f>> {
x.downcast_ref::<ListGen<FrozenListData>>()
.map(|x| ListRef::new(coerce(x.0.content())))
}
}
impl FrozenListRef {
pub const TYPE: &'static str = ListRef::TYPE;
fn new(slice: &[FrozenValue]) -> &FrozenListRef {
coerce(slice)
}
pub fn from_value(x: Value) -> Option<&'static FrozenListRef> {
Self::from_frozen_value(x.unpack_frozen()?)
}
pub fn from_frozen_value(x: FrozenValue) -> Option<&'static FrozenListRef> {
x.downcast_ref::<ListGen<FrozenListData>>()
.map(|x| FrozenListRef::new(x.0.content()))
}
}
impl<'v> Deref for ListRef<'v> {
type Target = [Value<'v>];
fn deref(&self) -> &[Value<'v>] {
&self.content
}
}
impl Deref for FrozenListRef {
type Target = [FrozenValue];
fn deref(&self) -> &[FrozenValue] {
&self.content
}
}
impl<'v> Display for ListRef<'v> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
display_list(&self.content, f)
}
}
impl Display for FrozenListRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
display_list(coerce(&self.content), f)
}
}
impl<'v> StarlarkTypeRepr for &'v ListRef<'v> {
fn starlark_type_repr() -> Ty {
Vec::<Value<'v>>::starlark_type_repr()
}
}
impl<'v> StarlarkTypeRepr for &'v FrozenListRef {
fn starlark_type_repr() -> Ty {
Vec::<FrozenValue>::starlark_type_repr()
}
}
impl<'v> UnpackValue<'v> for &'v ListRef<'v> {
fn expected() -> String {
"list".to_owned()
}
fn unpack_value(value: Value<'v>) -> Option<Self> {
ListRef::from_value(value)
}
}
impl<'v> UnpackValue<'v> for &'v FrozenListRef {
fn expected() -> String {
"frozen list".to_owned()
}
fn unpack_value(value: Value<'v>) -> Option<Self> {
FrozenListRef::from_value(value)
}
}