starlark/values/types/
list_or_tuple.rs1use std::slice;
21use std::vec;
22
23use either::Either;
24
25use crate::typing::Ty;
26use crate::values::list::UnpackList;
27use crate::values::tuple::UnpackTuple;
28use crate::values::type_repr::StarlarkTypeRepr;
29use crate::values::UnpackValue;
30use crate::values::Value;
31
32#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
34pub struct UnpackListOrTuple<T> {
35 pub items: Vec<T>,
37}
38
39impl<T> Default for UnpackListOrTuple<T> {
40 fn default() -> Self {
41 UnpackListOrTuple { items: Vec::new() }
42 }
43}
44
45impl<T: StarlarkTypeRepr> StarlarkTypeRepr for UnpackListOrTuple<T> {
46 type Canonical = <Either<UnpackList<T>, UnpackTuple<T>> as StarlarkTypeRepr>::Canonical;
47
48 fn starlark_type_repr() -> Ty {
49 Either::<UnpackList<T>, UnpackTuple<T>>::starlark_type_repr()
50 }
51}
52
53impl<'v, T: UnpackValue<'v>> UnpackValue<'v> for UnpackListOrTuple<T> {
54 type Error = <T as UnpackValue<'v>>::Error;
55
56 fn unpack_value_impl(value: Value<'v>) -> Result<Option<Self>, Self::Error> {
57 match Either::<UnpackList<T>, UnpackTuple<T>>::unpack_value_impl(value)
58 .map_err(|e| e.into_inner())?
59 {
60 Some(Either::Left(l)) => Ok(Some(UnpackListOrTuple { items: l.items })),
61 Some(Either::Right(r)) => Ok(Some(UnpackListOrTuple { items: r.items })),
62 None => Ok(None),
63 }
64 }
65}
66
67impl<T> IntoIterator for UnpackListOrTuple<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 UnpackListOrTuple<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 UnpackListOrTuple<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::types::list_or_tuple::UnpackListOrTuple;
97 use crate::values::Heap;
98 use crate::values::UnpackValue;
99
100 #[test]
101 fn test_unpack() {
102 let heap = Heap::new();
103 let list = heap.alloc(vec!["a", "b"]);
104 let tuple = heap.alloc(("a", "b"));
105 let list_of_ints = heap.alloc(vec![1, 2]);
106 let tuple_of_ints = heap.alloc((1, 2));
107 assert_eq!(
108 vec!["a", "b"],
109 UnpackListOrTuple::<&str>::unpack_value(list)
110 .unwrap()
111 .unwrap()
112 .items
113 );
114 assert_eq!(
115 vec!["a", "b"],
116 UnpackListOrTuple::<&str>::unpack_value(tuple)
117 .unwrap()
118 .unwrap()
119 .items
120 );
121 assert!(
122 UnpackListOrTuple::<&str>::unpack_value(list_of_ints)
123 .unwrap()
124 .is_none()
125 );
126 assert!(
127 UnpackListOrTuple::<&str>::unpack_value(tuple_of_ints)
128 .unwrap()
129 .is_none()
130 );
131 assert!(
132 UnpackListOrTuple::<&str>::unpack_value(heap.alloc(1))
133 .unwrap()
134 .is_none()
135 );
136 }
137}