use std::slice;
use std::vec;
use crate::typing::Ty;
use crate::values::list::ListRef;
use crate::values::type_repr::StarlarkTypeRepr;
use crate::values::UnpackValue;
use crate::values::Value;
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct UnpackList<T> {
pub items: Vec<T>,
}
impl<T: StarlarkTypeRepr> StarlarkTypeRepr for UnpackList<T> {
fn starlark_type_repr() -> Ty {
Vec::<T>::starlark_type_repr()
}
}
impl<'v, T: UnpackValue<'v>> UnpackValue<'v> for UnpackList<T> {
fn unpack_value(value: Value<'v>) -> Option<Self> {
let list = ListRef::from_value(value)?;
let mut items = Vec::with_capacity(list.len());
for v in list.iter() {
items.push(T::unpack_value(v)?);
}
Some(UnpackList { items })
}
}
impl<T> IntoIterator for UnpackList<T> {
type Item = T;
type IntoIter = vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl<'a, T> IntoIterator for &'a UnpackList<T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.items.iter()
}
}
impl<'a, T> IntoIterator for &'a mut UnpackList<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.items.iter_mut()
}
}
#[cfg(test)]
mod tests {
use crate::values::list::UnpackList;
use crate::values::Heap;
use crate::values::UnpackValue;
#[test]
fn test_unpack() {
let heap = Heap::new();
let v = heap.alloc(vec!["a", "b"]);
assert_eq!(
vec!["a", "b"],
UnpackList::<&str>::unpack_value(v).unwrap().items
);
assert!(UnpackList::<u32>::unpack_value(v).is_none());
assert!(UnpackList::<&str>::unpack_value(heap.alloc(1)).is_none());
}
}