1use super::{BoxedObject, Iter, Object, RefValue};
3use crate::value;
4use tokay_macros::tokay_method;
5extern crate self as tokay;
6
7type InnerList = Vec<RefValue>;
9
10#[derive(Debug, Clone, PartialEq, PartialOrd)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13#[cfg_attr(feature = "serde", serde(transparent))]
14pub struct List {
15 list: InnerList,
16}
17
18impl Object for List {
19 fn severity(&self) -> u8 {
20 30
21 }
22
23 fn name(&self) -> &'static str {
24 "list"
25 }
26
27 fn repr(&self) -> String {
28 let mut ret = "(".to_string();
29
30 for item in self.iter() {
31 if ret.len() > 1 {
32 ret.push_str(", ");
33 }
34
35 ret.push_str(&item.borrow().repr());
36 }
37
38 if self.len() <= 1 {
39 ret.push_str(", )");
40 } else {
41 ret.push_str(")");
42 }
43
44 ret
45 }
46
47 fn is_true(&self) -> bool {
48 self.len() > 0
49 }
50
51 fn is_mutable(&self) -> bool {
52 true
53 }
54}
55
56#[allow(unused_doc_comments)]
57impl List {
58 pub fn new() -> Self {
59 Self {
60 list: InnerList::new(),
61 }
62 }
63
64 pub fn with_capacity(len: usize) -> Self {
65 Self {
66 list: InnerList::with_capacity(len),
67 }
68 }
69
70 tokay_method!("list : @*args", {
72 let list = if args.len() == 1 {
73 if args[0].is("iter") {
75 return Ok(args[0]
76 .call_method("collect", context, Vec::new(), None)?
77 .unwrap());
78 }
79 else {
81 List::from(args[0].clone())
82 }
83 }
84 else {
86 List { list: args }
87 };
88
89 Ok(RefValue::from(list))
90 });
91
92 tokay_method!("list_clone : @list", {
94 let borrowed = list.borrow();
95
96 if let Some(list) = borrowed.object::<List>() {
97 Ok(RefValue::from(list.clone()))
98 } else {
99 Ok(RefValue::from(List {
100 list: vec![list.clone()],
101 }))
102 }
103 });
104
105 tokay_method!("list_len : @list", {
107 let list = list.borrow();
108
109 Ok(RefValue::from(if let Some(list) = list.object::<List>() {
110 list.len()
111 } else if list.is_void() {
112 0
113 } else {
114 1
115 }))
116 });
117
118 tokay_method!(
128 "list_get_item : @list, index, default=void, upsert=false",
129 {
130 if !list.is("list") {
132 list = Self::list(vec![list], None)?;
133 }
134
135 {
136 let list = list.borrow();
137 let index = index.to_usize()?;
138
139 if let Some(value) = list.object::<List>().unwrap().get(index) {
140 return Ok(value.clone());
141 }
142 }
143
144 if upsert.is_true() {
145 if default.is_void() {
147 default = value![null];
148 }
149
150 return Self::list_set_item(vec![list, index, default], None);
151 }
152
153 Ok(default)
154 }
155 );
156
157 tokay_method!("list_set_item : @list, item, value=void", {
158 if !list.is("list") {
160 list = Self::list(vec![list], None)?;
161 }
162
163 let mut list = list.borrow_mut();
164 let list = list.object_mut::<List>().unwrap();
165
166 let item = item.to_usize()?;
167 let len = list.len();
168
169 if item >= len {
170 list.resize_with(item + 1, Default::default)
171 }
172
173 if value.is_void() {
174 value = list.remove(item);
175 } else {
176 list[item] = value.clone();
177 }
178
179 Ok(value)
180 });
181
182 tokay_method!("list_flatten : @list", {
183 if let Some(list) = list.borrow().object::<List>() {
184 let mut ret = List::with_capacity(list.len());
185
186 for item in list.iter() {
187 if let Some(list) = item.borrow().object::<List>() {
188 for item in list.iter() {
190 ret.push(item.clone());
191 }
192 } else {
193 ret.push(item.clone());
194 }
195 }
196
197 return Ok(RefValue::from(ret));
198 }
199
200 Ok(RefValue::from(crate::value!([list])))
201 });
202
203 tokay_method!("list_iadd : @list, append", {
204 if append.is_void() {
206 return Ok(list);
207 }
208
209 if !list.is("list") {
211 let item = RefValue::from(list.borrow().clone());
212 if item.is_void() {
213 *(list.borrow_mut()) = Self::list(vec![], None)?.into();
214 } else {
215 *(list.borrow_mut()) = Self::list(vec![item], None)?.into();
216 }
217 }
218
219 if let (Ok(mut inner), Ok(to_append)) = (list.try_borrow_mut(), append.try_borrow()) {
221 let inner = inner.object_mut::<List>().unwrap();
222
223 if let Some(append) = to_append.object::<List>() {
225 inner.reserve(append.len());
226
227 for item in append.iter() {
228 inner.push(item.clone());
229 }
230 } else {
232 inner.push(append.clone());
233 }
234
235 return Ok(list.clone());
236 }
237
238 let new = Self::list_add(vec![list.clone(), append.clone()], None)?;
240 *list.borrow_mut() = new.into();
241
242 Ok(list)
243 });
244
245 tokay_method!("list_add : @list, append", {
246 if append.is_void() {
248 return Ok(list);
249 }
250
251 if !list.is("list") {
253 list = RefValue::from(List::from(list));
254 }
255
256 let mut list = list.borrow().object::<List>().unwrap().clone();
257
258 if let Some(append) = append.borrow().object::<List>() {
260 list.reserve(append.len());
261
262 for item in append.iter() {
263 list.push(item.clone());
264 }
265 } else {
267 list.push(append.clone());
268 }
269
270 Ok(RefValue::from(list))
271 });
272
273 tokay_method!("list_push : @list, item, index=void", {
278 if item.is_void() {
280 return Ok(value![void]);
281 }
282
283 let mut list = list.borrow_mut();
284
285 if let Some(list) = list.object_mut::<List>() {
287 if index.is_void() {
288 list.push(item);
289 } else {
290 let index = index.to_usize()?;
291 let len = list.len();
292
293 if index > len {
294 return Err(format!(
295 "{} provided index {} out of range in list sized {}",
296 __function, index, len
297 )
298 .into());
299 }
300
301 list.insert(index, item);
302 }
303 }
304
305 Ok(value![void])
306 });
307
308 tokay_method!("list_extend : @list, extend, index=void", {
313 if extend.is_void() {
315 return Ok(value![void]);
316 }
317
318 if !extend.is("list") {
320 extend = RefValue::from(List::from(extend));
321 }
322
323 let mut list = list.borrow_mut();
324
325 if let Some(list) = list.object_mut::<List>() {
327 let extend = extend.borrow();
328 let extend = extend.object::<List>().unwrap();
329
330 list.reserve(extend.len());
331
332 if index.is_void() {
333 for item in extend.iter() {
334 if !item.is_void() {
335 list.push(item.clone());
336 }
337 }
338 } else {
339 let mut index = index.to_usize()?;
340 let len = list.len();
341
342 if index > len {
343 return Err(format!(
344 "{} provided index {} out of range in list sized {}",
345 __function, index, len
346 )
347 .into());
348 }
349
350 for item in extend.iter() {
351 if !item.is_void() {
352 list.insert(index, item.clone());
353 index += 1;
354 }
355 }
356 }
357 }
358
359 Ok(value![void])
360 });
361
362 tokay_method!("list_pop : @list, index=void", {
364 let index = if index.is_void() {
365 None
366 } else {
367 Some(index.to_usize()?)
368 };
369
370 if !list.is("list") {
371 if index.is_none() {
372 return Ok(list); }
374
375 return Ok(value![void]);
376 }
377
378 let mut list = list.borrow_mut();
379 let list = list.object_mut::<List>().unwrap();
380
381 Ok(match index {
383 None => match list.pop() {
384 Some(item) => item,
385 None => value![void],
386 },
387 Some(index) => {
388 let len = list.len();
389
390 if index < len {
391 list.remove(index)
392 } else {
393 value![void]
394 }
395 }
396 })
397 });
398
399 tokay_method!("list_sort : @list", {
400 if !list.is("list") {
401 return Ok(Self::list(vec![list], None)?);
402 }
403
404 {
405 let mut list = list.borrow_mut();
406 let list = list.object_mut::<List>().unwrap();
407 list.sort();
408 }
409
410 Ok(list)
411 });
412
413 tokay_method!("list_index : @list, item", {
418 let list = list.borrow();
419
420 if let Some(list) = list.object::<List>() {
421 if let Some(index) = list
422 .list
423 .iter()
424 .position(|val| *val.borrow() == *item.borrow())
425 {
426 return Ok(value![index]);
427 }
428 }
429
430 Ok(value![-1])
431 });
432}
433
434impl std::ops::Deref for List {
435 type Target = InnerList;
436
437 fn deref(&self) -> &Self::Target {
438 &self.list
439 }
440}
441
442impl std::ops::DerefMut for List {
443 fn deref_mut(&mut self) -> &mut Self::Target {
444 &mut self.list
445 }
446}
447
448impl std::iter::IntoIterator for List {
449 type Item = RefValue;
450 type IntoIter = std::vec::IntoIter<Self::Item>;
451
452 fn into_iter(self) -> Self::IntoIter {
453 self.list.into_iter()
454 }
455}
456
457impl From<RefValue> for List {
458 fn from(refvalue: RefValue) -> Self {
459 match refvalue.name() {
460 "iter" => {
461 let mut iter = refvalue.borrow_mut();
462 let iter = iter.object_mut::<Iter>().unwrap();
463 let mut list = InnerList::new();
464
465 for item in iter {
466 list.push(item);
467 }
468
469 Self { list }
470 }
471 "list" => {
472 let list = refvalue.borrow();
473 let list = list.object::<List>().unwrap();
474 (*list).clone()
475 }
476 "void" => Self { list: Vec::new() },
477 _ => Self {
478 list: vec![refvalue.clone()],
479 },
480 }
481 }
482}
483
484impl From<&RefValue> for List {
485 fn from(refvalue: &RefValue) -> Self {
486 List::from(refvalue.clone())
487 }
488}
489
490impl From<List> for RefValue {
491 fn from(value: List) -> Self {
492 RefValue::from(Box::new(value) as BoxedObject)
493 }
494}
495
496impl From<InnerList> for RefValue {
497 fn from(list: InnerList) -> Self {
498 RefValue::from(List { list })
499 }
500}