1use crate::ffi::*;
43use std::{fmt, mem::MaybeUninit, ops::Index};
44
45pub type VectorIntList = igraph_vector_int_list_t;
47pub type VectorList = igraph_vector_list_t;
49pub type MatrixList = igraph_matrix_list_t;
51pub type GraphList = igraph_graph_list_t;
53pub type BitsetList = igraph_bitset_list_t;
55
56macro_rules! impl_list {
57 ($ty:ident, $item:ident, init = $init:ident, init_copy = $init_copy:ident,
58 destroy = $destroy:ident, push_back = $push:ident, pop_back = $pop:ident,
59 remove = $remove:ident) => {
60 impl $ty {
61 pub fn new() -> Self {
64 crate::error::ensure_init();
65 let mut raw = MaybeUninit::<Self>::uninit();
66 crate::error::check(unsafe { $init(raw.as_mut_ptr(), 0) })
67 .expect("igraph failed to allocate a list");
68 unsafe { raw.assume_init() }
69 }
70
71 pub fn len(&self) -> usize {
73 if self.stor_begin.is_null() {
74 0
75 } else {
76 unsafe { self.end.offset_from(self.stor_begin) as usize }
77 }
78 }
79
80 pub fn is_empty(&self) -> bool {
82 self.len() == 0
83 }
84
85 pub fn as_slice(&self) -> &[$item] {
87 if self.stor_begin.is_null() {
88 &[]
89 } else {
90 unsafe { std::slice::from_raw_parts(self.stor_begin, self.len()) }
91 }
92 }
93
94 pub fn as_mut_slice(&mut self) -> &mut [$item] {
96 if self.stor_begin.is_null() {
97 &mut []
98 } else {
99 let len = self.len();
100 unsafe { std::slice::from_raw_parts_mut(self.stor_begin, len) }
101 }
102 }
103
104 pub fn get(&self, index: usize) -> Option<&$item> {
106 self.as_slice().get(index)
107 }
108
109 pub fn iter(&self) -> std::slice::Iter<'_, $item> {
111 self.as_slice().iter()
112 }
113
114 pub fn push(&mut self, mut item: $item) {
117 crate::error::check(unsafe { $push(self, &mut item) })
118 .expect("igraph failed to grow a list");
119 std::mem::forget(item);
121 }
122
123 pub fn pop(&mut self) -> Option<$item> {
126 if self.is_empty() {
127 None
128 } else {
129 Some(unsafe { $pop(self) })
130 }
131 }
132
133 pub fn remove(&mut self, index: usize) -> $item {
140 assert!(index < self.len(), "list index {index} out of bounds");
141 let mut out = MaybeUninit::<$item>::uninit();
142 crate::error::check(unsafe {
143 $remove(self, index as igraph_int_t, out.as_mut_ptr())
144 })
145 .expect("igraph failed to remove a list item");
146 unsafe { out.assume_init() }
147 }
148
149 pub fn into_vec(mut self) -> Vec<$item> {
151 let mut items = Vec::with_capacity(self.len());
152 while let Some(item) = self.pop() {
153 items.push(item);
154 }
155 items.reverse();
156 items
157 }
158 }
159
160 impl Drop for $ty {
161 fn drop(&mut self) {
162 if !self.stor_begin.is_null() {
163 unsafe { $destroy(self) };
164 self.stor_begin = std::ptr::null_mut();
165 }
166 }
167 }
168
169 impl Default for $ty {
170 fn default() -> Self {
171 Self::new()
172 }
173 }
174
175 impl Clone for $ty {
176 fn clone(&self) -> Self {
177 crate::error::ensure_init();
178 let mut raw = MaybeUninit::<Self>::uninit();
179 crate::error::check(unsafe { $init_copy(raw.as_mut_ptr(), self) })
180 .expect("igraph failed to copy a list");
181 unsafe { raw.assume_init() }
182 }
183 }
184
185 impl Index<usize> for $ty {
186 type Output = $item;
187 fn index(&self, index: usize) -> &$item {
188 &self.as_slice()[index]
189 }
190 }
191
192 impl<'a> IntoIterator for &'a $ty {
193 type Item = &'a $item;
194 type IntoIter = std::slice::Iter<'a, $item>;
195 fn into_iter(self) -> Self::IntoIter {
196 self.iter()
197 }
198 }
199
200 impl IntoIterator for $ty {
201 type Item = $item;
202 type IntoIter = std::vec::IntoIter<$item>;
203 fn into_iter(self) -> Self::IntoIter {
204 self.into_vec().into_iter()
205 }
206 }
207
208 impl FromIterator<$item> for $ty {
209 fn from_iter<I: IntoIterator<Item = $item>>(iter: I) -> Self {
210 let mut list = Self::new();
211 for item in iter {
212 list.push(item);
213 }
214 list
215 }
216 }
217
218 impl From<Vec<$item>> for $ty {
219 fn from(items: Vec<$item>) -> Self {
220 items.into_iter().collect()
221 }
222 }
223
224 unsafe impl Send for $ty {}
225 };
226}
227
228impl_list!(
229 igraph_vector_int_list_t,
230 igraph_vector_int_t,
231 init = igraph_vector_int_list_init,
232 init_copy = igraph_vector_int_list_init_copy,
233 destroy = igraph_vector_int_list_destroy,
234 push_back = igraph_vector_int_list_push_back,
235 pop_back = igraph_vector_int_list_pop_back,
236 remove = igraph_vector_int_list_remove
237);
238impl_list!(
239 igraph_vector_list_t,
240 igraph_vector_t,
241 init = igraph_vector_list_init,
242 init_copy = igraph_vector_list_init_copy,
243 destroy = igraph_vector_list_destroy,
244 push_back = igraph_vector_list_push_back,
245 pop_back = igraph_vector_list_pop_back,
246 remove = igraph_vector_list_remove
247);
248impl_list!(
249 igraph_matrix_list_t,
250 igraph_matrix_t,
251 init = igraph_matrix_list_init,
252 init_copy = igraph_matrix_list_init_copy,
253 destroy = igraph_matrix_list_destroy,
254 push_back = igraph_matrix_list_push_back,
255 pop_back = igraph_matrix_list_pop_back,
256 remove = igraph_matrix_list_remove
257);
258impl_list!(
259 igraph_graph_list_t,
260 igraph_t,
261 init = igraph_graph_list_init,
262 init_copy = igraph_graph_list_init_copy,
263 destroy = igraph_graph_list_destroy,
264 push_back = igraph_graph_list_push_back,
265 pop_back = igraph_graph_list_pop_back,
266 remove = igraph_graph_list_remove
267);
268
269impl_list!(
270 igraph_bitset_list_t,
271 igraph_bitset_t,
272 init = igraph_bitset_list_init,
273 init_copy = igraph_bitset_list_init_copy,
274 destroy = igraph_bitset_list_destroy,
275 push_back = igraph_bitset_list_push_back,
276 pop_back = igraph_bitset_list_pop_back,
277 remove = igraph_bitset_list_remove
278);
279
280unsafe impl Sync for igraph_bitset_list_t {}
281unsafe impl Sync for igraph_vector_int_list_t {}
282unsafe impl Sync for igraph_vector_list_t {}
283unsafe impl Sync for igraph_matrix_list_t {}
284
285macro_rules! impl_vec_conversions {
286 ($ty:ident, $elem:ty, $vec:ident) => {
287 impl $ty {
288 pub fn to_vecs(&self) -> Vec<Vec<$elem>> {
290 self.iter().map(|v| v.to_vec()).collect()
291 }
292 }
293
294 impl FromIterator<Vec<$elem>> for $ty {
295 fn from_iter<I: IntoIterator<Item = Vec<$elem>>>(iter: I) -> Self {
296 iter.into_iter().map($vec::from).collect()
297 }
298 }
299
300 impl<'a> FromIterator<&'a [$elem]> for $ty {
301 fn from_iter<I: IntoIterator<Item = &'a [$elem]>>(iter: I) -> Self {
302 iter.into_iter().map($vec::from_slice).collect()
303 }
304 }
305
306 impl From<&[Vec<$elem>]> for $ty {
307 fn from(items: &[Vec<$elem>]) -> Self {
308 items.iter().map(|v| $vec::from_slice(v)).collect()
309 }
310 }
311
312 impl From<$ty> for Vec<Vec<$elem>> {
313 fn from(list: $ty) -> Self {
314 list.to_vecs()
315 }
316 }
317
318 impl PartialEq for $ty {
319 fn eq(&self, other: &Self) -> bool {
320 self.as_slice() == other.as_slice()
321 }
322 }
323 };
324}
325
326impl_vec_conversions!(igraph_vector_int_list_t, igraph_int_t, igraph_vector_int_t);
327impl_vec_conversions!(igraph_vector_list_t, igraph_real_t, igraph_vector_t);
328
329macro_rules! impl_list_extra {
334 (
335 $ty:ident, $item:ident,
336 insert = $insert:ident, replace = $replace:ident, remove_fast = $remove_fast:ident,
337 clear = $clear:ident, reverse = $reverse:ident, permute = $permute:ident,
338 capacity = $capacity:ident, reserve = $reserve:ident, swap_elements = $swap_elements:ident,
339 push_back_copy = $push_back_copy:ident
340 ) => {
341 impl $ty {
342 pub fn insert(&mut self, pos: usize, mut item: $item) {
349 let len = self.len();
350 assert!(
351 pos <= len,
352 "list insertion index {pos} out of bounds (len {len})"
353 );
354 crate::error::check(unsafe { $insert(self, pos as igraph_int_t, &mut item) })
355 .expect("igraph failed to grow a list");
356 std::mem::forget(item);
358 }
359
360 pub fn replace(&mut self, pos: usize, mut item: $item) -> $item {
366 let len = self.len();
367 assert!(pos < len, "list index {pos} out of bounds (len {len})");
368 unsafe { $replace(self, pos as igraph_int_t, &mut item) };
370 item
371 }
372
373 pub fn swap_remove(&mut self, pos: usize) -> $item {
380 let len = self.len();
381 assert!(pos < len, "list index {pos} out of bounds (len {len})");
382 let mut out = MaybeUninit::<$item>::uninit();
383 crate::error::check(unsafe {
384 $remove_fast(self, pos as igraph_int_t, out.as_mut_ptr())
385 })
386 .expect("igraph failed to remove a list item");
387 unsafe { out.assume_init() }
388 }
389
390 pub fn clear(&mut self) {
393 if !self.stor_begin.is_null() {
394 unsafe { $clear(self) };
395 }
396 }
397
398 pub fn truncate(&mut self, len: usize) {
400 while self.len() > len {
401 drop(self.pop());
402 }
403 }
404
405 pub fn reverse(&mut self) {
408 if !self.is_empty() {
409 crate::error::check(unsafe { $reverse(self) })
410 .expect("igraph_*_list_reverse cannot fail");
411 }
412 }
413
414 pub fn swap(&mut self, i: usize, j: usize) {
420 let len = self.len();
421 assert!(
422 i < len && j < len,
423 "list indices ({i}, {j}) out of bounds (len {len})"
424 );
425 unsafe { $swap_elements(self, i as igraph_int_t, j as igraph_int_t) };
426 }
427
428 pub fn permute(&mut self, index: &[igraph_int_t]) -> crate::error::Result<()> {
438 let len = self.len();
439 if index.len() != len {
440 return Err(crate::error::Error::invalid(format!(
441 "permutation of length {} for a list of length {len}",
442 index.len()
443 )));
444 }
445 let mut seen = vec![false; len];
446 for &i in index {
447 if i < 0 || i as usize >= len || std::mem::replace(&mut seen[i as usize], true)
448 {
449 return Err(crate::error::Error::invalid(format!(
450 "invalid or repeated position {i} in a permutation of length {len}"
451 )));
452 }
453 }
454 if len == 0 {
455 return Ok(());
456 }
457 let idx = crate::vector::VectorInt::view(index);
458 crate::igraph_call!($permute(self, idx.as_ptr()))
459 }
460
461 pub fn sort_by(&mut self, compare: impl FnMut(&$item, &$item) -> std::cmp::Ordering) {
464 self.as_mut_slice().sort_by(compare);
465 }
466
467 pub fn sort_by_key<K: Ord>(&mut self, key: impl FnMut(&$item) -> K) {
469 self.as_mut_slice().sort_by_key(key);
470 }
471
472 pub fn capacity(&self) -> usize {
475 if self.stor_begin.is_null() {
476 0
477 } else {
478 unsafe { $capacity(self) as usize }
479 }
480 }
481
482 pub fn reserve(&mut self, capacity: usize) {
485 crate::error::check(unsafe { $reserve(self, crate::error::int_size(capacity)) })
486 .expect("igraph failed to reserve list storage");
487 }
488
489 pub fn push_copy(&mut self, item: &$item) {
492 crate::error::check(unsafe { $push_back_copy(self, item) })
493 .expect("igraph failed to grow a list");
494 }
495
496 pub fn get_mut(&mut self, index: usize) -> Option<&mut $item> {
498 self.as_mut_slice().get_mut(index)
499 }
500
501 pub fn first(&self) -> Option<&$item> {
503 self.as_slice().first()
504 }
505
506 pub fn last(&self) -> Option<&$item> {
508 self.as_slice().last()
509 }
510
511 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, $item> {
513 self.as_mut_slice().iter_mut()
514 }
515 }
516
517 impl std::ops::IndexMut<usize> for $ty {
518 fn index_mut(&mut self, index: usize) -> &mut $item {
519 &mut self.as_mut_slice()[index]
520 }
521 }
522
523 impl<'a> IntoIterator for &'a mut $ty {
524 type Item = &'a mut $item;
525 type IntoIter = std::slice::IterMut<'a, $item>;
526 fn into_iter(self) -> Self::IntoIter {
527 self.iter_mut()
528 }
529 }
530
531 impl Extend<$item> for $ty {
532 fn extend<I: IntoIterator<Item = $item>>(&mut self, iter: I) {
533 for item in iter {
534 self.push(item);
535 }
536 }
537 }
538 };
539}
540
541impl_list_extra!(
542 igraph_vector_int_list_t,
543 igraph_vector_int_t,
544 insert = igraph_vector_int_list_insert,
545 replace = igraph_vector_int_list_replace,
546 remove_fast = igraph_vector_int_list_remove_fast,
547 clear = igraph_vector_int_list_clear,
548 reverse = igraph_vector_int_list_reverse,
549 permute = igraph_vector_int_list_permute,
550 capacity = igraph_vector_int_list_capacity,
551 reserve = igraph_vector_int_list_reserve,
552 swap_elements = igraph_vector_int_list_swap_elements,
553 push_back_copy = igraph_vector_int_list_push_back_copy
554);
555impl_list_extra!(
556 igraph_vector_list_t,
557 igraph_vector_t,
558 insert = igraph_vector_list_insert,
559 replace = igraph_vector_list_replace,
560 remove_fast = igraph_vector_list_remove_fast,
561 clear = igraph_vector_list_clear,
562 reverse = igraph_vector_list_reverse,
563 permute = igraph_vector_list_permute,
564 capacity = igraph_vector_list_capacity,
565 reserve = igraph_vector_list_reserve,
566 swap_elements = igraph_vector_list_swap_elements,
567 push_back_copy = igraph_vector_list_push_back_copy
568);
569impl_list_extra!(
570 igraph_matrix_list_t,
571 igraph_matrix_t,
572 insert = igraph_matrix_list_insert,
573 replace = igraph_matrix_list_replace,
574 remove_fast = igraph_matrix_list_remove_fast,
575 clear = igraph_matrix_list_clear,
576 reverse = igraph_matrix_list_reverse,
577 permute = igraph_matrix_list_permute,
578 capacity = igraph_matrix_list_capacity,
579 reserve = igraph_matrix_list_reserve,
580 swap_elements = igraph_matrix_list_swap_elements,
581 push_back_copy = igraph_matrix_list_push_back_copy
582);
583impl_list_extra!(
584 igraph_bitset_list_t,
585 igraph_bitset_t,
586 insert = igraph_bitset_list_insert,
587 replace = igraph_bitset_list_replace,
588 remove_fast = igraph_bitset_list_remove_fast,
589 clear = igraph_bitset_list_clear,
590 reverse = igraph_bitset_list_reverse,
591 permute = igraph_bitset_list_permute,
592 capacity = igraph_bitset_list_capacity,
593 reserve = igraph_bitset_list_reserve,
594 swap_elements = igraph_bitset_list_swap_elements,
595 push_back_copy = igraph_bitset_list_push_back_copy
596);
597impl_list_extra!(
598 igraph_graph_list_t,
599 igraph_t,
600 insert = igraph_graph_list_insert,
601 replace = igraph_graph_list_replace,
602 remove_fast = igraph_graph_list_remove_fast,
603 clear = igraph_graph_list_clear,
604 reverse = igraph_graph_list_reverse,
605 permute = igraph_graph_list_permute,
606 capacity = igraph_graph_list_capacity,
607 reserve = igraph_graph_list_reserve,
608 swap_elements = igraph_graph_list_swap_elements,
609 push_back_copy = igraph_graph_list_push_back_copy
610);
611
612macro_rules! impl_vec_list_order {
617 (
618 $ty:ident, $item:ident,
619 sort = $sort:ident, sort_ind = $sort_ind:ident, dedup = $dedup:ident,
620 lex_cmp = $lex_cmp:ident, colex_cmp = $colex_cmp:ident, all_e = $all_e:ident
621 ) => {
622 impl $ty {
623 pub fn sort(&mut self) {
628 if !self.is_empty() {
629 unsafe { $sort(self, Some($lex_cmp)) };
630 }
631 }
632
633 pub fn sort_colex(&mut self) {
637 if !self.is_empty() {
638 unsafe { $sort(self, Some($colex_cmp)) };
639 }
640 }
641
642 pub fn sort_ind(&self) -> Vec<igraph_int_t> {
646 if self.is_empty() {
647 return Vec::new();
648 }
649 let mut ind = crate::vector::VectorInt::new();
650 let mut copy = self.clone();
653 crate::error::check(unsafe { $sort_ind(&mut copy, &mut ind, Some($lex_cmp)) })
654 .expect("igraph failed to sort a list");
655 ind.into()
656 }
657
658 pub fn dedup(&mut self) {
663 if !self.is_empty() {
664 unsafe { $dedup(self, Some($all_e)) };
665 }
666 }
667 }
668 };
669}
670
671impl_vec_list_order!(
672 igraph_vector_int_list_t,
673 igraph_vector_int_t,
674 sort = igraph_vector_int_list_sort,
675 sort_ind = igraph_vector_int_list_sort_ind,
676 dedup = igraph_vector_int_list_remove_consecutive_duplicates,
677 lex_cmp = igraph_vector_int_lex_cmp,
678 colex_cmp = igraph_vector_int_colex_cmp,
679 all_e = igraph_vector_int_all_e
680);
681impl_vec_list_order!(
682 igraph_vector_list_t,
683 igraph_vector_t,
684 sort = igraph_vector_list_sort,
685 sort_ind = igraph_vector_list_sort_ind,
686 dedup = igraph_vector_list_remove_consecutive_duplicates,
687 lex_cmp = igraph_vector_lex_cmp,
688 colex_cmp = igraph_vector_colex_cmp,
689 all_e = igraph_vector_all_e
690);
691
692impl igraph_graph_list_t {
693 pub fn set_directed(&mut self, directed: bool) {
697 self.directed = directed;
700 }
701}
702
703impl fmt::Display for igraph_vector_int_list_t {
705 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
706 f.debug_list()
707 .entries(self.iter().map(|v| v.as_slice()))
708 .finish()
709 }
710}
711
712impl fmt::Display for igraph_vector_list_t {
713 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
714 f.debug_list()
715 .entries(self.iter().map(|v| v.as_slice()))
716 .finish()
717 }
718}