1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{fmt, marker::PhantomData, mem, ptr}; |
4 | |
5 | use crate::{ffi, translate::*}; |
6 | |
7 | // rustdoc-stripper-ignore-next |
8 | /// Minimum size of the `PtrSlice` allocation. |
9 | const MIN_SIZE: usize = 16; |
10 | |
11 | // rustdoc-stripper-ignore-next |
12 | /// Slice of elements of type `T` allocated by the GLib allocator. |
13 | /// |
14 | /// The underlying memory is always `NULL`-terminated. [`Slice<T>`](crate::collections::slice::Slice) |
15 | /// can be used for a non-`NULL`-terminated slice. |
16 | /// |
17 | /// This can be used like a `&[T]`, `&mut [T]` and `Vec<T>`. |
18 | pub struct PtrSlice<T: TransparentPtrType> { |
19 | ptr: ptr::NonNull<<T as GlibPtrDefault>::GlibType>, |
20 | // rustdoc-stripper-ignore-next |
21 | /// Length without the `NULL`-terminator. |
22 | len: usize, |
23 | // rustdoc-stripper-ignore-next |
24 | /// Capacity **with** the `NULL`-terminator, i.e. the actual allocation size. |
25 | capacity: usize, |
26 | } |
27 | |
28 | impl<T: fmt::Debug + TransparentPtrType> fmt::Debug for PtrSlice<T> { |
29 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
30 | self.as_slice().fmt(f) |
31 | } |
32 | } |
33 | |
34 | unsafe impl<T: Send + TransparentPtrType> Send for PtrSlice<T> {} |
35 | |
36 | unsafe impl<T: Sync + TransparentPtrType> Sync for PtrSlice<T> {} |
37 | |
38 | impl<T: PartialEq + TransparentPtrType> PartialEq for PtrSlice<T> { |
39 | #[inline ] |
40 | fn eq(&self, other: &Self) -> bool { |
41 | self.as_slice() == other.as_slice() |
42 | } |
43 | } |
44 | |
45 | impl<T: Eq + TransparentPtrType> Eq for PtrSlice<T> {} |
46 | |
47 | impl<T: PartialOrd + TransparentPtrType> PartialOrd for PtrSlice<T> { |
48 | #[inline ] |
49 | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
50 | self.as_slice().partial_cmp(other.as_slice()) |
51 | } |
52 | } |
53 | |
54 | impl<T: Ord + TransparentPtrType> Ord for PtrSlice<T> { |
55 | #[inline ] |
56 | fn cmp(&self, other: &Self) -> std::cmp::Ordering { |
57 | self.as_slice().cmp(other.as_slice()) |
58 | } |
59 | } |
60 | |
61 | impl<T: std::hash::Hash + TransparentPtrType> std::hash::Hash for PtrSlice<T> { |
62 | #[inline ] |
63 | fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
64 | self.as_slice().hash(state) |
65 | } |
66 | } |
67 | |
68 | impl<T: PartialEq + TransparentPtrType> PartialEq<[T]> for PtrSlice<T> { |
69 | #[inline ] |
70 | fn eq(&self, other: &[T]) -> bool { |
71 | self.as_slice() == other |
72 | } |
73 | } |
74 | |
75 | impl<T: PartialEq + TransparentPtrType> PartialEq<PtrSlice<T>> for [T] { |
76 | #[inline ] |
77 | fn eq(&self, other: &PtrSlice<T>) -> bool { |
78 | self == other.as_slice() |
79 | } |
80 | } |
81 | |
82 | impl<T: TransparentPtrType> Drop for PtrSlice<T> { |
83 | #[inline ] |
84 | fn drop(&mut self) { |
85 | unsafe { |
86 | if mem::needs_drop::<T>() { |
87 | for i: usize in 0..self.len { |
88 | ptr::drop_in_place::<T>(self.ptr.as_ptr().add(count:i) as *mut T); |
89 | } |
90 | } |
91 | |
92 | if self.capacity != 0 { |
93 | ffi::g_free(self.ptr.as_ptr() as ffi::gpointer); |
94 | } |
95 | } |
96 | } |
97 | } |
98 | |
99 | impl<T: TransparentPtrType> AsRef<[T]> for PtrSlice<T> { |
100 | #[inline ] |
101 | fn as_ref(&self) -> &[T] { |
102 | self.as_slice() |
103 | } |
104 | } |
105 | |
106 | impl<T: TransparentPtrType> AsMut<[T]> for PtrSlice<T> { |
107 | #[inline ] |
108 | fn as_mut(&mut self) -> &mut [T] { |
109 | self.as_mut_slice() |
110 | } |
111 | } |
112 | |
113 | impl<T: TransparentPtrType> std::borrow::Borrow<[T]> for PtrSlice<T> { |
114 | #[inline ] |
115 | fn borrow(&self) -> &[T] { |
116 | self.as_slice() |
117 | } |
118 | } |
119 | |
120 | impl<T: TransparentPtrType> std::borrow::BorrowMut<[T]> for PtrSlice<T> { |
121 | #[inline ] |
122 | fn borrow_mut(&mut self) -> &mut [T] { |
123 | self.as_mut_slice() |
124 | } |
125 | } |
126 | |
127 | impl<T: TransparentPtrType> std::ops::Deref for PtrSlice<T> { |
128 | type Target = [T]; |
129 | |
130 | #[inline ] |
131 | fn deref(&self) -> &[T] { |
132 | self.as_slice() |
133 | } |
134 | } |
135 | |
136 | impl<T: TransparentPtrType> std::ops::DerefMut for PtrSlice<T> { |
137 | #[inline ] |
138 | fn deref_mut(&mut self) -> &mut [T] { |
139 | self.as_mut_slice() |
140 | } |
141 | } |
142 | |
143 | impl<T: TransparentPtrType> Default for PtrSlice<T> { |
144 | #[inline ] |
145 | fn default() -> Self { |
146 | Self::new() |
147 | } |
148 | } |
149 | |
150 | impl<T: TransparentPtrType> std::iter::Extend<T> for PtrSlice<T> { |
151 | #[inline ] |
152 | fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { |
153 | let iter: ::IntoIter = iter.into_iter(); |
154 | self.reserve(additional:iter.size_hint().0); |
155 | |
156 | for item: T in iter { |
157 | self.push(item); |
158 | } |
159 | } |
160 | } |
161 | |
162 | impl<'a, T: TransparentPtrType + 'a> std::iter::Extend<&'a T> for PtrSlice<T> { |
163 | #[inline ] |
164 | fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { |
165 | let iter: ::IntoIter = iter.into_iter(); |
166 | self.reserve(additional:iter.size_hint().0); |
167 | |
168 | for item: &'a T in iter { |
169 | self.push(item.clone()); |
170 | } |
171 | } |
172 | } |
173 | |
174 | impl<T: TransparentPtrType> std::iter::FromIterator<T> for PtrSlice<T> { |
175 | #[inline ] |
176 | fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { |
177 | let iter: ::IntoIter = iter.into_iter(); |
178 | let mut s: PtrSlice = Self::with_capacity(iter.size_hint().0); |
179 | for item: T in iter { |
180 | s.push(item); |
181 | } |
182 | s |
183 | } |
184 | } |
185 | |
186 | impl<'a, T: TransparentPtrType> std::iter::IntoIterator for &'a PtrSlice<T> { |
187 | type Item = &'a T; |
188 | type IntoIter = std::slice::Iter<'a, T>; |
189 | |
190 | #[inline ] |
191 | fn into_iter(self) -> Self::IntoIter { |
192 | self.as_slice().iter() |
193 | } |
194 | } |
195 | |
196 | impl<'a, T: TransparentPtrType> std::iter::IntoIterator for &'a mut PtrSlice<T> { |
197 | type Item = &'a mut T; |
198 | type IntoIter = std::slice::IterMut<'a, T>; |
199 | |
200 | #[inline ] |
201 | fn into_iter(self) -> Self::IntoIter { |
202 | self.as_mut_slice().iter_mut() |
203 | } |
204 | } |
205 | |
206 | impl<T: TransparentPtrType> std::iter::IntoIterator for PtrSlice<T> { |
207 | type Item = T; |
208 | type IntoIter = IntoIter<T>; |
209 | |
210 | #[inline ] |
211 | fn into_iter(self) -> Self::IntoIter { |
212 | IntoIter::new(self) |
213 | } |
214 | } |
215 | |
216 | pub struct IntoIter<T: TransparentPtrType> { |
217 | ptr: ptr::NonNull<<T as GlibPtrDefault>::GlibType>, |
218 | idx: ptr::NonNull<<T as GlibPtrDefault>::GlibType>, |
219 | len: usize, |
220 | empty: bool, |
221 | } |
222 | |
223 | impl<T: TransparentPtrType> IntoIter<T> { |
224 | #[inline ] |
225 | fn new(slice: PtrSlice<T>) -> Self { |
226 | let slice = mem::ManuallyDrop::new(slice); |
227 | IntoIter { |
228 | ptr: slice.ptr, |
229 | idx: slice.ptr, |
230 | len: slice.len, |
231 | empty: slice.capacity == 0, |
232 | } |
233 | } |
234 | |
235 | // rustdoc-stripper-ignore-next |
236 | /// Returns the remaining items as slice. |
237 | #[inline ] |
238 | pub fn as_slice(&self) -> &[T] { |
239 | unsafe { |
240 | if self.len == 0 { |
241 | &[] |
242 | } else { |
243 | std::slice::from_raw_parts(self.idx.as_ptr() as *mut T, self.len) |
244 | } |
245 | } |
246 | } |
247 | |
248 | // rustdoc-stripper-ignore-next |
249 | /// Returns the remaining items as mutable slice. |
250 | #[inline ] |
251 | pub fn as_mut_slice(&mut self) -> &mut [T] { |
252 | unsafe { |
253 | if self.len == 0 { |
254 | &mut [] |
255 | } else { |
256 | std::slice::from_raw_parts_mut(self.idx.as_ptr() as *mut T, self.len) |
257 | } |
258 | } |
259 | } |
260 | } |
261 | |
262 | impl<T: TransparentPtrType> Drop for IntoIter<T> { |
263 | #[inline ] |
264 | fn drop(&mut self) { |
265 | unsafe { |
266 | if mem::needs_drop::<T>() { |
267 | for i: usize in 0..self.len { |
268 | ptr::drop_in_place::<T>(self.idx.as_ptr().add(count:i) as *mut T); |
269 | } |
270 | } |
271 | |
272 | if !self.empty { |
273 | ffi::g_free(self.ptr.as_ptr() as ffi::gpointer); |
274 | } |
275 | } |
276 | } |
277 | } |
278 | |
279 | impl<T: TransparentPtrType> Iterator for IntoIter<T> { |
280 | type Item = T; |
281 | |
282 | #[inline ] |
283 | fn next(&mut self) -> Option<Self::Item> { |
284 | if self.len == 0 { |
285 | return None; |
286 | } |
287 | |
288 | unsafe { |
289 | let p = self.idx.as_ptr(); |
290 | self.len -= 1; |
291 | self.idx = ptr::NonNull::new_unchecked(p.add(1)); |
292 | Some(ptr::read(p as *mut T)) |
293 | } |
294 | } |
295 | |
296 | #[inline ] |
297 | fn size_hint(&self) -> (usize, Option<usize>) { |
298 | (self.len, Some(self.len)) |
299 | } |
300 | |
301 | #[inline ] |
302 | fn count(self) -> usize { |
303 | self.len |
304 | } |
305 | |
306 | #[inline ] |
307 | fn last(mut self) -> Option<T> { |
308 | if self.len == 0 { |
309 | None |
310 | } else { |
311 | self.len -= 1; |
312 | Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) }) |
313 | } |
314 | } |
315 | } |
316 | |
317 | impl<T: TransparentPtrType> DoubleEndedIterator for IntoIter<T> { |
318 | #[inline ] |
319 | fn next_back(&mut self) -> Option<T> { |
320 | if self.len == 0 { |
321 | None |
322 | } else { |
323 | self.len -= 1; |
324 | Some(unsafe { ptr::read(self.idx.as_ptr().add(self.len) as *mut T) }) |
325 | } |
326 | } |
327 | } |
328 | |
329 | impl<T: TransparentPtrType> ExactSizeIterator for IntoIter<T> {} |
330 | |
331 | impl<T: TransparentPtrType> std::iter::FusedIterator for IntoIter<T> {} |
332 | |
333 | impl<T: TransparentPtrType> From<PtrSlice<T>> for Vec<T> { |
334 | #[inline ] |
335 | fn from(mut value: PtrSlice<T>) -> Self { |
336 | unsafe { |
337 | let mut s: Vec = Vec::with_capacity(value.len); |
338 | ptr::copy_nonoverlapping(src:value.ptr.as_ptr() as *const T, dst:s.as_mut_ptr(), count:value.len); |
339 | s.set_len(new_len:value.len); |
340 | value.len = 0; |
341 | s |
342 | } |
343 | } |
344 | } |
345 | |
346 | impl<T: TransparentPtrType> From<Vec<T>> for PtrSlice<T> { |
347 | #[inline ] |
348 | fn from(mut value: Vec<T>) -> Self { |
349 | unsafe { |
350 | let mut s: PtrSlice = Self::with_capacity(value.len()); |
351 | ptr::copy_nonoverlapping(src:value.as_ptr(), dst:s.ptr.as_ptr() as *mut T, count:value.len()); |
352 | s.len = value.len(); |
353 | value.set_len(new_len:0); |
354 | ptr::write( |
355 | dst:s.ptr.as_ptr().add(s.len), |
356 | src:Ptr::from(ptr:ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
357 | ); |
358 | s |
359 | } |
360 | } |
361 | } |
362 | |
363 | impl<T: TransparentPtrType, const N: usize> From<[T; N]> for PtrSlice<T> { |
364 | #[inline ] |
365 | fn from(value: [T; N]) -> Self { |
366 | unsafe { |
367 | let value: ManuallyDrop<[T; N]> = mem::ManuallyDrop::new(value); |
368 | let len: usize = value.len(); |
369 | let mut s: PtrSlice = Self::with_capacity(len); |
370 | ptr::copy_nonoverlapping(src:value.as_ptr(), dst:s.ptr.as_ptr() as *mut T, count:len); |
371 | s.len = len; |
372 | ptr::write( |
373 | dst:s.ptr.as_ptr().add(len), |
374 | src:Ptr::from(ptr:ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
375 | ); |
376 | s |
377 | } |
378 | } |
379 | } |
380 | |
381 | impl<'a, T: TransparentPtrType> From<&'a [T]> for PtrSlice<T> { |
382 | #[inline ] |
383 | fn from(value: &'a [T]) -> Self { |
384 | unsafe { |
385 | let mut s: PtrSlice = Self::with_capacity(value.len()); |
386 | for (i: usize, item: &T) in value.iter().enumerate() { |
387 | ptr::write(dst:s.ptr.as_ptr().add(i) as *mut T, src:item.clone()); |
388 | } |
389 | s.len = value.len(); |
390 | ptr::write( |
391 | dst:s.ptr.as_ptr().add(s.len), |
392 | src:Ptr::from(ptr:ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
393 | ); |
394 | s |
395 | } |
396 | } |
397 | } |
398 | |
399 | impl<'a, T: TransparentPtrType> From<&'a [&'a T]> for PtrSlice<T> { |
400 | #[inline ] |
401 | fn from(value: &'a [&'a T]) -> Self { |
402 | unsafe { |
403 | let mut s: PtrSlice = Self::with_capacity(value.len()); |
404 | for (i: usize, item: &&T) in value.iter().enumerate() { |
405 | ptr::write(dst:s.ptr.as_ptr().add(i) as *mut T, (*item).clone()); |
406 | } |
407 | s.len = value.len(); |
408 | ptr::write( |
409 | dst:s.ptr.as_ptr().add(s.len), |
410 | src:Ptr::from(ptr:ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
411 | ); |
412 | s |
413 | } |
414 | } |
415 | } |
416 | |
417 | impl<T: TransparentPtrType> Clone for PtrSlice<T> { |
418 | #[inline ] |
419 | fn clone(&self) -> Self { |
420 | Self::from(self.as_slice()) |
421 | } |
422 | } |
423 | |
424 | impl<T: TransparentPtrType> PtrSlice<T> { |
425 | // rustdoc-stripper-ignore-next |
426 | /// Borrows a C array. |
427 | #[inline ] |
428 | pub unsafe fn from_glib_borrow<'a>(ptr: *const <T as GlibPtrDefault>::GlibType) -> &'a [T] { |
429 | let mut len = 0; |
430 | if !ptr.is_null() { |
431 | while !(*ptr.add(len)).is_null() { |
432 | len += 1; |
433 | } |
434 | } |
435 | Self::from_glib_borrow_num(ptr, len) |
436 | } |
437 | |
438 | // rustdoc-stripper-ignore-next |
439 | /// Borrows a C array. |
440 | #[inline ] |
441 | pub unsafe fn from_glib_borrow_num<'a>( |
442 | ptr: *const <T as GlibPtrDefault>::GlibType, |
443 | len: usize, |
444 | ) -> &'a [T] { |
445 | debug_assert_eq!( |
446 | mem::size_of::<T>(), |
447 | mem::size_of::<<T as GlibPtrDefault>::GlibType>() |
448 | ); |
449 | debug_assert!(!ptr.is_null() || len == 0); |
450 | |
451 | if len == 0 { |
452 | &[] |
453 | } else { |
454 | std::slice::from_raw_parts(ptr as *const T, len) |
455 | } |
456 | } |
457 | |
458 | // rustdoc-stripper-ignore-next |
459 | /// Create a new `PtrSlice` around a C array. |
460 | #[inline ] |
461 | pub unsafe fn from_glib_none_num( |
462 | ptr: *const <T as GlibPtrDefault>::GlibType, |
463 | len: usize, |
464 | _null_terminated: bool, |
465 | ) -> Self { |
466 | debug_assert_eq!( |
467 | mem::size_of::<T>(), |
468 | mem::size_of::<<T as GlibPtrDefault>::GlibType>() |
469 | ); |
470 | debug_assert!(!ptr.is_null() || len == 0); |
471 | |
472 | if len == 0 { |
473 | PtrSlice::default() |
474 | } else { |
475 | // Need to fully copy the array here. |
476 | let s = Self::from_glib_borrow_num(ptr, len); |
477 | Self::from(s) |
478 | } |
479 | } |
480 | |
481 | // rustdoc-stripper-ignore-next |
482 | /// Create a new `PtrSlice` around a C array. |
483 | #[inline ] |
484 | pub unsafe fn from_glib_container_num( |
485 | ptr: *mut <T as GlibPtrDefault>::GlibType, |
486 | len: usize, |
487 | null_terminated: bool, |
488 | ) -> Self { |
489 | debug_assert_eq!( |
490 | mem::size_of::<T>(), |
491 | mem::size_of::<<T as GlibPtrDefault>::GlibType>() |
492 | ); |
493 | debug_assert!(!ptr.is_null() || len == 0); |
494 | |
495 | if len == 0 { |
496 | ffi::g_free(ptr as ffi::gpointer); |
497 | PtrSlice::default() |
498 | } else { |
499 | // Need to clone every item because we don't own it here |
500 | for i in 0..len { |
501 | let p = ptr.add(i) as *mut T; |
502 | let clone: T = (*p).clone(); |
503 | ptr::write(p, clone); |
504 | } |
505 | |
506 | // And now it can be handled exactly the same as `from_glib_full_num()`. |
507 | Self::from_glib_full_num(ptr, len, null_terminated) |
508 | } |
509 | } |
510 | |
511 | // rustdoc-stripper-ignore-next |
512 | /// Create a new `PtrSlice` around a C array. |
513 | #[inline ] |
514 | pub unsafe fn from_glib_full_num( |
515 | ptr: *mut <T as GlibPtrDefault>::GlibType, |
516 | len: usize, |
517 | null_terminated: bool, |
518 | ) -> Self { |
519 | debug_assert_eq!( |
520 | mem::size_of::<T>(), |
521 | mem::size_of::<<T as GlibPtrDefault>::GlibType>() |
522 | ); |
523 | debug_assert!(!ptr.is_null() || len == 0); |
524 | |
525 | if len == 0 { |
526 | ffi::g_free(ptr as ffi::gpointer); |
527 | PtrSlice::default() |
528 | } else { |
529 | if null_terminated { |
530 | return PtrSlice { |
531 | ptr: ptr::NonNull::new_unchecked(ptr), |
532 | len, |
533 | capacity: len + 1, |
534 | }; |
535 | } |
536 | |
537 | // Need to re-allocate here for adding the NULL-terminator |
538 | let capacity = len + 1; |
539 | assert_ne!(capacity, 0); |
540 | let ptr = ffi::g_realloc( |
541 | ptr as *mut _, |
542 | mem::size_of::<T>().checked_mul(capacity).unwrap(), |
543 | ) as *mut <T as GlibPtrDefault>::GlibType; |
544 | |
545 | ptr::write( |
546 | ptr.add(len), |
547 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
548 | ); |
549 | |
550 | PtrSlice { |
551 | ptr: ptr::NonNull::new_unchecked(ptr), |
552 | len, |
553 | capacity, |
554 | } |
555 | } |
556 | } |
557 | |
558 | // rustdoc-stripper-ignore-next |
559 | /// Create a new `PtrSlice` around a `NULL`-terminated C array. |
560 | #[inline ] |
561 | pub unsafe fn from_glib_none(ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
562 | let mut len = 0; |
563 | if !ptr.is_null() { |
564 | while !(*ptr.add(len)).is_null() { |
565 | len += 1; |
566 | } |
567 | } |
568 | |
569 | PtrSlice::from_glib_none_num(ptr, len, true) |
570 | } |
571 | |
572 | // rustdoc-stripper-ignore-next |
573 | /// Create a new `PtrSlice` around a `NULL`-terminated C array. |
574 | #[inline ] |
575 | pub unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
576 | let mut len = 0; |
577 | if !ptr.is_null() { |
578 | while !(*ptr.add(len)).is_null() { |
579 | len += 1; |
580 | } |
581 | } |
582 | |
583 | PtrSlice::from_glib_container_num(ptr, len, true) |
584 | } |
585 | |
586 | // rustdoc-stripper-ignore-next |
587 | /// Create a new `PtrSlice` around a `NULL`-terminated C array. |
588 | #[inline ] |
589 | pub unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
590 | let mut len = 0; |
591 | if !ptr.is_null() { |
592 | while !(*ptr.add(len)).is_null() { |
593 | len += 1; |
594 | } |
595 | } |
596 | |
597 | PtrSlice::from_glib_full_num(ptr, len, true) |
598 | } |
599 | |
600 | // rustdoc-stripper-ignore-next |
601 | /// Creates a new empty slice. |
602 | #[inline ] |
603 | pub fn new() -> Self { |
604 | debug_assert_eq!( |
605 | mem::size_of::<T>(), |
606 | mem::size_of::<<T as GlibPtrDefault>::GlibType>() |
607 | ); |
608 | |
609 | PtrSlice { |
610 | ptr: ptr::NonNull::dangling(), |
611 | len: 0, |
612 | capacity: 0, |
613 | } |
614 | } |
615 | |
616 | // rustdoc-stripper-ignore-next |
617 | /// Creates a new empty slice with the given capacity. |
618 | #[inline ] |
619 | pub fn with_capacity(capacity: usize) -> Self { |
620 | let mut s = Self::new(); |
621 | s.reserve(capacity); |
622 | s |
623 | } |
624 | |
625 | // rustdoc-stripper-ignore-next |
626 | /// Returns the underlying pointer. |
627 | /// |
628 | /// This is guaranteed to be `NULL`-terminated. |
629 | #[inline ] |
630 | pub fn as_ptr(&self) -> *const <T as GlibPtrDefault>::GlibType { |
631 | if self.len == 0 { |
632 | static EMPTY: [usize; 1] = [0]; |
633 | |
634 | EMPTY.as_ptr() as *const _ |
635 | } else { |
636 | self.ptr.as_ptr() |
637 | } |
638 | } |
639 | |
640 | // rustdoc-stripper-ignore-next |
641 | /// Returns the underlying pointer. |
642 | /// |
643 | /// This is guaranteed to be `NULL`-terminated. |
644 | #[inline ] |
645 | pub fn as_mut_ptr(&mut self) -> *mut <T as GlibPtrDefault>::GlibType { |
646 | if self.len == 0 { |
647 | static EMPTY: [usize; 1] = [0]; |
648 | |
649 | EMPTY.as_ptr() as *mut _ |
650 | } else { |
651 | self.ptr.as_ptr() |
652 | } |
653 | } |
654 | |
655 | // rustdoc-stripper-ignore-next |
656 | /// Consumes the slice and returns the underlying pointer. |
657 | /// |
658 | /// This is guaranteed to be `NULL`-terminated. |
659 | #[inline ] |
660 | pub fn into_raw(mut self) -> *mut <T as GlibPtrDefault>::GlibType { |
661 | if self.len == 0 { |
662 | ptr::null_mut() |
663 | } else { |
664 | self.len = 0; |
665 | self.capacity = 0; |
666 | self.ptr.as_ptr() |
667 | } |
668 | } |
669 | |
670 | // rustdoc-stripper-ignore-next |
671 | /// Gets the length of the slice. |
672 | #[inline ] |
673 | pub fn len(&self) -> usize { |
674 | self.len |
675 | } |
676 | |
677 | // rustdoc-stripper-ignore-next |
678 | /// Returns `true` if the slice is empty. |
679 | #[inline ] |
680 | pub fn is_empty(&self) -> bool { |
681 | self.len == 0 |
682 | } |
683 | |
684 | // rustdoc-stripper-ignore-next |
685 | /// Returns the capacity of the slice. |
686 | /// |
687 | /// This includes the space that is reserved for the `NULL`-terminator. |
688 | #[inline ] |
689 | pub fn capacity(&self) -> usize { |
690 | self.capacity |
691 | } |
692 | |
693 | // rustdoc-stripper-ignore-next |
694 | /// Sets the length of the slice to `len`. |
695 | /// |
696 | /// # SAFETY |
697 | /// |
698 | /// There must be at least `len` valid items and a `NULL`-terminator after the last item. |
699 | pub unsafe fn set_len(&mut self, len: usize) { |
700 | self.len = len; |
701 | } |
702 | |
703 | // rustdoc-stripper-ignore-next |
704 | /// Reserves at least this much additional capacity. |
705 | #[allow (clippy::int_plus_one)] |
706 | pub fn reserve(&mut self, additional: usize) { |
707 | // Nothing new to reserve as there's still enough space |
708 | if self.len + additional + 1 <= self.capacity { |
709 | return; |
710 | } |
711 | |
712 | let new_capacity = |
713 | usize::next_power_of_two(std::cmp::max(self.len + additional, MIN_SIZE) + 1); |
714 | assert_ne!(new_capacity, 0); |
715 | assert!(new_capacity > self.capacity); |
716 | |
717 | unsafe { |
718 | let ptr = if self.capacity == 0 { |
719 | ptr::null_mut() |
720 | } else { |
721 | self.ptr.as_ptr() as *mut _ |
722 | }; |
723 | let new_ptr = |
724 | ffi::g_realloc(ptr, mem::size_of::<T>().checked_mul(new_capacity).unwrap()) |
725 | as *mut <T as GlibPtrDefault>::GlibType; |
726 | if self.capacity == 0 { |
727 | ptr::write( |
728 | new_ptr, |
729 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
730 | ); |
731 | } |
732 | self.ptr = ptr::NonNull::new_unchecked(new_ptr); |
733 | self.capacity = new_capacity; |
734 | } |
735 | } |
736 | |
737 | // rustdoc-stripper-ignore-next |
738 | /// Borrows this slice as a `&[T]`. |
739 | #[inline ] |
740 | pub fn as_slice(&self) -> &[T] { |
741 | unsafe { |
742 | if self.len == 0 { |
743 | &[] |
744 | } else { |
745 | std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len) |
746 | } |
747 | } |
748 | } |
749 | |
750 | // rustdoc-stripper-ignore-next |
751 | /// Borrows this slice as a `&mut [T]`. |
752 | #[inline ] |
753 | pub fn as_mut_slice(&mut self) -> &mut [T] { |
754 | unsafe { |
755 | if self.len == 0 { |
756 | &mut [] |
757 | } else { |
758 | std::slice::from_raw_parts_mut(self.ptr.as_ptr() as *mut T, self.len) |
759 | } |
760 | } |
761 | } |
762 | |
763 | // rustdoc-stripper-ignore-next |
764 | /// Removes all items from the slice. |
765 | #[inline ] |
766 | pub fn clear(&mut self) { |
767 | unsafe { |
768 | if mem::needs_drop::<T>() { |
769 | for i in 0..self.len { |
770 | ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T); |
771 | } |
772 | } |
773 | |
774 | self.len = 0; |
775 | } |
776 | } |
777 | |
778 | // rustdoc-stripper-ignore-next |
779 | /// Clones and appends all elements in `slice` to the slice. |
780 | #[inline ] |
781 | pub fn extend_from_slice(&mut self, other: &[T]) { |
782 | // Nothing new to reserve as there's still enough space |
783 | if self.len + other.len() + 1 > self.capacity { |
784 | self.reserve(other.len()); |
785 | } |
786 | |
787 | unsafe { |
788 | for item in other { |
789 | ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item.clone()); |
790 | self.len += 1; |
791 | } |
792 | |
793 | ptr::write( |
794 | self.ptr.as_ptr().add(self.len), |
795 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
796 | ); |
797 | } |
798 | } |
799 | |
800 | // rustdoc-stripper-ignore-next |
801 | /// Inserts `item` at position `index` of the slice, shifting all elements after it to the |
802 | /// right. |
803 | #[inline ] |
804 | pub fn insert(&mut self, index: usize, item: T) { |
805 | assert!(index <= self.len); |
806 | |
807 | // Nothing new to reserve as there's still enough space |
808 | if self.len + 1 + 1 > self.capacity { |
809 | self.reserve(1); |
810 | } |
811 | |
812 | unsafe { |
813 | if index == self.len { |
814 | ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item); |
815 | } else { |
816 | let p = self.ptr.as_ptr().add(index); |
817 | ptr::copy(p, p.add(1), self.len - index); |
818 | ptr::write(self.ptr.as_ptr().add(index) as *mut T, item); |
819 | } |
820 | |
821 | self.len += 1; |
822 | |
823 | ptr::write( |
824 | self.ptr.as_ptr().add(self.len), |
825 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
826 | ); |
827 | } |
828 | } |
829 | |
830 | // rustdoc-stripper-ignore-next |
831 | /// Pushes `item` to the end of the slice. |
832 | #[inline ] |
833 | pub fn push(&mut self, item: T) { |
834 | // Nothing new to reserve as there's still enough space |
835 | if self.len + 1 + 1 > self.capacity { |
836 | self.reserve(1); |
837 | } |
838 | |
839 | unsafe { |
840 | ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item); |
841 | self.len += 1; |
842 | |
843 | ptr::write( |
844 | self.ptr.as_ptr().add(self.len), |
845 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
846 | ); |
847 | } |
848 | } |
849 | |
850 | // rustdoc-stripper-ignore-next |
851 | /// Removes item from position `index` of the slice, shifting all elements after it to the |
852 | /// left. |
853 | #[inline ] |
854 | pub fn remove(&mut self, index: usize) -> T { |
855 | assert!(index < self.len); |
856 | |
857 | unsafe { |
858 | let p = self.ptr.as_ptr().add(index); |
859 | let item = ptr::read(p as *mut T); |
860 | ptr::copy(p.add(1), p, self.len - index - 1); |
861 | |
862 | self.len -= 1; |
863 | |
864 | ptr::write( |
865 | self.ptr.as_ptr().add(self.len), |
866 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
867 | ); |
868 | |
869 | item |
870 | } |
871 | } |
872 | |
873 | // rustdoc-stripper-ignore-next |
874 | /// Removes the last item of the slice and returns it. |
875 | #[inline ] |
876 | pub fn pop(&mut self) -> Option<T> { |
877 | if self.len == 0 { |
878 | return None; |
879 | } |
880 | |
881 | unsafe { |
882 | self.len -= 1; |
883 | let p = self.ptr.as_ptr().add(self.len); |
884 | let item = ptr::read(p as *mut T); |
885 | |
886 | ptr::write( |
887 | self.ptr.as_ptr().add(self.len), |
888 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
889 | ); |
890 | |
891 | Some(item) |
892 | } |
893 | } |
894 | |
895 | // rustdoc-stripper-ignore-next |
896 | /// Shortens the slice by keeping the last `len` items. |
897 | /// |
898 | /// If there are fewer than `len` items then this has no effect. |
899 | #[inline ] |
900 | pub fn truncate(&mut self, len: usize) { |
901 | if self.len <= len { |
902 | return; |
903 | } |
904 | |
905 | unsafe { |
906 | while self.len > len { |
907 | self.len -= 1; |
908 | let p = self.ptr.as_ptr().add(self.len); |
909 | ptr::drop_in_place::<T>(p as *mut T); |
910 | ptr::write( |
911 | p, |
912 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
913 | ); |
914 | } |
915 | } |
916 | } |
917 | } |
918 | |
919 | impl<T: TransparentPtrType> |
920 | FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType> |
921 | for PtrSlice<T> |
922 | { |
923 | #[inline ] |
924 | unsafe fn from_glib_none_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self { |
925 | Self::from_glib_none_num(ptr, len:num, _null_terminated:false) |
926 | } |
927 | |
928 | #[inline ] |
929 | unsafe fn from_glib_container_num( |
930 | ptr: *mut <T as GlibPtrDefault>::GlibType, |
931 | num: usize, |
932 | ) -> Self { |
933 | Self::from_glib_container_num(ptr, len:num, null_terminated:false) |
934 | } |
935 | |
936 | #[inline ] |
937 | unsafe fn from_glib_full_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self { |
938 | Self::from_glib_full_num(ptr, len:num, null_terminated:false) |
939 | } |
940 | } |
941 | |
942 | impl<T: TransparentPtrType> |
943 | FromGlibContainer<<T as GlibPtrDefault>::GlibType, *const <T as GlibPtrDefault>::GlibType> |
944 | for PtrSlice<T> |
945 | { |
946 | unsafe fn from_glib_none_num(ptr: *const <T as GlibPtrDefault>::GlibType, num: usize) -> Self { |
947 | Self::from_glib_none_num(ptr, len:num, _null_terminated:false) |
948 | } |
949 | |
950 | unsafe fn from_glib_container_num( |
951 | _ptr: *const <T as GlibPtrDefault>::GlibType, |
952 | _num: usize, |
953 | ) -> Self { |
954 | unimplemented!(); |
955 | } |
956 | |
957 | unsafe fn from_glib_full_num( |
958 | _ptr: *const <T as GlibPtrDefault>::GlibType, |
959 | _num: usize, |
960 | ) -> Self { |
961 | unimplemented!(); |
962 | } |
963 | } |
964 | |
965 | impl<T: TransparentPtrType> |
966 | FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType> |
967 | for PtrSlice<T> |
968 | { |
969 | #[inline ] |
970 | unsafe fn from_glib_none(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
971 | Self::from_glib_none(ptr) |
972 | } |
973 | |
974 | #[inline ] |
975 | unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
976 | Self::from_glib_container(ptr) |
977 | } |
978 | |
979 | #[inline ] |
980 | unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
981 | Self::from_glib_full(ptr) |
982 | } |
983 | } |
984 | |
985 | impl<T: TransparentPtrType> |
986 | FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *const <T as GlibPtrDefault>::GlibType> |
987 | for PtrSlice<T> |
988 | { |
989 | #[inline ] |
990 | unsafe fn from_glib_none(ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
991 | Self::from_glib_none(ptr) |
992 | } |
993 | |
994 | unsafe fn from_glib_container(_ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
995 | unimplemented!(); |
996 | } |
997 | |
998 | unsafe fn from_glib_full(_ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
999 | unimplemented!(); |
1000 | } |
1001 | } |
1002 | |
1003 | impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *mut <T as GlibPtrDefault>::GlibType> |
1004 | for PtrSlice<T> |
1005 | { |
1006 | type Storage = PhantomData<&'a Self>; |
1007 | |
1008 | #[inline ] |
1009 | fn to_glib_none(&'a self) -> Stash<'a, *mut <T as GlibPtrDefault>::GlibType, Self> { |
1010 | Stash(self.as_ptr() as *mut _, PhantomData) |
1011 | } |
1012 | |
1013 | #[inline ] |
1014 | fn to_glib_container(&'a self) -> Stash<'a, *mut <T as GlibPtrDefault>::GlibType, Self> { |
1015 | unsafe { |
1016 | let ptr: *mut ::GlibType = ffi::g_malloc(n_bytes:mem::size_of::<T>().checked_mul(self.len() + 1).unwrap()) |
1017 | as *mut <T as GlibPtrDefault>::GlibType; |
1018 | ptr::copy_nonoverlapping(self.as_ptr(), dst:ptr, self.len() + 1); |
1019 | Stash(ptr, PhantomData) |
1020 | } |
1021 | } |
1022 | |
1023 | #[inline ] |
1024 | fn to_glib_full(&self) -> *mut <T as GlibPtrDefault>::GlibType { |
1025 | self.clone().into_raw() |
1026 | } |
1027 | } |
1028 | |
1029 | impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *const <T as GlibPtrDefault>::GlibType> |
1030 | for PtrSlice<T> |
1031 | { |
1032 | type Storage = PhantomData<&'a Self>; |
1033 | |
1034 | #[inline ] |
1035 | fn to_glib_none(&'a self) -> Stash<'a, *const <T as GlibPtrDefault>::GlibType, Self> { |
1036 | Stash(self.as_ptr(), PhantomData) |
1037 | } |
1038 | } |
1039 | |
1040 | impl<'a, T: TransparentPtrType + 'a> ToGlibPtrMut<'a, *mut <T as GlibPtrDefault>::GlibType> |
1041 | for PtrSlice<T> |
1042 | { |
1043 | type Storage = PhantomData<&'a mut Self>; |
1044 | |
1045 | #[inline ] |
1046 | fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut <T as GlibPtrDefault>::GlibType, Self> { |
1047 | StashMut(self.as_mut_ptr(), PhantomData) |
1048 | } |
1049 | } |
1050 | |
1051 | impl<T: TransparentPtrType> IntoGlibPtr<*mut <T as GlibPtrDefault>::GlibType> for PtrSlice<T> { |
1052 | #[inline ] |
1053 | unsafe fn into_glib_ptr(self) -> *mut <T as GlibPtrDefault>::GlibType { |
1054 | self.into_raw() |
1055 | } |
1056 | } |
1057 | |
1058 | impl<T: TransparentPtrType> From<super::Slice<T>> for PtrSlice<T> { |
1059 | fn from(value: super::Slice<T>) -> Self { |
1060 | let len = value.len(); |
1061 | let capacity = value.capacity(); |
1062 | unsafe { |
1063 | let ptr = value.into_raw(); |
1064 | let mut s = PtrSlice::<T> { |
1065 | ptr: ptr::NonNull::new_unchecked(ptr), |
1066 | len, |
1067 | capacity, |
1068 | }; |
1069 | |
1070 | // Reserve space for the `NULL`-terminator if needed |
1071 | if len == capacity { |
1072 | s.reserve(0); |
1073 | } |
1074 | |
1075 | ptr::write( |
1076 | s.ptr.as_ptr().add(s.len()), |
1077 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1078 | ); |
1079 | |
1080 | s |
1081 | } |
1082 | } |
1083 | } |
1084 | |
1085 | // rustdoc-stripper-ignore-next |
1086 | /// A trait to accept both `&[T]` or `PtrSlice<T>` as an argument. |
1087 | pub trait IntoPtrSlice<T: TransparentPtrType> { |
1088 | // rustdoc-stripper-ignore-next |
1089 | /// Runs the given closure with a `NULL`-terminated array. |
1090 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R; |
1091 | } |
1092 | |
1093 | impl<T: TransparentPtrType> IntoPtrSlice<T> for PtrSlice<T> { |
1094 | #[inline ] |
1095 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1096 | <&Self>::run_with_ptr_slice(&self, f) |
1097 | } |
1098 | } |
1099 | |
1100 | impl<T: TransparentPtrType> IntoPtrSlice<T> for &'_ PtrSlice<T> { |
1101 | #[inline ] |
1102 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1103 | f(unsafe { std::slice::from_raw_parts(self.as_ptr() as *mut _, self.len() + 1) }) |
1104 | } |
1105 | } |
1106 | |
1107 | // rustdoc-stripper-ignore-next |
1108 | /// Maximum number of pointers to stack-allocate before falling back to a heap allocation. |
1109 | const MAX_STACK_ALLOCATION: usize = 16; |
1110 | |
1111 | impl<T: TransparentPtrType> IntoPtrSlice<T> for Vec<T> { |
1112 | #[inline ] |
1113 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1114 | if self.len() < MAX_STACK_ALLOCATION { |
1115 | unsafe { |
1116 | let mut s = mem::MaybeUninit::< |
1117 | [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION], |
1118 | >::uninit(); |
1119 | let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType; |
1120 | ptr::copy_nonoverlapping( |
1121 | self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType, |
1122 | ptr, |
1123 | self.len(), |
1124 | ); |
1125 | ptr::write( |
1126 | ptr.add(self.len()), |
1127 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1128 | ); |
1129 | f(std::slice::from_raw_parts(ptr, self.len() + 1)) |
1130 | } |
1131 | } else { |
1132 | PtrSlice::<T>::from(self).run_with_ptr_slice(f) |
1133 | } |
1134 | } |
1135 | } |
1136 | |
1137 | impl<T: TransparentPtrType, const N: usize> IntoPtrSlice<T> for [T; N] { |
1138 | #[inline ] |
1139 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1140 | if self.len() < MAX_STACK_ALLOCATION { |
1141 | unsafe { |
1142 | let mut s = mem::MaybeUninit::< |
1143 | [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION], |
1144 | >::uninit(); |
1145 | let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType; |
1146 | ptr::copy_nonoverlapping( |
1147 | self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType, |
1148 | ptr, |
1149 | self.len(), |
1150 | ); |
1151 | ptr::write( |
1152 | ptr.add(self.len()), |
1153 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1154 | ); |
1155 | f(std::slice::from_raw_parts(ptr, self.len() + 1)) |
1156 | } |
1157 | } else { |
1158 | PtrSlice::<T>::from(self).run_with_ptr_slice(f) |
1159 | } |
1160 | } |
1161 | } |
1162 | |
1163 | impl<T: TransparentPtrType> IntoPtrSlice<T> for &'_ [T] { |
1164 | #[inline ] |
1165 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1166 | if self.len() < MAX_STACK_ALLOCATION { |
1167 | unsafe { |
1168 | let mut s = mem::MaybeUninit::< |
1169 | [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION], |
1170 | >::uninit(); |
1171 | let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType; |
1172 | ptr::copy_nonoverlapping( |
1173 | self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType, |
1174 | ptr, |
1175 | self.len(), |
1176 | ); |
1177 | ptr::write( |
1178 | ptr.add(self.len()), |
1179 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1180 | ); |
1181 | f(std::slice::from_raw_parts(ptr, self.len() + 1)) |
1182 | } |
1183 | } else { |
1184 | PtrSlice::<T>::from(self).run_with_ptr_slice(f) |
1185 | } |
1186 | } |
1187 | } |
1188 | |
1189 | #[cfg (test)] |
1190 | mod test { |
1191 | use super::*; |
1192 | |
1193 | #[test ] |
1194 | fn test_from_glib_full() { |
1195 | let items = [ |
1196 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1197 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1198 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1199 | crate::Error::new(crate::FileError::Perm, "Failed 4" ), |
1200 | ]; |
1201 | |
1202 | let slice = unsafe { |
1203 | let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut *mut ffi::GError; |
1204 | ptr::write(ptr.add(0), items[0].to_glib_full()); |
1205 | ptr::write(ptr.add(1), items[1].to_glib_full()); |
1206 | ptr::write(ptr.add(2), items[2].to_glib_full()); |
1207 | ptr::write(ptr.add(3), items[3].to_glib_full()); |
1208 | |
1209 | PtrSlice::<crate::Error>::from_glib_full_num(ptr, 4, false) |
1210 | }; |
1211 | |
1212 | for (a, b) in Iterator::zip(items.iter(), slice.iter()) { |
1213 | assert_eq!(a.message(), b.message()); |
1214 | assert_eq!( |
1215 | a.kind::<crate::FileError>().unwrap(), |
1216 | b.kind::<crate::FileError>().unwrap() |
1217 | ); |
1218 | } |
1219 | } |
1220 | |
1221 | #[test ] |
1222 | fn test_from_glib_none() { |
1223 | let items = [ |
1224 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1225 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1226 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1227 | crate::Error::new(crate::FileError::Perm, "Failed 4" ), |
1228 | ]; |
1229 | |
1230 | let slice = unsafe { |
1231 | PtrSlice::<crate::Error>::from_glib_none_num( |
1232 | items.as_ptr() as *const *mut ffi::GError, |
1233 | 4, |
1234 | false, |
1235 | ) |
1236 | }; |
1237 | |
1238 | for (a, b) in Iterator::zip(items.iter(), slice.iter()) { |
1239 | assert_eq!(a.message(), b.message()); |
1240 | assert_eq!( |
1241 | a.kind::<crate::FileError>().unwrap(), |
1242 | b.kind::<crate::FileError>().unwrap() |
1243 | ); |
1244 | } |
1245 | } |
1246 | |
1247 | #[test ] |
1248 | fn test_safe_api() { |
1249 | let items = [ |
1250 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1251 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1252 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1253 | ]; |
1254 | |
1255 | let mut slice = PtrSlice::from(&items[..]); |
1256 | assert_eq!(slice.len(), 3); |
1257 | slice.push(crate::Error::new(crate::FileError::Perm, "Failed 4" )); |
1258 | assert_eq!(slice.len(), 4); |
1259 | |
1260 | for (a, b) in Iterator::zip(items.iter(), slice.iter()) { |
1261 | assert_eq!(a.message(), b.message()); |
1262 | assert_eq!( |
1263 | a.kind::<crate::FileError>().unwrap(), |
1264 | b.kind::<crate::FileError>().unwrap() |
1265 | ); |
1266 | } |
1267 | assert_eq!(slice[3].message(), "Failed 4" ); |
1268 | |
1269 | let vec = Vec::from(slice); |
1270 | assert_eq!(vec.len(), 4); |
1271 | for (a, b) in Iterator::zip(items.iter(), vec.iter()) { |
1272 | assert_eq!(a.message(), b.message()); |
1273 | assert_eq!( |
1274 | a.kind::<crate::FileError>().unwrap(), |
1275 | b.kind::<crate::FileError>().unwrap() |
1276 | ); |
1277 | } |
1278 | assert_eq!(vec[3].message(), "Failed 4" ); |
1279 | |
1280 | let mut slice = PtrSlice::from(vec); |
1281 | assert_eq!(slice.len(), 4); |
1282 | let e = slice.pop().unwrap(); |
1283 | assert_eq!(e.message(), "Failed 4" ); |
1284 | assert_eq!(slice.len(), 3); |
1285 | slice.insert(2, e); |
1286 | assert_eq!(slice.len(), 4); |
1287 | assert_eq!(slice[0].message(), "Failed 1" ); |
1288 | assert_eq!(slice[1].message(), "Failed 2" ); |
1289 | assert_eq!(slice[2].message(), "Failed 4" ); |
1290 | assert_eq!(slice[3].message(), "Failed 3" ); |
1291 | let e = slice.remove(2); |
1292 | assert_eq!(e.message(), "Failed 4" ); |
1293 | assert_eq!(slice.len(), 3); |
1294 | slice.push(e); |
1295 | assert_eq!(slice.len(), 4); |
1296 | |
1297 | let slice2 = crate::Slice::from(slice.clone()); |
1298 | |
1299 | for (a, b) in Iterator::zip(items.iter(), slice.into_iter()) { |
1300 | assert_eq!(a.message(), b.message()); |
1301 | assert_eq!( |
1302 | a.kind::<crate::FileError>().unwrap(), |
1303 | b.kind::<crate::FileError>().unwrap() |
1304 | ); |
1305 | } |
1306 | |
1307 | let slice3 = crate::PtrSlice::from(slice2.clone()); |
1308 | |
1309 | for (a, b) in Iterator::zip(items.iter(), slice2.into_iter()) { |
1310 | assert_eq!(a.message(), b.message()); |
1311 | assert_eq!( |
1312 | a.kind::<crate::FileError>().unwrap(), |
1313 | b.kind::<crate::FileError>().unwrap() |
1314 | ); |
1315 | } |
1316 | |
1317 | for (a, b) in Iterator::zip(items.iter(), slice3.into_iter()) { |
1318 | assert_eq!(a.message(), b.message()); |
1319 | assert_eq!( |
1320 | a.kind::<crate::FileError>().unwrap(), |
1321 | b.kind::<crate::FileError>().unwrap() |
1322 | ); |
1323 | } |
1324 | } |
1325 | |
1326 | #[test ] |
1327 | fn test_into_ptrslice() { |
1328 | let items = [ |
1329 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1330 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1331 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1332 | crate::Error::new(crate::FileError::Perm, "Failed 4" ), |
1333 | ]; |
1334 | |
1335 | items[..].run_with_ptr_slice(|s| unsafe { |
1336 | assert!(s[4].is_null()); |
1337 | assert_eq!(s.len(), items.len() + 1); |
1338 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len()); |
1339 | assert_eq!(s, items); |
1340 | }); |
1341 | |
1342 | Vec::from(&items[..]).run_with_ptr_slice(|s| unsafe { |
1343 | assert!(s[4].is_null()); |
1344 | assert_eq!(s.len(), items.len() + 1); |
1345 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len()); |
1346 | for (a, b) in Iterator::zip(items.iter(), s.iter()) { |
1347 | assert_eq!(a.message(), b.message()); |
1348 | assert_eq!( |
1349 | a.kind::<crate::FileError>().unwrap(), |
1350 | b.kind::<crate::FileError>().unwrap() |
1351 | ); |
1352 | } |
1353 | }); |
1354 | |
1355 | PtrSlice::<crate::Error>::from(&items[..]).run_with_ptr_slice(|s| unsafe { |
1356 | assert!(s[4].is_null()); |
1357 | assert_eq!(s.len(), items.len() + 1); |
1358 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len()); |
1359 | for (a, b) in Iterator::zip(items.iter(), s.iter()) { |
1360 | assert_eq!(a.message(), b.message()); |
1361 | assert_eq!( |
1362 | a.kind::<crate::FileError>().unwrap(), |
1363 | b.kind::<crate::FileError>().unwrap() |
1364 | ); |
1365 | } |
1366 | }); |
1367 | |
1368 | let v = Vec::from(&items[..]); |
1369 | items.run_with_ptr_slice(|s| unsafe { |
1370 | assert!(s[4].is_null()); |
1371 | assert_eq!(s.len(), v.len() + 1); |
1372 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, v.len()); |
1373 | for (a, b) in Iterator::zip(v.iter(), s.iter()) { |
1374 | assert_eq!(a.message(), b.message()); |
1375 | assert_eq!( |
1376 | a.kind::<crate::FileError>().unwrap(), |
1377 | b.kind::<crate::FileError>().unwrap() |
1378 | ); |
1379 | } |
1380 | }); |
1381 | } |
1382 | } |
1383 | |