1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, marker::PhantomData, mem, ptr};
4
5use crate::translate::*;
6
7// rustdoc-stripper-ignore-next
8/// Minimum size of the `Slice` allocation in bytes.
9const MIN_SIZE: usize = 256;
10
11// rustdoc-stripper-ignore-next
12/// Slice of elements of type `T` allocated by the GLib allocator.
13///
14/// This can be used like a `&[T]`, `&mut [T]` and `Vec<T>`.
15pub struct Slice<T: TransparentType> {
16 ptr: ptr::NonNull<T::GlibType>,
17 len: usize,
18 capacity: usize,
19}
20
21unsafe impl<T: TransparentType + Send> Send for Slice<T> {}
22
23unsafe impl<T: TransparentType + Sync> Sync for Slice<T> {}
24
25impl<T: fmt::Debug + TransparentType> fmt::Debug for Slice<T> {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 self.as_slice().fmt(f)
28 }
29}
30
31impl<T: PartialEq + TransparentType> PartialEq for Slice<T> {
32 #[inline]
33 fn eq(&self, other: &Self) -> bool {
34 self.as_slice() == other.as_slice()
35 }
36}
37
38impl<T: Eq + TransparentType> Eq for Slice<T> {}
39
40impl<T: PartialOrd + TransparentType> PartialOrd for Slice<T> {
41 #[inline]
42 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
43 self.as_slice().partial_cmp(other.as_slice())
44 }
45}
46
47impl<T: Ord + TransparentType> Ord for Slice<T> {
48 #[inline]
49 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
50 self.as_slice().cmp(other.as_slice())
51 }
52}
53
54impl<T: std::hash::Hash + TransparentType> std::hash::Hash for Slice<T> {
55 #[inline]
56 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
57 self.as_slice().hash(state)
58 }
59}
60
61impl<T: PartialEq + TransparentType> PartialEq<[T]> for Slice<T> {
62 #[inline]
63 fn eq(&self, other: &[T]) -> bool {
64 self.as_slice() == other
65 }
66}
67
68impl<T: PartialEq + TransparentType> PartialEq<Slice<T>> for [T] {
69 #[inline]
70 fn eq(&self, other: &Slice<T>) -> bool {
71 self == other.as_slice()
72 }
73}
74
75impl<T: TransparentType> Drop for Slice<T> {
76 #[inline]
77 fn drop(&mut self) {
78 unsafe {
79 if mem::needs_drop::<T>() {
80 for i: usize in 0..self.len {
81 ptr::drop_in_place::<T>(self.ptr.as_ptr().add(count:i) as *mut T);
82 }
83 }
84
85 if self.capacity != 0 {
86 ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
87 }
88 }
89 }
90}
91
92impl<T: TransparentType> AsRef<[T]> for Slice<T> {
93 #[inline]
94 fn as_ref(&self) -> &[T] {
95 self.as_slice()
96 }
97}
98
99impl<T: TransparentType> AsMut<[T]> for Slice<T> {
100 #[inline]
101 fn as_mut(&mut self) -> &mut [T] {
102 self.as_mut_slice()
103 }
104}
105
106impl<T: TransparentType> std::borrow::Borrow<[T]> for Slice<T> {
107 #[inline]
108 fn borrow(&self) -> &[T] {
109 self.as_slice()
110 }
111}
112
113impl<T: TransparentType> std::borrow::BorrowMut<[T]> for Slice<T> {
114 #[inline]
115 fn borrow_mut(&mut self) -> &mut [T] {
116 self.as_mut_slice()
117 }
118}
119
120impl<T: TransparentType> std::ops::Deref for Slice<T> {
121 type Target = [T];
122
123 #[inline]
124 fn deref(&self) -> &[T] {
125 self.as_slice()
126 }
127}
128
129impl<T: TransparentType> std::ops::DerefMut for Slice<T> {
130 #[inline]
131 fn deref_mut(&mut self) -> &mut [T] {
132 self.as_mut_slice()
133 }
134}
135
136impl<T: TransparentType> Default for Slice<T> {
137 #[inline]
138 fn default() -> Self {
139 Self::new()
140 }
141}
142
143impl<T: TransparentType> std::iter::Extend<T> for Slice<T> {
144 #[inline]
145 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
146 let iter: ::IntoIter = iter.into_iter();
147 self.reserve(additional:iter.size_hint().0);
148
149 for item: T in iter {
150 self.push(item);
151 }
152 }
153}
154
155impl<'a, T: TransparentType + 'a> std::iter::Extend<&'a T> for Slice<T> {
156 #[inline]
157 fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
158 let iter: ::IntoIter = iter.into_iter();
159 self.reserve(additional:iter.size_hint().0);
160
161 for item: &T in iter {
162 self.push(item.clone());
163 }
164 }
165}
166
167impl<T: TransparentType> std::iter::FromIterator<T> for Slice<T> {
168 #[inline]
169 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
170 let iter: ::IntoIter = iter.into_iter();
171 let mut s: Slice = Self::with_capacity(iter.size_hint().0);
172 for item: T in iter {
173 s.push(item);
174 }
175 s
176 }
177}
178
179impl<'a, T: TransparentType> std::iter::IntoIterator for &'a Slice<T> {
180 type Item = &'a T;
181 type IntoIter = std::slice::Iter<'a, T>;
182
183 #[inline]
184 fn into_iter(self) -> Self::IntoIter {
185 self.as_slice().iter()
186 }
187}
188
189impl<'a, T: TransparentType> std::iter::IntoIterator for &'a mut Slice<T> {
190 type Item = &'a mut T;
191 type IntoIter = std::slice::IterMut<'a, T>;
192
193 #[inline]
194 fn into_iter(self) -> Self::IntoIter {
195 self.as_mut_slice().iter_mut()
196 }
197}
198
199impl<T: TransparentType> std::iter::IntoIterator for Slice<T> {
200 type Item = T;
201 type IntoIter = IntoIter<T>;
202
203 #[inline]
204 fn into_iter(self) -> Self::IntoIter {
205 IntoIter::new(self)
206 }
207}
208
209pub struct IntoIter<T: TransparentType> {
210 ptr: ptr::NonNull<T::GlibType>,
211 idx: ptr::NonNull<T::GlibType>,
212 len: usize,
213 empty: bool,
214}
215
216impl<T: TransparentType> IntoIter<T> {
217 #[inline]
218 fn new(slice: Slice<T>) -> Self {
219 let slice = mem::ManuallyDrop::new(slice);
220 IntoIter {
221 ptr: slice.ptr,
222 idx: slice.ptr,
223 len: slice.len,
224 empty: slice.capacity == 0,
225 }
226 }
227
228 // rustdoc-stripper-ignore-next
229 /// Returns the remaining items as slice.
230 #[inline]
231 pub fn as_slice(&self) -> &[T] {
232 unsafe {
233 if self.len == 0 {
234 &[]
235 } else {
236 std::slice::from_raw_parts(self.idx.as_ptr() as *mut T, self.len)
237 }
238 }
239 }
240
241 // rustdoc-stripper-ignore-next
242 /// Returns the remaining items as mutable slice.
243 #[inline]
244 pub fn as_mut_slice(&mut self) -> &mut [T] {
245 unsafe {
246 if self.len == 0 {
247 &mut []
248 } else {
249 std::slice::from_raw_parts_mut(self.idx.as_ptr() as *mut T, self.len)
250 }
251 }
252 }
253}
254
255impl<T: TransparentType> Drop for IntoIter<T> {
256 #[inline]
257 fn drop(&mut self) {
258 unsafe {
259 if mem::needs_drop::<T>() {
260 for i: usize in 0..self.len {
261 ptr::drop_in_place::<T>(self.idx.as_ptr().add(count:i) as *mut T);
262 }
263 }
264
265 if !self.empty {
266 ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
267 }
268 }
269 }
270}
271
272impl<T: TransparentType> Iterator for IntoIter<T> {
273 type Item = T;
274
275 #[inline]
276 fn next(&mut self) -> Option<Self::Item> {
277 if self.len == 0 {
278 return None;
279 }
280
281 unsafe {
282 let p = self.idx.as_ptr();
283 self.len -= 1;
284 self.idx = ptr::NonNull::new_unchecked(p.add(1));
285 Some(ptr::read(p as *mut T))
286 }
287 }
288
289 #[inline]
290 fn size_hint(&self) -> (usize, Option<usize>) {
291 (self.len, Some(self.len))
292 }
293
294 #[inline]
295 fn count(self) -> usize {
296 self.len
297 }
298
299 #[inline]
300 fn last(mut self) -> Option<T> {
301 if self.len == 0 {
302 None
303 } else {
304 self.len -= 1;
305 Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) })
306 }
307 }
308}
309
310impl<T: TransparentType> DoubleEndedIterator for IntoIter<T> {
311 #[inline]
312 fn next_back(&mut self) -> Option<T> {
313 if self.len == 0 {
314 None
315 } else {
316 self.len -= 1;
317 Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) })
318 }
319 }
320}
321
322impl<T: TransparentType> ExactSizeIterator for IntoIter<T> {}
323
324impl<T: TransparentType> std::iter::FusedIterator for IntoIter<T> {}
325
326impl<T: TransparentType> From<Slice<T>> for Vec<T> {
327 #[inline]
328 fn from(mut value: Slice<T>) -> Self {
329 unsafe {
330 let mut s: Vec = Vec::with_capacity(value.len);
331 ptr::copy_nonoverlapping(src:value.ptr.as_ptr() as *const T, dst:s.as_mut_ptr(), count:value.len);
332 s.set_len(new_len:value.len);
333 value.len = 0;
334 s
335 }
336 }
337}
338
339impl<T: TransparentType> From<Vec<T>> for Slice<T> {
340 #[inline]
341 fn from(mut value: Vec<T>) -> Self {
342 unsafe {
343 let mut s: Slice = Self::with_capacity(value.len());
344 ptr::copy_nonoverlapping(src:value.as_ptr(), dst:s.ptr.as_ptr() as *mut T, count:value.len());
345 s.len = value.len();
346 value.set_len(new_len:0);
347 s
348 }
349 }
350}
351
352impl<T: TransparentType, const N: usize> From<[T; N]> for Slice<T> {
353 #[inline]
354 fn from(value: [T; N]) -> Self {
355 unsafe {
356 let value: ManuallyDrop<[T; N]> = mem::ManuallyDrop::new(value);
357 let len: usize = value.len();
358 let mut s: Slice = Self::with_capacity(len);
359 ptr::copy_nonoverlapping(src:value.as_ptr(), dst:s.ptr.as_ptr() as *mut T, count:len);
360 s.len = len;
361 s
362 }
363 }
364}
365
366impl<'a, T: TransparentType> From<&'a [T]> for Slice<T> {
367 #[inline]
368 fn from(value: &'a [T]) -> Self {
369 unsafe {
370 let mut s: Slice = Self::with_capacity(value.len());
371 for (i: usize, item: &T) in value.iter().enumerate() {
372 ptr::write(dst:s.ptr.as_ptr().add(i) as *mut T, src:item.clone());
373 }
374 s.len = value.len();
375 s
376 }
377 }
378}
379
380impl<'a, T: TransparentType> From<&'a [&'a T]> for Slice<T> {
381 #[inline]
382 fn from(value: &'a [&'a T]) -> Self {
383 unsafe {
384 let mut s: Slice = Self::with_capacity(value.len());
385 for (i: usize, item: &&T) in value.iter().enumerate() {
386 ptr::write(dst:s.ptr.as_ptr().add(i) as *mut T, (*item).clone());
387 }
388 s.len = value.len();
389 s
390 }
391 }
392}
393
394impl<T: TransparentType> Clone for Slice<T> {
395 #[inline]
396 fn clone(&self) -> Self {
397 Self::from(self.as_slice())
398 }
399}
400
401impl<T: TransparentType> Slice<T> {
402 // rustdoc-stripper-ignore-next
403 /// Borrows a C array.
404 #[inline]
405 pub unsafe fn from_glib_borrow_num<'a>(ptr: *const T::GlibType, len: usize) -> &'a [T] {
406 debug_assert!(!ptr.is_null() || len == 0);
407
408 if len == 0 {
409 &[]
410 } else {
411 std::slice::from_raw_parts(ptr as *const T, len)
412 }
413 }
414
415 // rustdoc-stripper-ignore-next
416 /// Borrows a mutable C array.
417 #[inline]
418 pub unsafe fn from_glib_borrow_num_mut<'a>(ptr: *mut T::GlibType, len: usize) -> &'a mut [T] {
419 debug_assert!(!ptr.is_null() || len == 0);
420
421 if len == 0 {
422 &mut []
423 } else {
424 std::slice::from_raw_parts_mut(ptr as *mut T, len)
425 }
426 }
427
428 // rustdoc-stripper-ignore-next
429 /// Borrows a C array of references.
430 #[inline]
431 pub unsafe fn from_glib_ptr_borrow_num<'a>(
432 ptr: *const *const T::GlibType,
433 len: usize,
434 ) -> &'a [&'a T] {
435 debug_assert!(!ptr.is_null() || len == 0);
436
437 if len == 0 {
438 &[]
439 } else {
440 std::slice::from_raw_parts(ptr as *const &T, len)
441 }
442 }
443
444 // rustdoc-stripper-ignore-next
445 /// Borrows a mutable C array.
446 #[inline]
447 pub unsafe fn from_glib_ptr_borrow_num_mut<'a>(
448 ptr: *mut *mut T::GlibType,
449 len: usize,
450 ) -> &'a mut [&'a mut T] {
451 debug_assert!(!ptr.is_null() || len == 0);
452
453 if len == 0 {
454 &mut []
455 } else {
456 std::slice::from_raw_parts_mut(ptr as *mut &mut T, len)
457 }
458 }
459
460 // rustdoc-stripper-ignore-next
461 /// Create a new `Slice` around a C array.
462 #[inline]
463 pub unsafe fn from_glib_none_num(ptr: *const T::GlibType, len: usize) -> Self {
464 debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
465 debug_assert!(!ptr.is_null() || len == 0);
466
467 if len == 0 {
468 Slice::default()
469 } else {
470 // Need to fully copy the array here.
471 let s = Self::from_glib_borrow_num(ptr, len);
472 Self::from(s)
473 }
474 }
475
476 // rustdoc-stripper-ignore-next
477 /// Create a new `Slice` around a C array.
478 #[inline]
479 pub unsafe fn from_glib_container_num(ptr: *mut T::GlibType, len: usize) -> Self {
480 debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
481 debug_assert!(!ptr.is_null() || len == 0);
482
483 if len == 0 {
484 ffi::g_free(ptr as ffi::gpointer);
485 Slice::default()
486 } else {
487 // Need to clone every item because we don't own it here but only
488 // if this type requires explicit drop.
489 if mem::needs_drop::<T>() {
490 for i in 0..len {
491 let p = ptr.add(i) as *mut T;
492 let clone: T = (*p).clone();
493 ptr::write(p, clone);
494 }
495 }
496
497 // And now it can be handled exactly the same as `from_glib_full_num()`.
498 Self::from_glib_full_num(ptr, len)
499 }
500 }
501
502 // rustdoc-stripper-ignore-next
503 /// Create a new `Slice` around a C array.
504 #[inline]
505 pub unsafe fn from_glib_full_num(ptr: *mut T::GlibType, len: usize) -> Self {
506 debug_assert_eq!(mem::size_of::<T>(), mem::size_of::<T::GlibType>());
507 debug_assert!(!ptr.is_null() || len == 0);
508
509 if len == 0 {
510 ffi::g_free(ptr as ffi::gpointer);
511 Slice::default()
512 } else {
513 Slice {
514 ptr: ptr::NonNull::new_unchecked(ptr),
515 len,
516 capacity: len,
517 }
518 }
519 }
520
521 // rustdoc-stripper-ignore-next
522 /// Creates a new empty slice.
523 #[inline]
524 pub fn new() -> Self {
525 Slice {
526 ptr: ptr::NonNull::dangling(),
527 len: 0,
528 capacity: 0,
529 }
530 }
531
532 // rustdoc-stripper-ignore-next
533 /// Creates a new empty slice with the given capacity.
534 #[inline]
535 pub fn with_capacity(capacity: usize) -> Self {
536 let mut s = Self::new();
537 s.reserve(capacity);
538 s
539 }
540
541 // rustdoc-stripper-ignore-next
542 /// Returns the underlying pointer.
543 ///
544 /// This is guaranteed to be `NULL`-terminated.
545 #[inline]
546 pub fn as_ptr(&self) -> *const T::GlibType {
547 if self.len == 0 {
548 ptr::null()
549 } else {
550 self.ptr.as_ptr()
551 }
552 }
553
554 // rustdoc-stripper-ignore-next
555 /// Returns the underlying pointer.
556 ///
557 /// This is guaranteed to be `NULL`-terminated.
558 #[inline]
559 pub fn as_mut_ptr(&mut self) -> *mut T::GlibType {
560 if self.len == 0 {
561 ptr::null_mut()
562 } else {
563 self.ptr.as_ptr()
564 }
565 }
566
567 // rustdoc-stripper-ignore-next
568 /// Consumes the slice and returns the underlying pointer.
569 ///
570 /// This is guaranteed to be `NULL`-terminated.
571 #[inline]
572 pub fn into_raw(mut self) -> *mut T::GlibType {
573 if self.len == 0 {
574 ptr::null_mut()
575 } else {
576 self.len = 0;
577 self.capacity = 0;
578 self.ptr.as_ptr()
579 }
580 }
581
582 // rustdoc-stripper-ignore-next
583 /// Gets the length of the slice.
584 #[inline]
585 pub fn len(&self) -> usize {
586 self.len
587 }
588
589 // rustdoc-stripper-ignore-next
590 /// Returns `true` if the slice is empty.
591 #[inline]
592 pub fn is_empty(&self) -> bool {
593 self.len == 0
594 }
595
596 // rustdoc-stripper-ignore-next
597 /// Returns the capacity of the slice.
598 #[inline]
599 pub fn capacity(&self) -> usize {
600 self.capacity
601 }
602
603 // rustdoc-stripper-ignore-next
604 /// Sets the length of the slice to `len`.
605 ///
606 /// # SAFETY
607 ///
608 /// There must be at least `len` valid items.
609 pub unsafe fn set_len(&mut self, len: usize) {
610 self.len = len;
611 }
612
613 // rustdoc-stripper-ignore-next
614 /// Reserves at least this much additional capacity.
615 pub fn reserve(&mut self, additional: usize) {
616 // Nothing new to reserve as there's still enough space
617 if self.len + additional <= self.capacity {
618 return;
619 }
620
621 let new_capacity = usize::next_power_of_two(std::cmp::max(
622 self.len + additional,
623 MIN_SIZE / mem::size_of::<T>(),
624 ));
625 assert_ne!(new_capacity, 0);
626 assert!(new_capacity > self.capacity);
627
628 unsafe {
629 let ptr = if self.capacity == 0 {
630 ptr::null_mut()
631 } else {
632 self.ptr.as_ptr() as *mut _
633 };
634 let new_ptr =
635 ffi::g_realloc(ptr, mem::size_of::<T>().checked_mul(new_capacity).unwrap())
636 as *mut T::GlibType;
637 self.ptr = ptr::NonNull::new_unchecked(new_ptr);
638 self.capacity = new_capacity;
639 }
640 }
641
642 // rustdoc-stripper-ignore-next
643 /// Borrows this slice as a `&[T]`.
644 #[inline]
645 pub fn as_slice(&self) -> &[T] {
646 unsafe {
647 if self.len == 0 {
648 &[]
649 } else {
650 std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len)
651 }
652 }
653 }
654
655 // rustdoc-stripper-ignore-next
656 /// Borrows this slice as a `&mut [T]`.
657 #[inline]
658 pub fn as_mut_slice(&mut self) -> &mut [T] {
659 unsafe {
660 if self.len == 0 {
661 &mut []
662 } else {
663 std::slice::from_raw_parts_mut(self.ptr.as_ptr() as *mut T, self.len)
664 }
665 }
666 }
667
668 // rustdoc-stripper-ignore-next
669 /// Removes all items from the slice.
670 #[inline]
671 pub fn clear(&mut self) {
672 unsafe {
673 if mem::needs_drop::<T>() {
674 for i in 0..self.len {
675 ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T);
676 }
677 }
678
679 self.len = 0;
680 }
681 }
682
683 // rustdoc-stripper-ignore-next
684 /// Clones and appends all elements in `slice` to the slice.
685 #[inline]
686 pub fn extend_from_slice(&mut self, other: &[T]) {
687 // Nothing new to reserve as there's still enough space
688 if self.len + other.len() > self.capacity {
689 self.reserve(other.len());
690 }
691
692 unsafe {
693 for item in other {
694 ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item.clone());
695 self.len += 1;
696 }
697 }
698 }
699
700 // rustdoc-stripper-ignore-next
701 /// Inserts `item` at position `index` of the slice, shifting all elements after it to the
702 /// right.
703 #[inline]
704 #[allow(clippy::int_plus_one)]
705 pub fn insert(&mut self, index: usize, item: T) {
706 assert!(index <= self.len);
707
708 // Nothing new to reserve as there's still enough space
709 if self.len + 1 > self.capacity {
710 self.reserve(1);
711 }
712
713 unsafe {
714 if index == self.len {
715 ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item);
716 } else {
717 let p = self.ptr.as_ptr().add(index);
718 ptr::copy(p, p.add(1), self.len - index);
719 ptr::write(self.ptr.as_ptr().add(index) as *mut T, item);
720 }
721
722 self.len += 1;
723 }
724 }
725
726 // rustdoc-stripper-ignore-next
727 /// Pushes `item` to the end of the slice.
728 #[inline]
729 #[allow(clippy::int_plus_one)]
730 pub fn push(&mut self, item: T) {
731 // Nothing new to reserve as there's still enough space
732 if self.len + 1 > self.capacity {
733 self.reserve(1);
734 }
735
736 unsafe {
737 ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item);
738 self.len += 1;
739 }
740 }
741
742 // rustdoc-stripper-ignore-next
743 /// Removes item from position `index` of the slice, shifting all elements after it to the
744 /// left.
745 #[inline]
746 pub fn remove(&mut self, index: usize) -> T {
747 assert!(index < self.len);
748
749 unsafe {
750 let p = self.ptr.as_ptr().add(index);
751 let item = ptr::read(p as *mut T);
752 ptr::copy(p.add(1), p, self.len - index - 1);
753
754 self.len -= 1;
755
756 item
757 }
758 }
759
760 // rustdoc-stripper-ignore-next
761 /// Removes the last item of the slice and returns it.
762 #[inline]
763 pub fn pop(&mut self) -> Option<T> {
764 if self.len == 0 {
765 return None;
766 }
767
768 unsafe {
769 self.len -= 1;
770 let p = self.ptr.as_ptr().add(self.len);
771 let item = ptr::read(p as *mut T);
772
773 Some(item)
774 }
775 }
776
777 // rustdoc-stripper-ignore-next
778 /// Shortens the slice by keeping the last `len` items.
779 ///
780 /// If there are fewer than `len` items then this has no effect.
781 #[inline]
782 pub fn truncate(&mut self, len: usize) {
783 if self.len <= len {
784 return;
785 }
786
787 unsafe {
788 while self.len > len {
789 self.len -= 1;
790 let p = self.ptr.as_ptr().add(self.len);
791 ptr::drop_in_place::<T>(p as *mut T);
792 }
793 }
794 }
795}
796
797impl<T: TransparentType + 'static> FromGlibContainer<T::GlibType, *mut T::GlibType> for Slice<T> {
798 unsafe fn from_glib_none_num(ptr: *mut T::GlibType, num: usize) -> Self {
799 Self::from_glib_none_num(ptr, len:num)
800 }
801
802 #[inline]
803 unsafe fn from_glib_container_num(ptr: *mut T::GlibType, num: usize) -> Self {
804 Self::from_glib_container_num(ptr, len:num)
805 }
806
807 #[inline]
808 unsafe fn from_glib_full_num(ptr: *mut T::GlibType, num: usize) -> Self {
809 Self::from_glib_full_num(ptr, len:num)
810 }
811}
812
813impl<T: TransparentType + 'static> FromGlibContainer<T::GlibType, *const T::GlibType> for Slice<T> {
814 unsafe fn from_glib_none_num(ptr: *const T::GlibType, num: usize) -> Self {
815 Self::from_glib_none_num(ptr, len:num)
816 }
817
818 unsafe fn from_glib_container_num(_ptr: *const T::GlibType, _num: usize) -> Self {
819 unimplemented!();
820 }
821
822 unsafe fn from_glib_full_num(_ptr: *const T::GlibType, _num: usize) -> Self {
823 unimplemented!();
824 }
825}
826
827impl<'a, T: TransparentType + 'a> ToGlibPtr<'a, *mut T::GlibType> for Slice<T> {
828 type Storage = PhantomData<&'a Self>;
829
830 #[inline]
831 fn to_glib_none(&'a self) -> Stash<'a, *mut T::GlibType, Self> {
832 Stash(self.as_ptr() as *mut _, PhantomData)
833 }
834
835 #[inline]
836 fn to_glib_container(&'a self) -> Stash<'a, *mut T::GlibType, Self> {
837 unsafe {
838 let ptr: *mut ::GlibType = ffi::g_malloc(n_bytes:mem::size_of::<T>().checked_mul(self.len()).unwrap())
839 as *mut T::GlibType;
840 ptr::copy_nonoverlapping(self.as_ptr(), dst:ptr, self.len());
841 Stash(ptr, PhantomData)
842 }
843 }
844
845 #[inline]
846 fn to_glib_full(&self) -> *mut T::GlibType {
847 self.clone().into_raw()
848 }
849}
850
851impl<'a, T: TransparentType + 'a> ToGlibPtr<'a, *const T::GlibType> for Slice<T> {
852 type Storage = PhantomData<&'a Self>;
853
854 #[inline]
855 fn to_glib_none(&'a self) -> Stash<'a, *const T::GlibType, Self> {
856 Stash(self.as_ptr(), PhantomData)
857 }
858}
859
860impl<'a, T: TransparentType + 'a> ToGlibPtrMut<'a, *mut T::GlibType> for Slice<T> {
861 type Storage = PhantomData<&'a mut Self>;
862
863 #[inline]
864 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut T::GlibType, Self> {
865 StashMut(self.as_mut_ptr(), PhantomData)
866 }
867}
868
869impl<T: TransparentType + 'static> IntoGlibPtr<*mut T::GlibType> for Slice<T> {
870 #[inline]
871 unsafe fn into_glib_ptr(self) -> *mut T::GlibType {
872 self.into_raw()
873 }
874}
875
876impl<T: TransparentPtrType> From<super::PtrSlice<T>> for Slice<T> {
877 fn from(value: super::PtrSlice<T>) -> Self {
878 let len: usize = value.len();
879 let capacity: usize = value.capacity();
880 unsafe {
881 let ptr: *mut ::GlibType = value.into_raw();
882 Slice::<T> {
883 ptr: ptr::NonNull::new_unchecked(ptr),
884 len,
885 capacity,
886 }
887 }
888 }
889}
890
891#[cfg(test)]
892mod test {
893 use super::*;
894
895 #[test]
896 fn test_from_glib_full() {
897 let items = [
898 crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
899 crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
900 crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
901 crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap(),
902 ];
903
904 let slice = unsafe {
905 let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut ffi::GDate;
906 ptr::write(ptr.add(0), *items[0].to_glib_none().0);
907 ptr::write(ptr.add(1), *items[1].to_glib_none().0);
908 ptr::write(ptr.add(2), *items[2].to_glib_none().0);
909 ptr::write(ptr.add(3), *items[3].to_glib_none().0);
910
911 Slice::<crate::Date>::from_glib_full_num(ptr, 4)
912 };
913
914 assert_eq!(&items[..], &*slice);
915 }
916
917 #[test]
918 fn test_from_glib_none() {
919 let items = [
920 crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
921 crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
922 crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
923 crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap(),
924 ];
925
926 let slice = unsafe {
927 Slice::<crate::Date>::from_glib_none_num(items.as_ptr() as *const ffi::GDate, 4)
928 };
929
930 assert_eq!(&items[..], &*slice);
931 }
932
933 #[test]
934 fn test_safe_api() {
935 let items = [
936 crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
937 crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
938 crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
939 ];
940
941 let mut slice = Slice::from(&items[..]);
942 assert_eq!(slice.len(), 3);
943 slice.push(crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap());
944 assert_eq!(slice.len(), 4);
945
946 for (a, b) in Iterator::zip(items.iter(), slice.iter()) {
947 assert_eq!(a, b);
948 }
949 assert_eq!(
950 (slice[3].day(), slice[3].month(), slice[3].year()),
951 (23, crate::DateMonth::November, 2021)
952 );
953
954 let vec = Vec::from(slice);
955 assert_eq!(vec.len(), 4);
956 for (a, b) in Iterator::zip(items.iter(), vec.iter()) {
957 assert_eq!(a, b);
958 }
959 assert_eq!(
960 (vec[3].day(), vec[3].month(), vec[3].year()),
961 (23, crate::DateMonth::November, 2021)
962 );
963
964 let mut slice = Slice::from(vec);
965 assert_eq!(slice.len(), 4);
966 let e = slice.pop().unwrap();
967 assert_eq!(
968 (e.day(), e.month(), e.year()),
969 (23, crate::DateMonth::November, 2021)
970 );
971 assert_eq!(slice.len(), 3);
972 slice.insert(2, e);
973 assert_eq!(slice.len(), 4);
974 assert_eq!(slice[0].day(), 20);
975 assert_eq!(slice[1].day(), 21);
976 assert_eq!(slice[2].day(), 23);
977 assert_eq!(slice[3].day(), 22);
978 let e = slice.remove(2);
979 assert_eq!(
980 (e.day(), e.month(), e.year()),
981 (23, crate::DateMonth::November, 2021)
982 );
983 assert_eq!(slice.len(), 3);
984 slice.push(e);
985 assert_eq!(slice.len(), 4);
986
987 for (a, b) in Iterator::zip(items.iter(), slice.into_iter()) {
988 assert_eq!(a, &b);
989 }
990 }
991}
992