starlark/values/types/tuple/
unpack.rs1use std::slice;
19use std::vec;
20
21use crate::typing::Ty;
22use crate::values::tuple::TupleRef;
23use crate::values::type_repr::StarlarkTypeRepr;
24use crate::values::UnpackValue;
25use crate::values::Value;
26
27#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
29pub struct UnpackTuple<T> {
30 pub items: Vec<T>,
32}
33
34impl<T: Default> Default for UnpackTuple<T> {
35 fn default() -> Self {
36 UnpackTuple { items: Vec::new() }
37 }
38}
39
40impl<T: StarlarkTypeRepr> StarlarkTypeRepr for UnpackTuple<T> {
41 type Canonical = UnpackTuple<T::Canonical>;
42
43 fn starlark_type_repr() -> Ty {
44 Ty::tuple_of(T::starlark_type_repr())
45 }
46}
47
48impl<'v, T: UnpackValue<'v>> UnpackValue<'v> for UnpackTuple<T> {
49 type Error = <T as UnpackValue<'v>>::Error;
50
51 fn unpack_value_impl(value: Value<'v>) -> Result<Option<Self>, Self::Error> {
52 let Some(tuple) = TupleRef::from_value(value) else {
53 return Ok(None);
54 };
55 let mut items = Vec::with_capacity(tuple.len());
57 for v in tuple.iter() {
58 let Some(v) = T::unpack_value_impl(v)? else {
59 return Ok(None);
60 };
61 items.push(v);
62 }
63 Ok(Some(UnpackTuple { items }))
64 }
65}
66
67impl<T> IntoIterator for UnpackTuple<T> {
68 type Item = T;
69 type IntoIter = vec::IntoIter<T>;
70
71 fn into_iter(self) -> Self::IntoIter {
72 self.items.into_iter()
73 }
74}
75
76impl<'a, T> IntoIterator for &'a UnpackTuple<T> {
77 type Item = &'a T;
78 type IntoIter = slice::Iter<'a, T>;
79
80 fn into_iter(self) -> Self::IntoIter {
81 self.items.iter()
82 }
83}
84
85impl<'a, T> IntoIterator for &'a mut UnpackTuple<T> {
86 type Item = &'a mut T;
87 type IntoIter = slice::IterMut<'a, T>;
88
89 fn into_iter(self) -> Self::IntoIter {
90 self.items.iter_mut()
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use crate::values::tuple::unpack::UnpackTuple;
97 use crate::values::Heap;
98 use crate::values::UnpackValue;
99
100 #[test]
101 fn test_unpack() {
102 let heap = Heap::new();
103 let v = heap.alloc(("a", "b"));
104 assert_eq!(
105 vec!["a", "b"],
106 UnpackTuple::<&str>::unpack_value(v).unwrap().unwrap().items
107 );
108 assert!(UnpackTuple::<u32>::unpack_value(v).unwrap().is_none());
109 assert!(
110 UnpackTuple::<&str>::unpack_value(heap.alloc(1))
111 .unwrap()
112 .is_none()
113 );
114 }
115}