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::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>`] |
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: &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 | PtrSlice { |
605 | ptr: ptr::NonNull::dangling(), |
606 | len: 0, |
607 | capacity: 0, |
608 | } |
609 | } |
610 | |
611 | // rustdoc-stripper-ignore-next |
612 | /// Creates a new empty slice with the given capacity. |
613 | #[inline ] |
614 | pub fn with_capacity(capacity: usize) -> Self { |
615 | let mut s = Self::new(); |
616 | s.reserve(capacity); |
617 | s |
618 | } |
619 | |
620 | // rustdoc-stripper-ignore-next |
621 | /// Returns the underlying pointer. |
622 | /// |
623 | /// This is guaranteed to be `NULL`-terminated. |
624 | #[inline ] |
625 | pub fn as_ptr(&self) -> *const <T as GlibPtrDefault>::GlibType { |
626 | if self.len == 0 { |
627 | static EMPTY: [usize; 1] = [0]; |
628 | |
629 | EMPTY.as_ptr() as *const _ |
630 | } else { |
631 | self.ptr.as_ptr() |
632 | } |
633 | } |
634 | |
635 | // rustdoc-stripper-ignore-next |
636 | /// Returns the underlying pointer. |
637 | /// |
638 | /// This is guaranteed to be `NULL`-terminated. |
639 | #[inline ] |
640 | pub fn as_mut_ptr(&mut self) -> *mut <T as GlibPtrDefault>::GlibType { |
641 | if self.len == 0 { |
642 | static EMPTY: [usize; 1] = [0]; |
643 | |
644 | EMPTY.as_ptr() as *mut _ |
645 | } else { |
646 | self.ptr.as_ptr() |
647 | } |
648 | } |
649 | |
650 | // rustdoc-stripper-ignore-next |
651 | /// Consumes the slice and returns the underlying pointer. |
652 | /// |
653 | /// This is guaranteed to be `NULL`-terminated. |
654 | #[inline ] |
655 | pub fn into_raw(mut self) -> *mut <T as GlibPtrDefault>::GlibType { |
656 | if self.len == 0 { |
657 | ptr::null_mut() |
658 | } else { |
659 | self.len = 0; |
660 | self.capacity = 0; |
661 | self.ptr.as_ptr() |
662 | } |
663 | } |
664 | |
665 | // rustdoc-stripper-ignore-next |
666 | /// Gets the length of the slice. |
667 | #[inline ] |
668 | pub fn len(&self) -> usize { |
669 | self.len |
670 | } |
671 | |
672 | // rustdoc-stripper-ignore-next |
673 | /// Returns `true` if the slice is empty. |
674 | #[inline ] |
675 | pub fn is_empty(&self) -> bool { |
676 | self.len == 0 |
677 | } |
678 | |
679 | // rustdoc-stripper-ignore-next |
680 | /// Returns the capacity of the slice. |
681 | /// |
682 | /// This includes the space that is reserved for the `NULL`-terminator. |
683 | #[inline ] |
684 | pub fn capacity(&self) -> usize { |
685 | self.capacity |
686 | } |
687 | |
688 | // rustdoc-stripper-ignore-next |
689 | /// Sets the length of the slice to `len`. |
690 | /// |
691 | /// # SAFETY |
692 | /// |
693 | /// There must be at least `len` valid items and a `NULL`-terminator after the last item. |
694 | pub unsafe fn set_len(&mut self, len: usize) { |
695 | self.len = len; |
696 | } |
697 | |
698 | // rustdoc-stripper-ignore-next |
699 | /// Reserves at least this much additional capacity. |
700 | #[allow (clippy::int_plus_one)] |
701 | pub fn reserve(&mut self, additional: usize) { |
702 | // Nothing new to reserve as there's still enough space |
703 | if self.len + additional + 1 <= self.capacity { |
704 | return; |
705 | } |
706 | |
707 | let new_capacity = |
708 | usize::next_power_of_two(std::cmp::max(self.len + additional, MIN_SIZE) + 1); |
709 | assert_ne!(new_capacity, 0); |
710 | assert!(new_capacity > self.capacity); |
711 | |
712 | unsafe { |
713 | let ptr = if self.capacity == 0 { |
714 | ptr::null_mut() |
715 | } else { |
716 | self.ptr.as_ptr() as *mut _ |
717 | }; |
718 | let new_ptr = |
719 | ffi::g_realloc(ptr, mem::size_of::<T>().checked_mul(new_capacity).unwrap()) |
720 | as *mut <T as GlibPtrDefault>::GlibType; |
721 | self.ptr = ptr::NonNull::new_unchecked(new_ptr); |
722 | self.capacity = new_capacity; |
723 | } |
724 | } |
725 | |
726 | // rustdoc-stripper-ignore-next |
727 | /// Borrows this slice as a `&[T]`. |
728 | #[inline ] |
729 | pub fn as_slice(&self) -> &[T] { |
730 | unsafe { |
731 | if self.len == 0 { |
732 | &[] |
733 | } else { |
734 | std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len) |
735 | } |
736 | } |
737 | } |
738 | |
739 | // rustdoc-stripper-ignore-next |
740 | /// Borrows this slice as a `&mut [T]`. |
741 | #[inline ] |
742 | pub fn as_mut_slice(&mut self) -> &mut [T] { |
743 | unsafe { |
744 | if self.len == 0 { |
745 | &mut [] |
746 | } else { |
747 | std::slice::from_raw_parts_mut(self.ptr.as_ptr() as *mut T, self.len) |
748 | } |
749 | } |
750 | } |
751 | |
752 | // rustdoc-stripper-ignore-next |
753 | /// Removes all items from the slice. |
754 | #[inline ] |
755 | pub fn clear(&mut self) { |
756 | unsafe { |
757 | if mem::needs_drop::<T>() { |
758 | for i in 0..self.len { |
759 | ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i) as *mut T); |
760 | } |
761 | } |
762 | |
763 | self.len = 0; |
764 | } |
765 | } |
766 | |
767 | // rustdoc-stripper-ignore-next |
768 | /// Clones and appends all elements in `slice` to the slice. |
769 | #[inline ] |
770 | pub fn extend_from_slice(&mut self, other: &[T]) { |
771 | // Nothing new to reserve as there's still enough space |
772 | if self.len + other.len() + 1 > self.capacity { |
773 | self.reserve(other.len()); |
774 | } |
775 | |
776 | unsafe { |
777 | for item in other { |
778 | ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item.clone()); |
779 | self.len += 1; |
780 | } |
781 | |
782 | ptr::write( |
783 | self.ptr.as_ptr().add(self.len), |
784 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
785 | ); |
786 | } |
787 | } |
788 | |
789 | // rustdoc-stripper-ignore-next |
790 | /// Inserts `item` at position `index` of the slice, shifting all elements after it to the |
791 | /// right. |
792 | #[inline ] |
793 | pub fn insert(&mut self, index: usize, item: T) { |
794 | assert!(index <= self.len); |
795 | |
796 | // Nothing new to reserve as there's still enough space |
797 | if self.len + 1 + 1 > self.capacity { |
798 | self.reserve(1); |
799 | } |
800 | |
801 | unsafe { |
802 | if index == self.len { |
803 | ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item); |
804 | } else { |
805 | let p = self.ptr.as_ptr().add(index); |
806 | ptr::copy(p, p.add(1), self.len - index); |
807 | ptr::write(self.ptr.as_ptr().add(index) as *mut T, item); |
808 | } |
809 | |
810 | self.len += 1; |
811 | |
812 | ptr::write( |
813 | self.ptr.as_ptr().add(self.len), |
814 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
815 | ); |
816 | } |
817 | } |
818 | |
819 | // rustdoc-stripper-ignore-next |
820 | /// Pushes `item` to the end of the slice. |
821 | #[inline ] |
822 | pub fn push(&mut self, item: T) { |
823 | // Nothing new to reserve as there's still enough space |
824 | if self.len + 1 + 1 > self.capacity { |
825 | self.reserve(1); |
826 | } |
827 | |
828 | unsafe { |
829 | ptr::write(self.ptr.as_ptr().add(self.len) as *mut T, item); |
830 | self.len += 1; |
831 | |
832 | ptr::write( |
833 | self.ptr.as_ptr().add(self.len), |
834 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
835 | ); |
836 | } |
837 | } |
838 | |
839 | // rustdoc-stripper-ignore-next |
840 | /// Removes item from position `index` of the slice, shifting all elements after it to the |
841 | /// left. |
842 | #[inline ] |
843 | pub fn remove(&mut self, index: usize) -> T { |
844 | assert!(index < self.len); |
845 | |
846 | unsafe { |
847 | let p = self.ptr.as_ptr().add(index); |
848 | let item = ptr::read(p as *mut T); |
849 | ptr::copy(p.add(1), p, self.len - index - 1); |
850 | |
851 | self.len -= 1; |
852 | |
853 | ptr::write( |
854 | self.ptr.as_ptr().add(self.len), |
855 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
856 | ); |
857 | |
858 | item |
859 | } |
860 | } |
861 | |
862 | // rustdoc-stripper-ignore-next |
863 | /// Removes the last item of the slice and returns it. |
864 | #[inline ] |
865 | pub fn pop(&mut self) -> Option<T> { |
866 | if self.len == 0 { |
867 | return None; |
868 | } |
869 | |
870 | unsafe { |
871 | self.len -= 1; |
872 | let p = self.ptr.as_ptr().add(self.len); |
873 | let item = ptr::read(p as *mut T); |
874 | |
875 | ptr::write( |
876 | self.ptr.as_ptr().add(self.len), |
877 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
878 | ); |
879 | |
880 | Some(item) |
881 | } |
882 | } |
883 | |
884 | // rustdoc-stripper-ignore-next |
885 | /// Shortens the slice by keeping the last `len` items. |
886 | /// |
887 | /// If there are fewer than `len` items then this has no effect. |
888 | #[inline ] |
889 | pub fn truncate(&mut self, len: usize) { |
890 | if self.len <= len { |
891 | return; |
892 | } |
893 | |
894 | unsafe { |
895 | while self.len > len { |
896 | self.len -= 1; |
897 | let p = self.ptr.as_ptr().add(self.len); |
898 | ptr::drop_in_place::<T>(p as *mut T); |
899 | ptr::write( |
900 | p, |
901 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
902 | ); |
903 | } |
904 | } |
905 | } |
906 | } |
907 | |
908 | impl<T: TransparentPtrType> |
909 | FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType> |
910 | for PtrSlice<T> |
911 | { |
912 | #[inline ] |
913 | unsafe fn from_glib_none_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self { |
914 | Self::from_glib_none_num(ptr, len:num, _null_terminated:false) |
915 | } |
916 | |
917 | #[inline ] |
918 | unsafe fn from_glib_container_num( |
919 | ptr: *mut <T as GlibPtrDefault>::GlibType, |
920 | num: usize, |
921 | ) -> Self { |
922 | Self::from_glib_container_num(ptr, len:num, null_terminated:false) |
923 | } |
924 | |
925 | #[inline ] |
926 | unsafe fn from_glib_full_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self { |
927 | Self::from_glib_full_num(ptr, len:num, null_terminated:false) |
928 | } |
929 | } |
930 | |
931 | impl<T: TransparentPtrType> |
932 | FromGlibContainer<<T as GlibPtrDefault>::GlibType, *const <T as GlibPtrDefault>::GlibType> |
933 | for PtrSlice<T> |
934 | { |
935 | unsafe fn from_glib_none_num(ptr: *const <T as GlibPtrDefault>::GlibType, num: usize) -> Self { |
936 | Self::from_glib_none_num(ptr, len:num, _null_terminated:false) |
937 | } |
938 | |
939 | unsafe fn from_glib_container_num( |
940 | _ptr: *const <T as GlibPtrDefault>::GlibType, |
941 | _num: usize, |
942 | ) -> Self { |
943 | unimplemented!(); |
944 | } |
945 | |
946 | unsafe fn from_glib_full_num( |
947 | _ptr: *const <T as GlibPtrDefault>::GlibType, |
948 | _num: usize, |
949 | ) -> Self { |
950 | unimplemented!(); |
951 | } |
952 | } |
953 | |
954 | impl<T: TransparentPtrType> |
955 | FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType> |
956 | for PtrSlice<T> |
957 | { |
958 | #[inline ] |
959 | unsafe fn from_glib_none(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
960 | Self::from_glib_none(ptr) |
961 | } |
962 | |
963 | #[inline ] |
964 | unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
965 | Self::from_glib_container(ptr) |
966 | } |
967 | |
968 | #[inline ] |
969 | unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self { |
970 | Self::from_glib_full(ptr) |
971 | } |
972 | } |
973 | |
974 | impl<T: TransparentPtrType> |
975 | FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *const <T as GlibPtrDefault>::GlibType> |
976 | for PtrSlice<T> |
977 | { |
978 | #[inline ] |
979 | unsafe fn from_glib_none(ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
980 | Self::from_glib_none(ptr) |
981 | } |
982 | |
983 | unsafe fn from_glib_container(_ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
984 | unimplemented!(); |
985 | } |
986 | |
987 | unsafe fn from_glib_full(_ptr: *const <T as GlibPtrDefault>::GlibType) -> Self { |
988 | unimplemented!(); |
989 | } |
990 | } |
991 | |
992 | impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *mut <T as GlibPtrDefault>::GlibType> |
993 | for PtrSlice<T> |
994 | { |
995 | type Storage = PhantomData<&'a Self>; |
996 | |
997 | #[inline ] |
998 | fn to_glib_none(&'a self) -> Stash<'a, *mut <T as GlibPtrDefault>::GlibType, Self> { |
999 | Stash(self.as_ptr() as *mut _, PhantomData) |
1000 | } |
1001 | |
1002 | #[inline ] |
1003 | fn to_glib_container(&'a self) -> Stash<'a, *mut <T as GlibPtrDefault>::GlibType, Self> { |
1004 | unsafe { |
1005 | let ptr: *mut ::GlibType = ffi::g_malloc(n_bytes:mem::size_of::<T>().checked_mul(self.len() + 1).unwrap()) |
1006 | as *mut <T as GlibPtrDefault>::GlibType; |
1007 | ptr::copy_nonoverlapping(self.as_ptr(), dst:ptr, self.len() + 1); |
1008 | Stash(ptr, PhantomData) |
1009 | } |
1010 | } |
1011 | |
1012 | #[inline ] |
1013 | fn to_glib_full(&self) -> *mut <T as GlibPtrDefault>::GlibType { |
1014 | self.clone().into_raw() |
1015 | } |
1016 | } |
1017 | |
1018 | impl<'a, T: TransparentPtrType + 'a> ToGlibPtr<'a, *const <T as GlibPtrDefault>::GlibType> |
1019 | for PtrSlice<T> |
1020 | { |
1021 | type Storage = PhantomData<&'a Self>; |
1022 | |
1023 | #[inline ] |
1024 | fn to_glib_none(&'a self) -> Stash<'a, *const <T as GlibPtrDefault>::GlibType, Self> { |
1025 | Stash(self.as_ptr(), PhantomData) |
1026 | } |
1027 | } |
1028 | |
1029 | impl<'a, T: TransparentPtrType + 'a> ToGlibPtrMut<'a, *mut <T as GlibPtrDefault>::GlibType> |
1030 | for PtrSlice<T> |
1031 | { |
1032 | type Storage = PhantomData<&'a mut Self>; |
1033 | |
1034 | #[inline ] |
1035 | fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut <T as GlibPtrDefault>::GlibType, Self> { |
1036 | StashMut(self.as_mut_ptr(), PhantomData) |
1037 | } |
1038 | } |
1039 | |
1040 | impl<T: TransparentPtrType> IntoGlibPtr<*mut <T as GlibPtrDefault>::GlibType> for PtrSlice<T> { |
1041 | #[inline ] |
1042 | unsafe fn into_glib_ptr(self) -> *mut <T as GlibPtrDefault>::GlibType { |
1043 | self.into_raw() |
1044 | } |
1045 | } |
1046 | |
1047 | impl<T: TransparentPtrType> From<super::Slice<T>> for PtrSlice<T> { |
1048 | fn from(value: super::Slice<T>) -> Self { |
1049 | let len = value.len(); |
1050 | let capacity = value.capacity(); |
1051 | unsafe { |
1052 | let ptr = value.into_raw(); |
1053 | let mut s = PtrSlice::<T> { |
1054 | ptr: ptr::NonNull::new_unchecked(ptr), |
1055 | len, |
1056 | capacity, |
1057 | }; |
1058 | |
1059 | // Reserve space for the `NULL`-terminator if needed |
1060 | if len == capacity { |
1061 | s.reserve(0); |
1062 | } |
1063 | |
1064 | ptr::write( |
1065 | s.ptr.as_ptr().add(s.len()), |
1066 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1067 | ); |
1068 | |
1069 | s |
1070 | } |
1071 | } |
1072 | } |
1073 | |
1074 | // rustdoc-stripper-ignore-next |
1075 | /// A trait to accept both `&[T]` or `PtrSlice<T>` as an argument. |
1076 | pub trait IntoPtrSlice<T: TransparentPtrType> { |
1077 | // rustdoc-stripper-ignore-next |
1078 | /// Runs the given closure with a `NULL`-terminated array. |
1079 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R; |
1080 | } |
1081 | |
1082 | impl<T: TransparentPtrType> IntoPtrSlice<T> for PtrSlice<T> { |
1083 | #[inline ] |
1084 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1085 | <&Self>::run_with_ptr_slice(&self, f) |
1086 | } |
1087 | } |
1088 | |
1089 | impl<'a, T: TransparentPtrType> IntoPtrSlice<T> for &'a PtrSlice<T> { |
1090 | #[inline ] |
1091 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1092 | f(unsafe { std::slice::from_raw_parts(self.as_ptr() as *mut _, self.len() + 1) }) |
1093 | } |
1094 | } |
1095 | |
1096 | // rustdoc-stripper-ignore-next |
1097 | /// Maximum number of pointers to stack-allocate before falling back to a heap allocation. |
1098 | const MAX_STACK_ALLOCATION: usize = 16; |
1099 | |
1100 | impl<T: TransparentPtrType> IntoPtrSlice<T> for Vec<T> { |
1101 | #[inline ] |
1102 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1103 | if self.len() < MAX_STACK_ALLOCATION { |
1104 | unsafe { |
1105 | let mut s = mem::MaybeUninit::< |
1106 | [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION], |
1107 | >::uninit(); |
1108 | let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType; |
1109 | ptr::copy_nonoverlapping( |
1110 | self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType, |
1111 | ptr, |
1112 | self.len(), |
1113 | ); |
1114 | ptr::write( |
1115 | ptr.add(self.len()), |
1116 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1117 | ); |
1118 | f(std::slice::from_raw_parts(ptr, self.len() + 1)) |
1119 | } |
1120 | } else { |
1121 | PtrSlice::<T>::from(self).run_with_ptr_slice(f) |
1122 | } |
1123 | } |
1124 | } |
1125 | |
1126 | impl<T: TransparentPtrType, const N: usize> IntoPtrSlice<T> for [T; N] { |
1127 | #[inline ] |
1128 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1129 | if self.len() < MAX_STACK_ALLOCATION { |
1130 | unsafe { |
1131 | let mut s = mem::MaybeUninit::< |
1132 | [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION], |
1133 | >::uninit(); |
1134 | let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType; |
1135 | ptr::copy_nonoverlapping( |
1136 | self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType, |
1137 | ptr, |
1138 | self.len(), |
1139 | ); |
1140 | ptr::write( |
1141 | ptr.add(self.len()), |
1142 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1143 | ); |
1144 | f(std::slice::from_raw_parts(ptr, self.len() + 1)) |
1145 | } |
1146 | } else { |
1147 | PtrSlice::<T>::from(self).run_with_ptr_slice(f) |
1148 | } |
1149 | } |
1150 | } |
1151 | |
1152 | impl<'a, T: TransparentPtrType> IntoPtrSlice<T> for &'a [T] { |
1153 | #[inline ] |
1154 | fn run_with_ptr_slice<R, F: FnOnce(&[<T as GlibPtrDefault>::GlibType]) -> R>(self, f: F) -> R { |
1155 | if self.len() < MAX_STACK_ALLOCATION { |
1156 | unsafe { |
1157 | let mut s = mem::MaybeUninit::< |
1158 | [<T as GlibPtrDefault>::GlibType; MAX_STACK_ALLOCATION], |
1159 | >::uninit(); |
1160 | let ptr = s.as_mut_ptr() as *mut <T as GlibPtrDefault>::GlibType; |
1161 | ptr::copy_nonoverlapping( |
1162 | self.as_ptr() as *mut <T as GlibPtrDefault>::GlibType, |
1163 | ptr, |
1164 | self.len(), |
1165 | ); |
1166 | ptr::write( |
1167 | ptr.add(self.len()), |
1168 | Ptr::from(ptr::null_mut::<<T as GlibPtrDefault>::GlibType>()), |
1169 | ); |
1170 | f(std::slice::from_raw_parts(ptr, self.len() + 1)) |
1171 | } |
1172 | } else { |
1173 | PtrSlice::<T>::from(self).run_with_ptr_slice(f) |
1174 | } |
1175 | } |
1176 | } |
1177 | |
1178 | #[cfg (test)] |
1179 | mod test { |
1180 | use super::*; |
1181 | |
1182 | #[test ] |
1183 | fn test_from_glib_full() { |
1184 | let items = [ |
1185 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1186 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1187 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1188 | crate::Error::new(crate::FileError::Perm, "Failed 4" ), |
1189 | ]; |
1190 | |
1191 | let slice = unsafe { |
1192 | let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut *mut ffi::GError; |
1193 | ptr::write(ptr.add(0), items[0].to_glib_full()); |
1194 | ptr::write(ptr.add(1), items[1].to_glib_full()); |
1195 | ptr::write(ptr.add(2), items[2].to_glib_full()); |
1196 | ptr::write(ptr.add(3), items[3].to_glib_full()); |
1197 | |
1198 | PtrSlice::<crate::Error>::from_glib_full_num(ptr, 4, false) |
1199 | }; |
1200 | |
1201 | for (a, b) in Iterator::zip(items.iter(), slice.iter()) { |
1202 | assert_eq!(a.message(), b.message()); |
1203 | assert_eq!( |
1204 | a.kind::<crate::FileError>().unwrap(), |
1205 | b.kind::<crate::FileError>().unwrap() |
1206 | ); |
1207 | } |
1208 | } |
1209 | |
1210 | #[test ] |
1211 | fn test_from_glib_none() { |
1212 | let items = [ |
1213 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1214 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1215 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1216 | crate::Error::new(crate::FileError::Perm, "Failed 4" ), |
1217 | ]; |
1218 | |
1219 | let slice = unsafe { |
1220 | PtrSlice::<crate::Error>::from_glib_none_num( |
1221 | items.as_ptr() as *const *mut ffi::GError, |
1222 | 4, |
1223 | false, |
1224 | ) |
1225 | }; |
1226 | |
1227 | for (a, b) in Iterator::zip(items.iter(), slice.iter()) { |
1228 | assert_eq!(a.message(), b.message()); |
1229 | assert_eq!( |
1230 | a.kind::<crate::FileError>().unwrap(), |
1231 | b.kind::<crate::FileError>().unwrap() |
1232 | ); |
1233 | } |
1234 | } |
1235 | |
1236 | #[test ] |
1237 | fn test_safe_api() { |
1238 | let items = [ |
1239 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1240 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1241 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1242 | ]; |
1243 | |
1244 | let mut slice = PtrSlice::from(&items[..]); |
1245 | assert_eq!(slice.len(), 3); |
1246 | slice.push(crate::Error::new(crate::FileError::Perm, "Failed 4" )); |
1247 | assert_eq!(slice.len(), 4); |
1248 | |
1249 | for (a, b) in Iterator::zip(items.iter(), slice.iter()) { |
1250 | assert_eq!(a.message(), b.message()); |
1251 | assert_eq!( |
1252 | a.kind::<crate::FileError>().unwrap(), |
1253 | b.kind::<crate::FileError>().unwrap() |
1254 | ); |
1255 | } |
1256 | assert_eq!(slice[3].message(), "Failed 4" ); |
1257 | |
1258 | let vec = Vec::from(slice); |
1259 | assert_eq!(vec.len(), 4); |
1260 | for (a, b) in Iterator::zip(items.iter(), vec.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!(vec[3].message(), "Failed 4" ); |
1268 | |
1269 | let mut slice = PtrSlice::from(vec); |
1270 | assert_eq!(slice.len(), 4); |
1271 | let e = slice.pop().unwrap(); |
1272 | assert_eq!(e.message(), "Failed 4" ); |
1273 | assert_eq!(slice.len(), 3); |
1274 | slice.insert(2, e); |
1275 | assert_eq!(slice.len(), 4); |
1276 | assert_eq!(slice[0].message(), "Failed 1" ); |
1277 | assert_eq!(slice[1].message(), "Failed 2" ); |
1278 | assert_eq!(slice[2].message(), "Failed 4" ); |
1279 | assert_eq!(slice[3].message(), "Failed 3" ); |
1280 | let e = slice.remove(2); |
1281 | assert_eq!(e.message(), "Failed 4" ); |
1282 | assert_eq!(slice.len(), 3); |
1283 | slice.push(e); |
1284 | assert_eq!(slice.len(), 4); |
1285 | |
1286 | let slice2 = crate::Slice::from(slice.clone()); |
1287 | |
1288 | for (a, b) in Iterator::zip(items.iter(), slice.into_iter()) { |
1289 | assert_eq!(a.message(), b.message()); |
1290 | assert_eq!( |
1291 | a.kind::<crate::FileError>().unwrap(), |
1292 | b.kind::<crate::FileError>().unwrap() |
1293 | ); |
1294 | } |
1295 | |
1296 | let slice3 = crate::PtrSlice::from(slice2.clone()); |
1297 | |
1298 | for (a, b) in Iterator::zip(items.iter(), slice2.into_iter()) { |
1299 | assert_eq!(a.message(), b.message()); |
1300 | assert_eq!( |
1301 | a.kind::<crate::FileError>().unwrap(), |
1302 | b.kind::<crate::FileError>().unwrap() |
1303 | ); |
1304 | } |
1305 | |
1306 | for (a, b) in Iterator::zip(items.iter(), slice3.into_iter()) { |
1307 | assert_eq!(a.message(), b.message()); |
1308 | assert_eq!( |
1309 | a.kind::<crate::FileError>().unwrap(), |
1310 | b.kind::<crate::FileError>().unwrap() |
1311 | ); |
1312 | } |
1313 | } |
1314 | |
1315 | #[test ] |
1316 | fn test_into_ptrslice() { |
1317 | let items = [ |
1318 | crate::Error::new(crate::FileError::Failed, "Failed 1" ), |
1319 | crate::Error::new(crate::FileError::Noent, "Failed 2" ), |
1320 | crate::Error::new(crate::FileError::Io, "Failed 3" ), |
1321 | crate::Error::new(crate::FileError::Perm, "Failed 4" ), |
1322 | ]; |
1323 | |
1324 | items[..].run_with_ptr_slice(|s| unsafe { |
1325 | assert!(s[4].is_null()); |
1326 | assert_eq!(s.len(), items.len() + 1); |
1327 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len()); |
1328 | assert_eq!(s, items); |
1329 | }); |
1330 | |
1331 | Vec::from(&items[..]).run_with_ptr_slice(|s| unsafe { |
1332 | assert!(s[4].is_null()); |
1333 | assert_eq!(s.len(), items.len() + 1); |
1334 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len()); |
1335 | for (a, b) in Iterator::zip(items.iter(), s.iter()) { |
1336 | assert_eq!(a.message(), b.message()); |
1337 | assert_eq!( |
1338 | a.kind::<crate::FileError>().unwrap(), |
1339 | b.kind::<crate::FileError>().unwrap() |
1340 | ); |
1341 | } |
1342 | }); |
1343 | |
1344 | PtrSlice::<crate::Error>::from(&items[..]).run_with_ptr_slice(|s| unsafe { |
1345 | assert!(s[4].is_null()); |
1346 | assert_eq!(s.len(), items.len() + 1); |
1347 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, items.len()); |
1348 | for (a, b) in Iterator::zip(items.iter(), s.iter()) { |
1349 | assert_eq!(a.message(), b.message()); |
1350 | assert_eq!( |
1351 | a.kind::<crate::FileError>().unwrap(), |
1352 | b.kind::<crate::FileError>().unwrap() |
1353 | ); |
1354 | } |
1355 | }); |
1356 | |
1357 | let v = Vec::from(&items[..]); |
1358 | items.run_with_ptr_slice(|s| unsafe { |
1359 | assert!(s[4].is_null()); |
1360 | assert_eq!(s.len(), v.len() + 1); |
1361 | let s = std::slice::from_raw_parts(s.as_ptr() as *const crate::Error, v.len()); |
1362 | for (a, b) in Iterator::zip(v.iter(), s.iter()) { |
1363 | assert_eq!(a.message(), b.message()); |
1364 | assert_eq!( |
1365 | a.kind::<crate::FileError>().unwrap(), |
1366 | b.kind::<crate::FileError>().unwrap() |
1367 | ); |
1368 | } |
1369 | }); |
1370 | } |
1371 | } |
1372 | |