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