1use std::ffi::c_int;
2use std::fmt::{self, Debug, Display};
3use std::mem::ManuallyDrop;
4use std::ptr;
5
6use luajit_bindings::{self as lua, ffi::lua_State};
7
8use super::{KVec, Object};
9
10pub type Array = KVec<Object>;
14
15impl Debug for Array {
16 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
17 f.debug_list().entries(self.iter()).finish()
18 }
19}
20
21impl Display for Array {
22 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23 Debug::fmt(self, f)
24 }
25}
26
27impl lua::Pushable for Array {
28 unsafe fn push(self, state: *mut lua_State) -> Result<c_int, lua::Error> {
29 <Vec<Object>>::from(self).push(state)
30 }
31}
32
33impl lua::Poppable for Array {
34 unsafe fn pop(state: *mut lua_State) -> Result<Self, lua::Error> {
35 <Vec<Object> as lua::Poppable>::pop(state).map(Into::into)
36 }
37}
38
39impl IntoIterator for Array {
40 type IntoIter = ArrayIterator;
41 type Item = <ArrayIterator as Iterator>::Item;
42
43 #[inline]
44 fn into_iter(self) -> Self::IntoIter {
45 let arr = ManuallyDrop::new(self);
47 let start = arr.items;
48 let end = unsafe { start.add(arr.len()) };
49 ArrayIterator { start, end }
50 }
51}
52
53impl<T> FromIterator<T> for Array
54where
55 T: Into<Object>,
56{
57 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
58 iter.into_iter()
59 .map(Into::into)
60 .filter(Object::is_some) .collect::<Vec<Object>>()
62 .into()
63 }
64}
65
66pub struct ArrayIterator {
68 start: *const Object,
69 end: *const Object,
70}
71
72impl Iterator for ArrayIterator {
73 type Item = Object;
74
75 #[inline]
76 fn next(&mut self) -> Option<Self::Item> {
77 if self.start == self.end {
78 return None;
79 }
80 let current = self.start;
81 self.start = unsafe { self.start.offset(1) };
82 Some(unsafe { ptr::read(current) })
83 }
84
85 #[inline]
86 fn size_hint(&self) -> (usize, Option<usize>) {
87 let exact = self.len();
88 (exact, Some(exact))
89 }
90
91 #[inline]
92 fn count(self) -> usize {
93 self.len()
94 }
95}
96
97impl ExactSizeIterator for ArrayIterator {
98 fn len(&self) -> usize {
99 unsafe { self.end.offset_from(self.start) as usize }
100 }
101}
102
103impl DoubleEndedIterator for ArrayIterator {
104 #[inline]
105 fn next_back(&mut self) -> Option<Self::Item> {
106 if self.start == self.end {
107 return None;
108 }
109 let current = self.end;
110 self.end = unsafe { self.end.offset(-1) };
111 Some(unsafe { ptr::read(current) })
112 }
113}
114
115impl std::iter::FusedIterator for ArrayIterator {}
116
117impl Drop for ArrayIterator {
118 fn drop(&mut self) {
119 while self.start != self.end {
120 unsafe {
121 ptr::drop_in_place(self.start as *mut Object);
122 self.start = self.start.offset(1);
123 }
124 }
125 }
126}
127
128macro_rules! from_tuple {
131 ($($ty:ident)*) => {
132 impl <$($ty: Into<Object>),*> From<($($ty,)*)> for Array {
133 #[allow(non_snake_case)]
134 fn from(($($ty,)*): ($($ty,)*)) -> Self {
135 Self::from_iter([$($ty.into(),)*])
136 }
137 }
138 };
139}
140
141from_tuple!(A);
142from_tuple!(A B);
143from_tuple!(A B C);
144from_tuple!(A B C D);
145from_tuple!(A B C D E);
146from_tuple!(A B C D E F);
147from_tuple!(A B C D E F G);
148from_tuple!(A B C D E F G H);
149from_tuple!(A B C D E F G H I);
150from_tuple!(A B C D E F G H I J);
151from_tuple!(A B C D E F G H I J K);
152from_tuple!(A B C D E F G H I J K L);
153from_tuple!(A B C D E F G H I J K L M);
154from_tuple!(A B C D E F G H I J K L M N);
155from_tuple!(A B C D E F G H I J K L M N O);
156from_tuple!(A B C D E F G H I J K L M N O P);
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161
162 #[test]
163 fn iter_basic() {
164 let array = Array::from_iter(["Foo", "Bar", "Baz"]);
165
166 let mut iter = array.into_iter();
167 assert_eq!(Some(Object::from("Foo")), iter.next());
168 assert_eq!(Some(Object::from("Bar")), iter.next());
169 assert_eq!(Some(Object::from("Baz")), iter.next());
170 assert_eq!(None, iter.next());
171 }
172
173 #[test]
174 fn drop_iter_halfway() {
175 let array = Array::from_iter(["Foo", "Bar", "Baz"]);
176
177 let mut iter = array.into_iter();
178 assert_eq!(Some(Object::from("Foo")), iter.next());
179 }
180
181 #[test]
182 fn empty_array() {
183 let empty = Array { size: 0, capacity: 0, items: ptr::null_mut() };
184 assert_eq!(0, empty.into_iter().count());
185 }
186
187 #[test]
188 fn debug_array() {
189 let arr = Array::from((1, 2, 3, "a", true));
190 assert_eq!(String::from("[1, 2, 3, \"a\", true]"), format!("{arr}"));
191 }
192
193 #[test]
194 fn debug_nested_array() {
195 let arr = Array::from_iter([Array::from((1, 2, 3))]);
196 assert_eq!(String::from("[[1, 2, 3]]"), format!("{arr}"));
197 }
198}