1#[cfg(not(windows))]
134use std::os::unix::prelude::*;
135use std::{
136 borrow::Cow,
137 char,
138 cmp::Ordering,
139 collections::HashMap,
140 error::Error,
141 ffi::{CStr, CString, OsStr, OsString},
142 fmt,
143 marker::PhantomData,
144 mem,
145 path::{Path, PathBuf},
146 ptr,
147};
148
149pub use crate::collections::{ptr_slice::IntoPtrSlice, strv::IntoStrV};
150use crate::ffi;
151pub use crate::gstring::{IntoGStr, IntoOptionalGStr};
152
153use libc::{c_char, size_t};
154
155pub trait Ptr: Copy + 'static {
158 fn is_null(&self) -> bool;
159 fn from<X>(ptr: *mut X) -> Self;
160 fn to<X>(self) -> *mut X;
161}
162
163impl<T: 'static> Ptr for *const T {
164 #[inline]
165 fn is_null(&self) -> bool {
166 (*self).is_null()
167 }
168
169 #[inline]
170 fn from<X>(ptr: *mut X) -> *const T {
171 ptr as *const T
172 }
173
174 #[inline]
175 fn to<X>(self) -> *mut X {
176 self as *mut X
177 }
178}
179
180impl<T: 'static> Ptr for *mut T {
181 #[inline]
182 fn is_null(&self) -> bool {
183 (*self).is_null()
184 }
185
186 #[inline]
187 fn from<X>(ptr: *mut X) -> *mut T {
188 ptr as *mut T
189 }
190
191 #[inline]
192 fn to<X>(self) -> *mut X {
193 self as *mut X
194 }
195}
196
197#[inline]
202pub fn mut_override<T>(ptr: *const T) -> *mut T {
203 ptr as *mut T
204}
205
206#[inline]
212pub fn const_override<T>(ptr: *mut T) -> *const T {
213 ptr as *const T
214}
215
216pub trait Uninitialized {
219 unsafe fn uninitialized() -> Self;
221}
222
223#[inline]
226pub unsafe fn uninitialized<T: Uninitialized>() -> T {
227 unsafe { T::uninitialized() }
228}
229
230pub struct Stash<'a, P: Copy, T: ?Sized + ToGlibPtr<'a, P>>(
260 pub P,
261 pub <T as ToGlibPtr<'a, P>>::Storage,
262);
263
264pub struct StashMut<'a, P: Copy, T: ?Sized>(pub P, pub <T as ToGlibPtrMut<'a, P>>::Storage)
265where
266 T: ToGlibPtrMut<'a, P>;
267
268#[derive(Debug)]
277pub struct Borrowed<T>(mem::ManuallyDrop<T>);
278
279impl<T> Borrowed<T> {
280 #[inline]
283 pub fn new(val: T) -> Self {
284 Self(mem::ManuallyDrop::new(val))
285 }
286
287 #[inline]
295 pub unsafe fn into_inner(self) -> T {
296 mem::ManuallyDrop::into_inner(self.0)
297 }
298}
299
300impl<T> AsRef<T> for Borrowed<T> {
301 #[inline]
302 fn as_ref(&self) -> &T {
303 &self.0
304 }
305}
306
307impl<T> std::ops::Deref for Borrowed<T> {
308 type Target = T;
309
310 #[inline]
311 fn deref(&self) -> &T {
312 &self.0
313 }
314}
315
316pub trait UnsafeFrom<T> {
319 unsafe fn unsafe_from(t: T) -> Self;
327}
328
329pub trait IntoGlib {
332 type GlibType: Copy;
333
334 fn into_glib(self) -> Self::GlibType;
335}
336
337impl IntoGlib for bool {
338 type GlibType = ffi::gboolean;
339
340 #[inline]
341 fn into_glib(self) -> ffi::gboolean {
342 if self { ffi::GTRUE } else { ffi::GFALSE }
343 }
344}
345
346impl IntoGlib for char {
347 type GlibType = u32;
348
349 #[inline]
350 fn into_glib(self) -> u32 {
351 self as u32
352 }
353}
354
355unsafe impl TransparentType for char {
356 type GlibType = u32;
357}
358
359impl IntoGlib for Option<char> {
360 type GlibType = u32;
361
362 #[inline]
363 fn into_glib(self) -> u32 {
364 self.as_ref().map(|&c| c as u32).unwrap_or(0)
365 }
366}
367
368impl IntoGlib for Ordering {
369 type GlibType = i32;
370
371 #[inline]
372 fn into_glib(self) -> i32 {
373 match self {
374 Ordering::Less => -1,
375 Ordering::Equal => 0,
376 Ordering::Greater => 1,
377 }
378 }
379}
380
381impl<O, E, G> IntoGlib for Result<O, E>
382where
383 G: Copy,
384 O: IntoGlib<GlibType = G> + TryFromGlib<G, Error = E>,
385 E: IntoGlib<GlibType = G>,
386{
387 type GlibType = G;
388
389 #[inline]
390 fn into_glib(self) -> Self::GlibType {
391 match self {
392 Ok(ok) => ok.into_glib(),
393 Err(err) => err.into_glib(),
394 }
395 }
396}
397
398pub trait OptionIntoGlib: IntoGlib {
401 const GLIB_NONE: Self::GlibType;
402}
403
404impl<T: OptionIntoGlib> IntoGlib for Option<T> {
405 type GlibType = T::GlibType;
406
407 #[inline]
408 fn into_glib(self) -> Self::GlibType {
409 match self {
410 Some(t) => t.into_glib(),
411 None => T::GLIB_NONE,
412 }
413 }
414}
415
416pub trait GlibPtrDefault {
421 type GlibType: Ptr;
422}
423
424impl<T: ?Sized + GlibPtrDefault> GlibPtrDefault for &T {
425 type GlibType = <T as GlibPtrDefault>::GlibType;
426}
427
428pub trait ToGlibPtr<'a, P: Copy> {
431 type Storage;
432
433 fn to_glib_none(&'a self) -> Stash<'a, P, Self>;
438
439 fn to_glib_container(&'a self) -> Stash<'a, P, Self> {
445 unimplemented!();
446 }
447
448 fn to_glib_full(&self) -> P {
453 unimplemented!();
454 }
455}
456
457pub trait ToGlibPtrMut<'a, P: Copy> {
460 type Storage;
461
462 #[allow(clippy::wrong_self_convention)]
467 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, P, Self>;
468}
469
470impl<'a, P: Ptr, T: ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for Option<T> {
471 type Storage = Option<<T as ToGlibPtr<'a, P>>::Storage>;
472
473 #[inline]
474 fn to_glib_none(&'a self) -> Stash<'a, P, Option<T>> {
475 self.as_ref()
476 .map_or(Stash(Ptr::from::<()>(ptr::null_mut()), None), |s| {
477 let s = s.to_glib_none();
478 Stash(s.0, Some(s.1))
479 })
480 }
481
482 #[inline]
483 fn to_glib_full(&self) -> P {
484 self.as_ref()
485 .map_or(Ptr::from::<()>(ptr::null_mut()), ToGlibPtr::to_glib_full)
486 }
487}
488
489impl<'a, 'opt: 'a, P: Ptr, T: ToGlibPtrMut<'a, P>> ToGlibPtrMut<'a, P> for Option<&'opt mut T> {
490 type Storage = Option<<T as ToGlibPtrMut<'a, P>>::Storage>;
491
492 #[inline]
493 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, P, Option<&'opt mut T>> {
494 self.as_mut()
495 .map_or(StashMut(Ptr::from::<()>(ptr::null_mut()), None), |s| {
496 let s = s.to_glib_none_mut();
497 StashMut(s.0, Some(s.1))
498 })
499 }
500}
501
502impl<'a, P: Ptr, T: ?Sized + ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for &'a T {
503 type Storage = <T as ToGlibPtr<'a, P>>::Storage;
504
505 #[inline]
506 fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
507 let s = (*self).to_glib_none();
508 Stash(s.0, s.1)
509 }
510
511 #[inline]
512 fn to_glib_full(&self) -> P {
513 (*self).to_glib_full()
514 }
515}
516
517#[doc(hidden)]
518#[derive(Debug)]
519pub enum CowStash<B, O> {
520 Borrowed(B),
521 Owned(O),
522}
523
524impl<'a, P: Ptr, T> ToGlibPtr<'a, P> for Cow<'a, T>
525where
526 T: ToOwned + ?Sized + ToGlibPtr<'a, P>,
527 T::Owned: ToGlibPtr<'a, P>,
528{
529 type Storage = CowStash<T::Storage, <T::Owned as ToGlibPtr<'a, P>>::Storage>;
530
531 #[inline]
532 fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
533 match self {
534 Cow::Borrowed(v) => {
535 let s = v.to_glib_none();
536 Stash(s.0, CowStash::Borrowed(s.1))
537 }
538 Cow::Owned(v) => {
539 let s = v.to_glib_none();
540 Stash(s.0, CowStash::Owned(s.1))
541 }
542 }
543 }
544
545 #[inline]
546 fn to_glib_full(&self) -> P {
547 match self {
548 Cow::Borrowed(v) => v.to_glib_full(),
549 Cow::Owned(v) => v.to_glib_full(),
550 }
551 }
552}
553
554impl<'a> ToGlibPtr<'a, *const c_char> for str {
555 type Storage = Cow<'static, [u8]>;
556
557 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
558 static EMPTY_STRING: &[u8] = &[0];
559
560 let bytes = if self.is_empty() {
561 Cow::Borrowed(EMPTY_STRING)
562 } else {
563 if cfg!(debug_assertions) {
564 crate::GStr::check_interior_nuls(self).unwrap();
565 }
566 let mut bytes = Vec::with_capacity(self.len() + 1);
567 unsafe {
568 ptr::copy_nonoverlapping(self.as_ptr(), bytes.as_mut_ptr(), self.len());
569 bytes.as_mut_ptr().add(self.len()).write(0);
570 bytes.set_len(self.len() + 1);
571 }
572 Cow::Owned(bytes)
573 };
574 Stash(bytes.as_ptr() as *const c_char, bytes)
575 }
576
577 #[inline]
578 fn to_glib_full(&self) -> *const c_char {
579 if cfg!(debug_assertions) {
580 crate::GStr::check_interior_nuls(self).unwrap();
581 }
582 unsafe {
583 ffi::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *const c_char
584 }
585 }
586}
587
588impl<'a> ToGlibPtr<'a, *mut c_char> for str {
589 type Storage = Cow<'static, [u8]>;
590
591 #[inline]
592 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
593 let s = ToGlibPtr::<*const c_char>::to_glib_none(self);
594 Stash(s.0 as *mut _, s.1)
595 }
596
597 #[inline]
598 fn to_glib_full(&self) -> *mut c_char {
599 ToGlibPtr::<*const c_char>::to_glib_full(self) as *mut _
600 }
601}
602
603impl<'a> ToGlibPtr<'a, *const c_char> for String {
604 type Storage = Cow<'static, [u8]>;
605
606 #[inline]
607 fn to_glib_none(&self) -> Stash<'a, *const c_char, String> {
608 let s = ToGlibPtr::to_glib_none(self.as_str());
609 Stash(s.0, s.1)
610 }
611
612 #[inline]
613 fn to_glib_full(&self) -> *const c_char {
614 ToGlibPtr::to_glib_full(self.as_str())
615 }
616}
617
618impl<'a> ToGlibPtr<'a, *mut c_char> for String {
619 type Storage = Cow<'static, [u8]>;
620
621 #[inline]
622 fn to_glib_none(&self) -> Stash<'a, *mut c_char, String> {
623 let s = ToGlibPtr::to_glib_none(self.as_str());
624 Stash(s.0, s.1)
625 }
626
627 #[inline]
628 fn to_glib_full(&self) -> *mut c_char {
629 ToGlibPtr::to_glib_full(self.as_str())
630 }
631}
632
633impl<'a> ToGlibPtr<'a, *const c_char> for CStr {
634 type Storage = PhantomData<&'a Self>;
635
636 #[inline]
637 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
638 Stash(self.as_ptr(), PhantomData)
639 }
640
641 #[inline]
642 fn to_glib_full(&self) -> *const c_char {
643 unsafe {
644 ffi::g_strndup(
645 self.as_ptr() as *const c_char,
646 self.to_bytes().len() as size_t,
647 ) as *const c_char
648 }
649 }
650}
651
652impl<'a> ToGlibPtr<'a, *mut c_char> for CStr {
653 type Storage = PhantomData<&'a Self>;
654
655 #[inline]
656 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
657 Stash(self.as_ptr() as *mut c_char, PhantomData)
658 }
659
660 #[inline]
661 fn to_glib_full(&self) -> *mut c_char {
662 unsafe {
663 ffi::g_strndup(
664 self.as_ptr() as *const c_char,
665 self.to_bytes().len() as size_t,
666 ) as *mut c_char
667 }
668 }
669}
670
671impl<'a> ToGlibPtr<'a, *const c_char> for CString {
672 type Storage = PhantomData<&'a Self>;
673
674 #[inline]
675 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
676 Stash(self.as_ptr(), PhantomData)
677 }
678
679 #[inline]
680 fn to_glib_full(&self) -> *const c_char {
681 unsafe {
682 ffi::g_strndup(
683 self.as_ptr() as *const c_char,
684 self.as_bytes().len() as size_t,
685 ) as *const c_char
686 }
687 }
688}
689
690impl<'a> ToGlibPtr<'a, *mut c_char> for CString {
691 type Storage = PhantomData<&'a Self>;
692
693 #[inline]
694 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
695 Stash(self.as_ptr() as *mut c_char, PhantomData)
696 }
697
698 #[inline]
699 fn to_glib_full(&self) -> *mut c_char {
700 unsafe {
701 ffi::g_strndup(
702 self.as_ptr() as *const c_char,
703 self.as_bytes().len() as size_t,
704 ) as *mut c_char
705 }
706 }
707}
708
709pub trait IntoGlibPtr<P: Ptr> {
712 #[allow(clippy::wrong_self_convention)]
715 fn into_glib_ptr(self) -> P;
716}
717
718impl<P: Ptr, T: IntoGlibPtr<P>> IntoGlibPtr<P> for Option<T> {
719 #[inline]
720 fn into_glib_ptr(self) -> P {
721 self.map_or(Ptr::from::<()>(ptr::null_mut()), |s| {
722 IntoGlibPtr::into_glib_ptr(s)
723 })
724 }
725}
726
727impl GlibPtrDefault for str {
728 type GlibType = *mut c_char;
729}
730
731impl GlibPtrDefault for String {
732 type GlibType = *mut c_char;
733}
734
735#[cfg(not(windows))]
736pub(crate) fn path_to_c(path: &Path) -> CString {
737 CString::new(path.as_os_str().as_bytes()).expect("Invalid path with NUL bytes")
743}
744
745#[cfg(windows)]
746pub(crate) fn path_to_c(path: &Path) -> CString {
747 let path_str = path
756 .to_str()
757 .expect("Path can't be represented as UTF-8")
758 .to_owned();
759
760 if path_str.starts_with("\\\\?\\") {
766 CString::new(path_str[4..].as_bytes())
767 } else {
768 CString::new(path_str.as_bytes())
769 }
770 .expect("Invalid path with NUL bytes")
771}
772
773#[cfg(not(windows))]
774pub(crate) fn os_str_to_c(s: &OsStr) -> CString {
775 CString::new(s.as_bytes()).expect("Invalid OS String with NUL bytes")
782}
783
784#[cfg(windows)]
785pub(crate) fn os_str_to_c(s: &OsStr) -> CString {
786 let os_str = s
795 .to_str()
796 .expect("OS String can't be represented as UTF-8")
797 .to_owned();
798
799 CString::new(os_str.as_bytes()).expect("Invalid OS string with NUL bytes")
800}
801
802impl<'a> ToGlibPtr<'a, *const c_char> for Path {
803 type Storage = CString;
804
805 #[inline]
806 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
807 let tmp = path_to_c(self);
808 Stash(tmp.as_ptr(), tmp)
809 }
810}
811
812impl<'a> ToGlibPtr<'a, *mut c_char> for Path {
813 type Storage = CString;
814
815 #[inline]
816 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
817 let tmp = path_to_c(self);
818 Stash(tmp.as_ptr() as *mut c_char, tmp)
819 }
820
821 #[inline]
822 fn to_glib_full(&self) -> *mut c_char {
823 let tmp = path_to_c(self);
824 unsafe { ffi::g_strdup(tmp.as_ptr()) }
825 }
826}
827
828impl<'a> ToGlibPtr<'a, *const c_char> for PathBuf {
829 type Storage = CString;
830
831 #[inline]
832 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
833 let tmp = path_to_c(self);
834 Stash(tmp.as_ptr(), tmp)
835 }
836}
837
838impl<'a> ToGlibPtr<'a, *mut c_char> for PathBuf {
839 type Storage = CString;
840
841 #[inline]
842 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
843 let tmp = path_to_c(self);
844 Stash(tmp.as_ptr() as *mut c_char, tmp)
845 }
846
847 #[inline]
848 fn to_glib_full(&self) -> *mut c_char {
849 let tmp = path_to_c(self);
850 unsafe { ffi::g_strdup(tmp.as_ptr()) }
851 }
852}
853
854impl GlibPtrDefault for Path {
855 type GlibType = *mut c_char;
856}
857
858impl GlibPtrDefault for PathBuf {
859 type GlibType = *mut c_char;
860}
861
862impl<'a> ToGlibPtr<'a, *const c_char> for OsStr {
863 type Storage = CString;
864
865 #[inline]
866 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
867 let tmp = os_str_to_c(self);
868 Stash(tmp.as_ptr(), tmp)
869 }
870}
871
872impl<'a> ToGlibPtr<'a, *mut c_char> for OsStr {
873 type Storage = CString;
874
875 #[inline]
876 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
877 let tmp = os_str_to_c(self);
878 Stash(tmp.as_ptr() as *mut c_char, tmp)
879 }
880
881 #[inline]
882 fn to_glib_full(&self) -> *mut c_char {
883 let tmp = os_str_to_c(self);
884 unsafe { ffi::g_strdup(tmp.as_ptr()) }
885 }
886}
887
888impl<'a> ToGlibPtr<'a, *const c_char> for OsString {
889 type Storage = CString;
890
891 #[inline]
892 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
893 let tmp = os_str_to_c(self);
894 Stash(tmp.as_ptr(), tmp)
895 }
896}
897
898impl<'a> ToGlibPtr<'a, *mut c_char> for OsString {
899 type Storage = CString;
900
901 #[inline]
902 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
903 let tmp = os_str_to_c(self);
904 Stash(tmp.as_ptr() as *mut c_char, tmp)
905 }
906
907 #[inline]
908 fn to_glib_full(&self) -> *mut c_char {
909 let tmp = os_str_to_c(self);
910 unsafe { ffi::g_strdup(tmp.as_ptr()) }
911 }
912}
913
914impl GlibPtrDefault for OsStr {
915 type GlibType = *mut c_char;
916}
917
918impl GlibPtrDefault for OsString {
919 type GlibType = *mut c_char;
920}
921
922pub trait ToGlibContainerFromSlice<'a, P>
923where
924 Self: Sized,
925{
926 type Storage;
927
928 #[allow(clippy::wrong_self_convention)]
929 fn to_glib_none_from_slice(t: &'a [Self]) -> (P, Self::Storage);
930 #[allow(clippy::wrong_self_convention)]
931 fn to_glib_container_from_slice(t: &'a [Self]) -> (P, Self::Storage);
932 #[allow(clippy::wrong_self_convention)]
933 fn to_glib_full_from_slice(t: &[Self]) -> P;
934}
935
936macro_rules! impl_to_glib_container_from_slice_fundamental {
937 ($name:ty) => {
938 impl<'a> ToGlibContainerFromSlice<'a, *mut $name> for $name {
939 type Storage = std::marker::PhantomData<&'a [$name]>;
940
941 #[inline]
942 fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut $name, Self::Storage) {
943 (t.as_ptr() as *mut $name, std::marker::PhantomData)
944 }
945
946 #[inline]
947 fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut $name, Self::Storage) {
948 (
949 ToGlibContainerFromSlice::to_glib_full_from_slice(t),
950 std::marker::PhantomData,
951 )
952 }
953
954 #[inline]
955 fn to_glib_full_from_slice(t: &[$name]) -> *mut $name {
956 if t.len() == 0 {
957 return ptr::null_mut();
958 }
959
960 unsafe {
961 let res = ffi::g_malloc(mem::size_of_val(t)) as *mut $name;
962 ptr::copy_nonoverlapping(t.as_ptr(), res, t.len());
963 res
964 }
965 }
966 }
967 };
968}
969
970impl_to_glib_container_from_slice_fundamental!(u8);
971impl_to_glib_container_from_slice_fundamental!(i8);
972impl_to_glib_container_from_slice_fundamental!(u16);
973impl_to_glib_container_from_slice_fundamental!(i16);
974impl_to_glib_container_from_slice_fundamental!(u32);
975impl_to_glib_container_from_slice_fundamental!(i32);
976impl_to_glib_container_from_slice_fundamental!(u64);
977impl_to_glib_container_from_slice_fundamental!(i64);
978impl_to_glib_container_from_slice_fundamental!(f32);
979impl_to_glib_container_from_slice_fundamental!(f64);
980
981macro_rules! impl_to_glib_container_from_slice_string {
982 ($name:ty, $ffi_name:ty) => {
983 impl<'a> ToGlibContainerFromSlice<'a, *mut $ffi_name> for $name {
984 type Storage = (Vec<Stash<'a, $ffi_name, $name>>, Option<Vec<$ffi_name>>);
985
986 fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut $ffi_name, Self::Storage) {
987 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
988 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
989 v_ptr.push(ptr::null_mut() as $ffi_name);
990
991 (v_ptr.as_ptr() as *mut $ffi_name, (v, Some(v_ptr)))
992 }
993
994 fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut $ffi_name, Self::Storage) {
995 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
996
997 let v_ptr = unsafe {
998 let v_ptr = ffi::g_malloc(mem::size_of::<$ffi_name>() * (t.len() + 1))
999 as *mut $ffi_name;
1000
1001 for (i, s) in v.iter().enumerate() {
1002 ptr::write(v_ptr.add(i), s.0);
1003 }
1004 ptr::write(v_ptr.add(t.len()), ptr::null_mut());
1005
1006 v_ptr
1007 };
1008
1009 (v_ptr, (v, None))
1010 }
1011
1012 fn to_glib_full_from_slice(t: &[$name]) -> *mut $ffi_name {
1013 unsafe {
1014 let v_ptr = ffi::g_malloc(mem::size_of::<$ffi_name>() * (t.len() + 1))
1015 as *mut $ffi_name;
1016
1017 for (i, s) in t.iter().enumerate() {
1018 ptr::write(v_ptr.add(i), s.to_glib_full());
1019 }
1020 ptr::write(v_ptr.add(t.len()), ptr::null_mut());
1021
1022 v_ptr
1023 }
1024 }
1025 }
1026 impl<'a> ToGlibContainerFromSlice<'a, *const $ffi_name> for $name {
1027 type Storage = (Vec<Stash<'a, $ffi_name, $name>>, Option<Vec<$ffi_name>>);
1028
1029 fn to_glib_none_from_slice(t: &'a [$name]) -> (*const $ffi_name, Self::Storage) {
1030 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
1031 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
1032 v_ptr.push(ptr::null_mut() as $ffi_name);
1033
1034 (v_ptr.as_ptr() as *const $ffi_name, (v, Some(v_ptr)))
1035 }
1036
1037 fn to_glib_container_from_slice(t: &'a [$name]) -> (*const $ffi_name, Self::Storage) {
1038 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
1039
1040 let v_ptr = unsafe {
1041 let v_ptr = ffi::g_malloc(mem::size_of::<$ffi_name>() * (t.len() + 1))
1042 as *mut $ffi_name;
1043
1044 for (i, s) in v.iter().enumerate() {
1045 ptr::write(v_ptr.add(i), s.0);
1046 }
1047 ptr::write(v_ptr.add(t.len()), ptr::null_mut());
1048
1049 v_ptr as *const $ffi_name
1050 };
1051
1052 (v_ptr, (v, None))
1053 }
1054
1055 fn to_glib_full_from_slice(t: &[$name]) -> *const $ffi_name {
1056 unsafe {
1057 let v_ptr = ffi::g_malloc(mem::size_of::<$ffi_name>() * (t.len() + 1))
1058 as *mut $ffi_name;
1059
1060 for (i, s) in t.iter().enumerate() {
1061 ptr::write(v_ptr.add(i), s.to_glib_full());
1062 }
1063 ptr::write(v_ptr.add(t.len()), ptr::null_mut());
1064
1065 v_ptr as *const $ffi_name
1066 }
1067 }
1068 }
1069 };
1070}
1071
1072impl_to_glib_container_from_slice_string!(&'a str, *mut c_char);
1073impl_to_glib_container_from_slice_string!(&'a str, *const c_char);
1074impl_to_glib_container_from_slice_string!(String, *mut c_char);
1075impl_to_glib_container_from_slice_string!(String, *const c_char);
1076impl_to_glib_container_from_slice_string!(&'a Path, *mut c_char);
1077impl_to_glib_container_from_slice_string!(&'a Path, *const c_char);
1078impl_to_glib_container_from_slice_string!(PathBuf, *mut c_char);
1079impl_to_glib_container_from_slice_string!(PathBuf, *const c_char);
1080impl_to_glib_container_from_slice_string!(&'a OsStr, *mut c_char);
1081impl_to_glib_container_from_slice_string!(&'a OsStr, *const c_char);
1082impl_to_glib_container_from_slice_string!(OsString, *mut c_char);
1083impl_to_glib_container_from_slice_string!(OsString, *const c_char);
1084impl_to_glib_container_from_slice_string!(&'a CStr, *mut c_char);
1085impl_to_glib_container_from_slice_string!(&'a CStr, *const c_char);
1086impl_to_glib_container_from_slice_string!(CString, *mut c_char);
1087impl_to_glib_container_from_slice_string!(CString, *const c_char);
1088impl_to_glib_container_from_slice_string!(crate::GString, *mut c_char);
1089impl_to_glib_container_from_slice_string!(crate::GString, *const c_char);
1090
1091impl<'a, T> ToGlibContainerFromSlice<'a, *mut ffi::GList> for T
1092where
1093 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
1094{
1095 type Storage = (
1096 Option<List>,
1097 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
1098 );
1099
1100 #[inline]
1101 fn to_glib_none_from_slice(t: &'a [T]) -> (*mut ffi::GList, Self::Storage) {
1102 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
1103 let mut list: *mut ffi::GList = ptr::null_mut();
1104 unsafe {
1105 for stash in &stash_vec {
1106 list = ffi::g_list_prepend(list, Ptr::to(stash.0));
1107 }
1108 }
1109 let stash = (ptr::NonNull::new(list).map(List), stash_vec);
1110 (list, stash)
1111 }
1112
1113 #[inline]
1114 fn to_glib_container_from_slice(t: &'a [T]) -> (*mut ffi::GList, Self::Storage) {
1115 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
1116 let mut list: *mut ffi::GList = ptr::null_mut();
1117 unsafe {
1118 for stash in &stash_vec {
1119 list = ffi::g_list_prepend(list, Ptr::to(stash.0));
1120 }
1121 }
1122 (list, (None, stash_vec))
1123 }
1124
1125 #[inline]
1126 fn to_glib_full_from_slice(t: &[T]) -> *mut ffi::GList {
1127 let mut list: *mut ffi::GList = ptr::null_mut();
1128 unsafe {
1129 for ptr in t.iter().rev().map(ToGlibPtr::to_glib_full) {
1130 list = ffi::g_list_prepend(list, Ptr::to(ptr));
1131 }
1132 }
1133 list
1134 }
1135}
1136
1137impl<'a, T> ToGlibContainerFromSlice<'a, *const ffi::GList> for T
1138where
1139 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
1140{
1141 type Storage = (
1142 Option<List>,
1143 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
1144 );
1145
1146 #[inline]
1147 fn to_glib_none_from_slice(t: &'a [T]) -> (*const ffi::GList, Self::Storage) {
1148 let (list, stash) = ToGlibContainerFromSlice::<*mut ffi::GList>::to_glib_none_from_slice(t);
1149 (list as *const ffi::GList, stash)
1150 }
1151
1152 #[inline]
1153 fn to_glib_container_from_slice(_t: &'a [T]) -> (*const ffi::GList, Self::Storage) {
1154 unimplemented!()
1155 }
1156
1157 #[inline]
1158 fn to_glib_full_from_slice(_t: &[T]) -> *const ffi::GList {
1159 unimplemented!()
1160 }
1161}
1162
1163#[doc(alias = "GList")]
1164pub struct List(ptr::NonNull<ffi::GList>);
1165
1166impl Drop for List {
1167 #[inline]
1168 fn drop(&mut self) {
1169 unsafe { ffi::g_list_free(self.0.as_ptr()) }
1170 }
1171}
1172
1173impl<'a, T> ToGlibContainerFromSlice<'a, *mut ffi::GSList> for &'a T
1174where
1175 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
1176{
1177 type Storage = (
1178 Option<SList>,
1179 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
1180 );
1181
1182 #[inline]
1183 fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*mut ffi::GSList, Self::Storage) {
1184 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
1185 let mut list: *mut ffi::GSList = ptr::null_mut();
1186 unsafe {
1187 for stash in &stash_vec {
1188 list = ffi::g_slist_prepend(list, Ptr::to(stash.0));
1189 }
1190 }
1191
1192 let stash = (ptr::NonNull::new(list).map(SList), stash_vec);
1193 (list, stash)
1194 }
1195
1196 #[inline]
1197 fn to_glib_container_from_slice(t: &'a [&'a T]) -> (*mut ffi::GSList, Self::Storage) {
1198 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
1199 let mut list: *mut ffi::GSList = ptr::null_mut();
1200 unsafe {
1201 for stash in &stash_vec {
1202 list = ffi::g_slist_prepend(list, Ptr::to(stash.0));
1203 }
1204 }
1205 (list, (None, stash_vec))
1206 }
1207
1208 #[inline]
1209 fn to_glib_full_from_slice(t: &[&'a T]) -> *mut ffi::GSList {
1210 let mut list: *mut ffi::GSList = ptr::null_mut();
1211 unsafe {
1212 for ptr in t.iter().rev().map(ToGlibPtr::to_glib_full) {
1213 list = ffi::g_slist_prepend(list, Ptr::to(ptr));
1214 }
1215 }
1216 list
1217 }
1218}
1219
1220impl<'a, T> ToGlibContainerFromSlice<'a, *const ffi::GSList> for &'a T
1221where
1222 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
1223{
1224 type Storage = (
1225 Option<SList>,
1226 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
1227 );
1228
1229 #[inline]
1230 fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*const ffi::GSList, Self::Storage) {
1231 let (list, stash) =
1232 ToGlibContainerFromSlice::<*mut ffi::GSList>::to_glib_none_from_slice(t);
1233 (list as *const ffi::GSList, stash)
1234 }
1235
1236 #[inline]
1237 fn to_glib_container_from_slice(_t: &'a [&'a T]) -> (*const ffi::GSList, Self::Storage) {
1238 unimplemented!()
1239 }
1240
1241 #[inline]
1242 fn to_glib_full_from_slice(_t: &[&'a T]) -> *const ffi::GSList {
1243 unimplemented!()
1244 }
1245}
1246
1247#[doc(alias = "GSList")]
1248pub struct SList(ptr::NonNull<ffi::GSList>);
1249
1250impl Drop for SList {
1251 #[inline]
1252 fn drop(&mut self) {
1253 unsafe { ffi::g_slist_free(self.0.as_ptr()) }
1254 }
1255}
1256
1257impl<'a, P: Ptr, T: ToGlibContainerFromSlice<'a, P>> ToGlibPtr<'a, P> for [T] {
1258 type Storage = T::Storage;
1259
1260 #[inline]
1261 fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
1262 let result = ToGlibContainerFromSlice::to_glib_none_from_slice(self);
1263 Stash(result.0, result.1)
1264 }
1265
1266 #[inline]
1267 fn to_glib_container(&'a self) -> Stash<'a, P, Self> {
1268 let result = ToGlibContainerFromSlice::to_glib_container_from_slice(self);
1269 Stash(result.0, result.1)
1270 }
1271
1272 #[inline]
1273 fn to_glib_full(&self) -> P {
1274 ToGlibContainerFromSlice::to_glib_full_from_slice(self)
1275 }
1276}
1277
1278#[allow(clippy::implicit_hasher)]
1279impl<'a> ToGlibPtr<'a, *mut ffi::GHashTable> for HashMap<String, String> {
1280 type Storage = HashTable;
1281
1282 #[inline]
1283 fn to_glib_none(&self) -> Stash<'a, *mut ffi::GHashTable, Self> {
1284 let ptr = self.to_glib_full();
1285 Stash(ptr, HashTable(unsafe { ptr::NonNull::new_unchecked(ptr) }))
1286 }
1287
1288 #[inline]
1289 fn to_glib_full(&self) -> *mut ffi::GHashTable {
1290 unsafe {
1291 let ptr = ffi::g_hash_table_new_full(
1292 Some(ffi::g_str_hash),
1293 Some(ffi::g_str_equal),
1294 Some(ffi::g_free),
1295 Some(ffi::g_free),
1296 );
1297 for (k, v) in self {
1298 let k: *mut c_char = k.to_glib_full();
1299 let v: *mut c_char = v.to_glib_full();
1300 ffi::g_hash_table_insert(ptr, k as *mut _, v as *mut _);
1301 }
1302 ptr
1303 }
1304 }
1305}
1306
1307#[doc(alias = "GHashTable")]
1308pub struct HashTable(ptr::NonNull<ffi::GHashTable>);
1309
1310impl Drop for HashTable {
1311 #[inline]
1312 fn drop(&mut self) {
1313 unsafe { ffi::g_hash_table_unref(self.0.as_ptr()) }
1314 }
1315}
1316
1317#[doc(alias = "GPtrArray")]
1318pub struct PtrArray(ptr::NonNull<ffi::GPtrArray>);
1319
1320impl Drop for PtrArray {
1321 #[inline]
1322 fn drop(&mut self) {
1323 unsafe {
1324 ffi::g_ptr_array_unref(self.0.as_ptr());
1325 }
1326 }
1327}
1328
1329impl<'a, T> ToGlibContainerFromSlice<'a, *mut ffi::GPtrArray> for T
1330where
1331 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
1332{
1333 type Storage = (
1334 Option<PtrArray>,
1335 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
1336 );
1337
1338 #[inline]
1339 fn to_glib_none_from_slice(t: &'a [T]) -> (*mut ffi::GPtrArray, Self::Storage) {
1340 let stash_vec: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
1341 let arr = unsafe { ffi::g_ptr_array_sized_new(t.len() as _) };
1342 unsafe {
1343 for stash in &stash_vec {
1344 ffi::g_ptr_array_add(arr, Ptr::to(stash.0));
1345 }
1346 }
1347
1348 (
1349 arr,
1350 (
1351 Some(PtrArray(unsafe { ptr::NonNull::new_unchecked(arr) })),
1352 stash_vec,
1353 ),
1354 )
1355 }
1356
1357 #[inline]
1358 fn to_glib_container_from_slice(t: &'a [T]) -> (*mut ffi::GPtrArray, Self::Storage) {
1359 let stash_vec: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
1360 let arr = unsafe { ffi::g_ptr_array_sized_new(t.len() as _) };
1361 unsafe {
1362 for stash in &stash_vec {
1363 ffi::g_ptr_array_add(arr, Ptr::to(stash.0));
1364 }
1365 }
1366 (arr, (None, stash_vec))
1367 }
1368
1369 #[inline]
1370 fn to_glib_full_from_slice(t: &[T]) -> *mut ffi::GPtrArray {
1371 let arr = unsafe { ffi::g_ptr_array_sized_new(t.len() as _) };
1372 unsafe {
1373 for ptr in t.iter().map(ToGlibPtr::to_glib_full) {
1374 ffi::g_ptr_array_add(arr, Ptr::to(ptr));
1375 }
1376 }
1377 arr
1378 }
1379}
1380
1381impl<'a, T> ToGlibContainerFromSlice<'a, *const ffi::GPtrArray> for T
1382where
1383 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
1384{
1385 type Storage = (
1386 Option<PtrArray>,
1387 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
1388 );
1389
1390 #[inline]
1391 fn to_glib_none_from_slice(t: &'a [T]) -> (*const ffi::GPtrArray, Self::Storage) {
1392 let (arr, stash) =
1393 ToGlibContainerFromSlice::<*mut ffi::GPtrArray>::to_glib_none_from_slice(t);
1394 (arr as *const ffi::GPtrArray, stash)
1395 }
1396
1397 #[inline]
1398 fn to_glib_container_from_slice(_t: &'a [T]) -> (*const ffi::GPtrArray, Self::Storage) {
1399 unimplemented!()
1400 }
1401
1402 #[inline]
1403 fn to_glib_full_from_slice(_t: &[T]) -> *const ffi::GPtrArray {
1404 unimplemented!()
1405 }
1406}
1407
1408pub trait FromGlib<G: Copy>: Sized {
1411 unsafe fn from_glib(val: G) -> Self;
1412}
1413
1414#[inline]
1417pub unsafe fn from_glib<G: Copy, T: FromGlib<G>>(val: G) -> T {
1418 unsafe { FromGlib::from_glib(val) }
1419}
1420
1421impl FromGlib<ffi::gboolean> for bool {
1422 #[inline]
1423 unsafe fn from_glib(val: ffi::gboolean) -> Self {
1424 val != ffi::GFALSE
1425 }
1426}
1427
1428impl FromGlib<i32> for Ordering {
1429 #[inline]
1430 unsafe fn from_glib(val: i32) -> Self {
1431 val.cmp(&0)
1432 }
1433}
1434
1435pub trait TryFromGlib<G: Copy>: Sized {
1438 type Error;
1439 unsafe fn try_from_glib(val: G) -> Result<Self, Self::Error>;
1440}
1441
1442#[inline]
1445pub unsafe fn try_from_glib<G: Copy, T: TryFromGlib<G>>(
1446 val: G,
1447) -> Result<T, <T as TryFromGlib<G>>::Error> {
1448 unsafe { TryFromGlib::try_from_glib(val) }
1449}
1450
1451#[derive(Debug, PartialEq, Eq)]
1454pub struct GlibNoneError;
1455
1456impl fmt::Display for GlibNoneError {
1457 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1458 write!(fmt, "glib value is None")
1459 }
1460}
1461
1462impl std::error::Error for GlibNoneError {}
1463
1464impl<G: Copy, T: TryFromGlib<G, Error = GlibNoneError>> FromGlib<G> for Option<T> {
1465 #[inline]
1466 unsafe fn from_glib(val: G) -> Self {
1467 unsafe { T::try_from_glib(val).ok() }
1468 }
1469}
1470
1471#[derive(Debug, Eq, PartialEq)]
1474pub enum GlibNoneOrInvalidError<I: Error> {
1475 Invalid(I),
1476 None,
1477}
1478
1479impl<I: Error> GlibNoneOrInvalidError<I> {
1480 #[inline]
1483 pub fn none() -> Self {
1484 Self::None
1485 }
1486
1487 #[inline]
1490 pub fn is_none(&self) -> bool {
1491 matches!(self, Self::None)
1492 }
1493
1494 #[inline]
1497 pub fn is_invalid(&self) -> bool {
1498 matches!(self, Self::Invalid(_))
1499 }
1500}
1501
1502impl<I: Error> From<I> for GlibNoneOrInvalidError<I> {
1503 #[inline]
1504 fn from(invalid: I) -> Self {
1505 Self::Invalid(invalid)
1506 }
1507}
1508
1509impl<I: Error> fmt::Display for GlibNoneOrInvalidError<I> {
1510 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1511 match self {
1512 Self::Invalid(err) => {
1513 write!(fmt, "glib value is invalid: ")?;
1514 fmt::Display::fmt(err, fmt)
1515 }
1516 Self::None => write!(fmt, "glib value is None"),
1517 }
1518 }
1519}
1520
1521impl<I: Error> Error for GlibNoneOrInvalidError<I> {}
1522
1523impl<G: Copy, I: Error, T: TryFromGlib<G, Error = GlibNoneOrInvalidError<I>>> FromGlib<G>
1524 for Result<Option<T>, I>
1525{
1526 #[inline]
1527 unsafe fn from_glib(val: G) -> Self {
1528 unsafe {
1529 match T::try_from_glib(val) {
1530 Ok(value) => Ok(Some(value)),
1531 Err(GlibNoneOrInvalidError::None) => Ok(None),
1532 Err(GlibNoneOrInvalidError::Invalid(err)) => Err(err),
1533 }
1534 }
1535 }
1536}
1537
1538pub trait FromGlibPtrNone<P: Ptr>: Sized {
1556 unsafe fn from_glib_none(ptr: P) -> Self;
1561}
1562
1563pub trait FromGlibPtrFull<P: Ptr>: Sized {
1580 unsafe fn from_glib_full(ptr: P) -> Self;
1585}
1586
1587pub trait FromGlibPtrBorrow<P: Ptr>: Sized {
1613 unsafe fn from_glib_borrow(_ptr: P) -> Borrowed<Self> {
1618 unimplemented!();
1619 }
1620}
1621
1622#[inline]
1627pub unsafe fn from_glib_none<P: Ptr, T: FromGlibPtrNone<P>>(ptr: P) -> T {
1628 unsafe { FromGlibPtrNone::from_glib_none(ptr) }
1629}
1630
1631#[inline]
1636pub unsafe fn from_glib_full<P: Ptr, T: FromGlibPtrFull<P>>(ptr: P) -> T {
1637 unsafe { FromGlibPtrFull::from_glib_full(ptr) }
1638}
1639
1640#[inline]
1645pub unsafe fn from_glib_borrow<P: Ptr, T: FromGlibPtrBorrow<P>>(ptr: P) -> Borrowed<T> {
1646 unsafe { FromGlibPtrBorrow::from_glib_borrow(ptr) }
1647}
1648
1649impl<P: Ptr, T: FromGlibPtrNone<P>> FromGlibPtrNone<P> for Option<T> {
1650 #[inline]
1651 unsafe fn from_glib_none(ptr: P) -> Option<T> {
1652 unsafe {
1653 if ptr.is_null() {
1654 None
1655 } else {
1656 Some(from_glib_none(ptr))
1657 }
1658 }
1659 }
1660}
1661
1662impl<P: Ptr, T: FromGlibPtrBorrow<P>> FromGlibPtrBorrow<P> for Option<T> {
1663 #[inline]
1664 unsafe fn from_glib_borrow(ptr: P) -> Borrowed<Option<T>> {
1665 unsafe {
1666 if ptr.is_null() {
1667 Borrowed::new(None)
1668 } else {
1669 let val = T::from_glib_borrow(ptr);
1670 Borrowed::new(Some(val.into_inner()))
1671 }
1672 }
1673 }
1674}
1675
1676impl<P: Ptr, T: FromGlibPtrFull<P>> FromGlibPtrFull<P> for Option<T> {
1677 #[inline]
1678 unsafe fn from_glib_full(ptr: P) -> Option<T> {
1679 unsafe {
1680 if ptr.is_null() {
1681 None
1682 } else {
1683 Some(from_glib_full(ptr))
1684 }
1685 }
1686 }
1687}
1688
1689impl FromGlibPtrNone<*const c_char> for String {
1690 #[inline]
1691 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1692 unsafe {
1693 debug_assert!(!ptr.is_null());
1694 Self::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned()
1695 }
1696 }
1697}
1698
1699impl FromGlibPtrFull<*const c_char> for String {
1701 #[inline]
1702 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1703 unsafe {
1704 let res = from_glib_none(ptr);
1705 ffi::g_free(ptr as *mut _);
1706 res
1707 }
1708 }
1709}
1710
1711impl FromGlibPtrNone<*mut c_char> for String {
1713 #[inline]
1714 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1715 unsafe {
1716 debug_assert!(!ptr.is_null());
1717 Self::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned()
1718 }
1719 }
1720}
1721
1722impl FromGlibPtrFull<*mut c_char> for String {
1724 #[inline]
1725 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1726 unsafe {
1727 let res = from_glib_none(ptr);
1728 ffi::g_free(ptr as *mut _);
1729 res
1730 }
1731 }
1732}
1733
1734#[cfg(not(windows))]
1735pub(crate) unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
1736 unsafe {
1737 debug_assert!(!ptr.is_null());
1738
1739 OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec()).into()
1743 }
1744}
1745
1746#[cfg(not(windows))]
1747pub(crate) unsafe fn c_to_path<'a>(ptr: *const c_char) -> &'a Path {
1748 unsafe {
1749 debug_assert!(!ptr.is_null());
1750
1751 Path::new(OsStr::from_bytes(CStr::from_ptr(ptr).to_bytes()))
1752 }
1753}
1754
1755#[cfg(windows)]
1756pub(crate) unsafe fn c_to_path<'a>(ptr: *const c_char) -> &'a Path {
1757 debug_assert!(!ptr.is_null());
1758
1759 unsafe {
1760 Path::new(crate::GStr::from_ptr(ptr).as_str())
1762 }
1763}
1764
1765#[cfg(windows)]
1766pub(crate) unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
1767 debug_assert!(!ptr.is_null());
1768
1769 unsafe {
1770 String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
1775 .expect("Invalid, non-UTF8 path")
1776 .into()
1777 }
1778}
1779
1780#[cfg(not(windows))]
1781pub(crate) unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
1782 unsafe {
1783 debug_assert!(!ptr.is_null());
1784
1785 OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec())
1789 }
1790}
1791
1792#[cfg(windows)]
1793pub(crate) unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
1794 debug_assert!(!ptr.is_null());
1795
1796 unsafe {
1797 String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
1803 .expect("Invalid, non-UTF8 path")
1804 .into()
1805 }
1806}
1807
1808impl FromGlibPtrNone<*const c_char> for PathBuf {
1809 #[inline]
1810 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1811 unsafe {
1812 debug_assert!(!ptr.is_null());
1813 c_to_path_buf(ptr)
1814 }
1815 }
1816}
1817
1818impl FromGlibPtrFull<*const c_char> for PathBuf {
1819 #[inline]
1820 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1821 unsafe {
1822 let res = from_glib_none(ptr);
1823 ffi::g_free(ptr as *mut _);
1824 res
1825 }
1826 }
1827}
1828
1829impl FromGlibPtrNone<*mut c_char> for PathBuf {
1830 #[inline]
1831 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1832 unsafe {
1833 debug_assert!(!ptr.is_null());
1834 c_to_path_buf(ptr)
1835 }
1836 }
1837}
1838
1839impl FromGlibPtrFull<*mut c_char> for PathBuf {
1840 #[inline]
1841 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1842 unsafe {
1843 let res = from_glib_none(ptr);
1844 ffi::g_free(ptr as *mut _);
1845 res
1846 }
1847 }
1848}
1849
1850#[cfg(not(windows))]
1851pub(crate) unsafe fn c_to_path_buf_num(ptr: *const c_char, num: usize) -> PathBuf {
1852 unsafe {
1853 debug_assert!(!ptr.is_null());
1854 let slice = std::slice::from_raw_parts(ptr as *const u8, num);
1855 OsString::from_vec(slice.to_vec()).into()
1856 }
1857}
1858
1859#[cfg(windows)]
1860pub(crate) unsafe fn c_to_path_buf_num(ptr: *const c_char, num: usize) -> PathBuf {
1861 unsafe {
1862 debug_assert!(!ptr.is_null());
1863 let slice = std::slice::from_raw_parts(ptr as *const u8, num);
1864 String::from_utf8(slice.into())
1865 .expect("Invalid, non-UTF8 path")
1866 .into()
1867 }
1868}
1869
1870#[doc(hidden)]
1871impl FromGlibContainer<*const c_char, *const i8> for PathBuf {
1872 unsafe fn from_glib_none_num(ptr: *const i8, num: usize) -> Self {
1873 unsafe { c_to_path_buf_num(ptr as *const _, num) }
1874 }
1875
1876 unsafe fn from_glib_container_num(ptr: *const i8, num: usize) -> Self {
1877 unsafe { c_to_path_buf_num(ptr as *const _, num) }
1878 }
1879
1880 unsafe fn from_glib_full_num(ptr: *const i8, num: usize) -> Self {
1881 unsafe {
1882 let res = c_to_path_buf_num(ptr as *const _, num);
1883 ffi::g_free(ptr as *mut _);
1884 res
1885 }
1886 }
1887}
1888
1889#[doc(hidden)]
1890impl FromGlibContainer<*const c_char, *mut i8> for PathBuf {
1891 unsafe fn from_glib_none_num(ptr: *mut i8, num: usize) -> Self {
1892 unsafe { FromGlibContainer::from_glib_none_num(ptr as *const i8, num) }
1893 }
1894
1895 unsafe fn from_glib_container_num(ptr: *mut i8, num: usize) -> Self {
1896 unsafe { FromGlibContainer::from_glib_container_num(ptr as *const i8, num) }
1897 }
1898
1899 unsafe fn from_glib_full_num(ptr: *mut i8, num: usize) -> Self {
1900 unsafe { FromGlibContainer::from_glib_full_num(ptr as *const i8, num) }
1901 }
1902}
1903
1904#[doc(hidden)]
1905impl FromGlibContainer<*const c_char, *const u8> for PathBuf {
1906 unsafe fn from_glib_none_num(ptr: *const u8, num: usize) -> Self {
1907 unsafe { FromGlibContainer::from_glib_none_num(ptr as *const i8, num) }
1908 }
1909
1910 unsafe fn from_glib_container_num(ptr: *const u8, num: usize) -> Self {
1911 unsafe { FromGlibContainer::from_glib_container_num(ptr as *const i8, num) }
1912 }
1913
1914 unsafe fn from_glib_full_num(ptr: *const u8, num: usize) -> Self {
1915 unsafe { FromGlibContainer::from_glib_full_num(ptr as *const i8, num) }
1916 }
1917}
1918
1919#[doc(hidden)]
1920impl FromGlibContainer<*const c_char, *mut u8> for PathBuf {
1921 unsafe fn from_glib_none_num(ptr: *mut u8, num: usize) -> Self {
1922 unsafe { FromGlibContainer::from_glib_none_num(ptr as *const i8, num) }
1923 }
1924
1925 unsafe fn from_glib_container_num(ptr: *mut u8, num: usize) -> Self {
1926 unsafe { FromGlibContainer::from_glib_container_num(ptr as *const i8, num) }
1927 }
1928
1929 unsafe fn from_glib_full_num(ptr: *mut u8, num: usize) -> Self {
1930 unsafe { FromGlibContainer::from_glib_full_num(ptr as *const i8, num) }
1931 }
1932}
1933
1934impl FromGlibPtrNone<*const c_char> for OsString {
1935 #[inline]
1936 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1937 unsafe {
1938 debug_assert!(!ptr.is_null());
1939 c_to_os_string(ptr)
1940 }
1941 }
1942}
1943
1944impl FromGlibPtrFull<*const c_char> for OsString {
1945 #[inline]
1946 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1947 unsafe {
1948 let res = from_glib_none(ptr);
1949 ffi::g_free(ptr as *mut _);
1950 res
1951 }
1952 }
1953}
1954
1955impl FromGlibPtrNone<*mut c_char> for OsString {
1956 #[inline]
1957 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1958 unsafe {
1959 debug_assert!(!ptr.is_null());
1960 c_to_os_string(ptr)
1961 }
1962 }
1963}
1964
1965impl FromGlibPtrFull<*mut c_char> for OsString {
1966 #[inline]
1967 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1968 unsafe {
1969 let res = from_glib_none(ptr);
1970 ffi::g_free(ptr as *mut _);
1971 res
1972 }
1973 }
1974}
1975
1976pub trait FromGlibContainer<T, P: Ptr>: Sized {
1978 unsafe fn from_glib_none_num(ptr: P, num: usize) -> Self;
1982
1983 unsafe fn from_glib_container_num(ptr: P, num: usize) -> Self;
1987
1988 unsafe fn from_glib_full_num(ptr: P, num: usize) -> Self;
1992}
1993
1994pub trait FromGlibPtrContainer<P: Ptr, PP: Ptr>: FromGlibContainer<P, PP> + Sized {
1996 unsafe fn from_glib_none(ptr: PP) -> Self;
1998
1999 unsafe fn from_glib_container(ptr: PP) -> Self;
2001
2002 unsafe fn from_glib_full(ptr: PP) -> Self;
2004}
2005
2006pub unsafe fn c_ptr_array_len<P: Ptr>(mut ptr: *const P) -> usize {
2007 unsafe {
2008 let mut len = 0;
2009
2010 if !ptr.is_null() {
2011 while !(*ptr).is_null() {
2012 len += 1;
2013 ptr = ptr.offset(1);
2014 }
2015 }
2016 len
2017 }
2018}
2019
2020pub trait FromGlibContainerAsVec<T, P: Ptr>
2021where
2022 Self: Sized,
2023{
2024 unsafe fn from_glib_none_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
2025 unsafe fn from_glib_container_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
2026 unsafe fn from_glib_full_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
2027}
2028
2029pub trait FromGlibPtrArrayContainerAsVec<P: Ptr, PP: Ptr>: FromGlibContainerAsVec<P, PP>
2030where
2031 Self: Sized,
2032{
2033 unsafe fn from_glib_none_as_vec(ptr: PP) -> Vec<Self>;
2034 unsafe fn from_glib_container_as_vec(ptr: PP) -> Vec<Self>;
2035 unsafe fn from_glib_full_as_vec(ptr: PP) -> Vec<Self>;
2036}
2037
2038impl FromGlibContainerAsVec<bool, *const ffi::gboolean> for bool {
2039 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::gboolean, num: usize) -> Vec<Self> {
2040 unsafe {
2041 if num == 0 || ptr.is_null() {
2042 return Vec::new();
2043 }
2044
2045 let mut res = Vec::<Self>::with_capacity(num);
2046 let res_ptr = res.as_mut_ptr();
2047 for i in 0..num {
2048 *res_ptr.add(i) = from_glib(ptr::read(ptr.add(i)));
2049 }
2050 res.set_len(num);
2051 res
2052 }
2053 }
2054
2055 unsafe fn from_glib_container_num_as_vec(_: *const ffi::gboolean, _: usize) -> Vec<Self> {
2056 unimplemented!();
2058 }
2059
2060 unsafe fn from_glib_full_num_as_vec(_: *const ffi::gboolean, _: usize) -> Vec<Self> {
2061 unimplemented!();
2063 }
2064}
2065
2066impl FromGlibContainerAsVec<bool, *mut ffi::gboolean> for bool {
2067 unsafe fn from_glib_none_num_as_vec(ptr: *mut ffi::gboolean, num: usize) -> Vec<Self> {
2068 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) }
2069 }
2070
2071 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::gboolean, num: usize) -> Vec<Self> {
2072 unsafe {
2073 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2074 ffi::g_free(ptr as *mut _);
2075 res
2076 }
2077 }
2078
2079 unsafe fn from_glib_full_num_as_vec(ptr: *mut ffi::gboolean, num: usize) -> Vec<Self> {
2080 unsafe { FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) }
2081 }
2082}
2083
2084macro_rules! impl_from_glib_container_as_vec_fundamental {
2085 ($name:ty) => {
2086 unsafe impl TransparentType for $name {
2087 type GlibType = $name;
2088 }
2089
2090 impl FromGlibContainerAsVec<$name, *const $name> for $name {
2091 unsafe fn from_glib_none_num_as_vec(ptr: *const $name, num: usize) -> Vec<Self> {
2092 unsafe {
2093 if num == 0 || ptr.is_null() {
2094 return Vec::new();
2095 }
2096
2097 let mut res = Vec::with_capacity(num);
2098 let res_ptr = res.as_mut_ptr();
2099 std::ptr::copy_nonoverlapping(ptr, res_ptr, num);
2100 res.set_len(num);
2101 res
2102 }
2103 }
2104
2105 unsafe fn from_glib_container_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
2106 unimplemented!();
2108 }
2109
2110 unsafe fn from_glib_full_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
2111 unimplemented!();
2113 }
2114 }
2115
2116 impl FromGlibContainerAsVec<$name, *mut $name> for $name {
2117 unsafe fn from_glib_none_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
2118 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) }
2119 }
2120
2121 unsafe fn from_glib_container_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
2122 unsafe {
2123 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2124 ffi::g_free(ptr as *mut _);
2125 res
2126 }
2127 }
2128
2129 unsafe fn from_glib_full_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
2130 unsafe { FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) }
2131 }
2132 }
2133 };
2134}
2135
2136impl_from_glib_container_as_vec_fundamental!(u8);
2137impl_from_glib_container_as_vec_fundamental!(i8);
2138impl_from_glib_container_as_vec_fundamental!(u16);
2139impl_from_glib_container_as_vec_fundamental!(i16);
2140impl_from_glib_container_as_vec_fundamental!(u32);
2141impl_from_glib_container_as_vec_fundamental!(i32);
2142impl_from_glib_container_as_vec_fundamental!(u64);
2143impl_from_glib_container_as_vec_fundamental!(i64);
2144impl_from_glib_container_as_vec_fundamental!(f32);
2145impl_from_glib_container_as_vec_fundamental!(f64);
2146
2147macro_rules! impl_from_glib_container_as_vec_string {
2148 ($name:ty, $ffi_name:ty) => {
2149 impl FromGlibContainerAsVec<$ffi_name, *const $ffi_name> for $name {
2150 unsafe fn from_glib_none_num_as_vec(ptr: *const $ffi_name, num: usize) -> Vec<Self> {
2151 unsafe {
2152 if num == 0 || ptr.is_null() {
2153 return Vec::new();
2154 }
2155
2156 let mut res = Vec::<Self>::with_capacity(num);
2157 let res_ptr = res.as_mut_ptr();
2158 for i in 0..num {
2159 std::ptr::write(
2160 res_ptr.add(i),
2161 from_glib_none(ptr::read(ptr.add(i)) as $ffi_name),
2162 );
2163 }
2164 res.set_len(num);
2165 res
2166 }
2167 }
2168
2169 unsafe fn from_glib_container_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
2170 unimplemented!();
2172 }
2173
2174 unsafe fn from_glib_full_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
2175 unimplemented!();
2177 }
2178 }
2179
2180 impl FromGlibContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
2181 unsafe fn from_glib_none_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
2182 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) }
2183 }
2184
2185 unsafe fn from_glib_container_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
2186 unsafe {
2187 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2188 ffi::g_free(ptr as *mut _);
2189 res
2190 }
2191 }
2192
2193 unsafe fn from_glib_full_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
2194 unsafe {
2195 if num == 0 || ptr.is_null() {
2196 ffi::g_free(ptr as *mut _);
2197 return Vec::new();
2198 }
2199
2200 let mut res = Vec::<Self>::with_capacity(num);
2201 let res_ptr = res.as_mut_ptr();
2202 for i in 0..num {
2203 std::ptr::write(
2204 res_ptr.add(i),
2205 from_glib_full(ptr::read(ptr.add(i)) as $ffi_name),
2206 );
2207 }
2208 res.set_len(num);
2209 ffi::g_free(ptr as *mut _);
2210 res
2211 }
2212 }
2213 }
2214
2215 impl FromGlibPtrArrayContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
2216 unsafe fn from_glib_none_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
2217 unsafe {
2218 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
2219 }
2220 }
2221
2222 unsafe fn from_glib_container_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
2223 unsafe {
2224 FromGlibContainerAsVec::from_glib_container_num_as_vec(
2225 ptr,
2226 c_ptr_array_len(ptr),
2227 )
2228 }
2229 }
2230
2231 unsafe fn from_glib_full_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
2232 unsafe {
2233 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
2234 }
2235 }
2236 }
2237
2238 impl FromGlibPtrArrayContainerAsVec<$ffi_name, *const $ffi_name> for $name {
2239 unsafe fn from_glib_none_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
2240 unsafe {
2241 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
2242 }
2243 }
2244
2245 unsafe fn from_glib_container_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
2246 unsafe {
2247 FromGlibContainerAsVec::from_glib_container_num_as_vec(
2248 ptr,
2249 c_ptr_array_len(ptr),
2250 )
2251 }
2252 }
2253
2254 unsafe fn from_glib_full_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
2255 unsafe {
2256 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
2257 }
2258 }
2259 }
2260 };
2261}
2262
2263impl_from_glib_container_as_vec_string!(String, *const c_char);
2265impl_from_glib_container_as_vec_string!(String, *mut c_char);
2266
2267impl_from_glib_container_as_vec_string!(PathBuf, *const c_char);
2268impl_from_glib_container_as_vec_string!(PathBuf, *mut c_char);
2269impl_from_glib_container_as_vec_string!(OsString, *const c_char);
2270impl_from_glib_container_as_vec_string!(OsString, *mut c_char);
2271
2272impl<P, PP: Ptr, T: FromGlibContainerAsVec<P, PP>> FromGlibContainer<P, PP> for Vec<T> {
2273 unsafe fn from_glib_none_num(ptr: PP, num: usize) -> Vec<T> {
2274 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num) }
2275 }
2276
2277 unsafe fn from_glib_container_num(ptr: PP, num: usize) -> Vec<T> {
2278 unsafe { FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) }
2279 }
2280
2281 unsafe fn from_glib_full_num(ptr: PP, num: usize) -> Vec<T> {
2282 unsafe { FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, num) }
2283 }
2284}
2285
2286impl<P: Ptr, PP: Ptr, T: FromGlibPtrArrayContainerAsVec<P, PP>> FromGlibPtrContainer<P, PP>
2287 for Vec<T>
2288{
2289 unsafe fn from_glib_none(ptr: PP) -> Vec<T> {
2290 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr) }
2291 }
2292
2293 unsafe fn from_glib_container(ptr: PP) -> Vec<T> {
2294 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_container_as_vec(ptr) }
2295 }
2296
2297 unsafe fn from_glib_full(ptr: PP) -> Vec<T> {
2298 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_full_as_vec(ptr) }
2299 }
2300}
2301
2302impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList> for T
2303where
2304 T: GlibPtrDefault
2305 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2306 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2307{
2308 unsafe fn from_glib_none_num_as_vec(mut ptr: *mut ffi::GSList, num: usize) -> Vec<T> {
2309 unsafe {
2310 if num == 0 || ptr.is_null() {
2311 return Vec::new();
2312 }
2313 let mut res = Vec::with_capacity(num);
2314 for _ in 0..num {
2315 if ptr.is_null() {
2316 break;
2317 }
2318
2319 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2320 if !item_ptr.is_null() {
2321 res.push(from_glib_none(item_ptr));
2322 }
2323 ptr = (*ptr).next;
2324 }
2325 res
2326 }
2327 }
2328
2329 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GSList, num: usize) -> Vec<T> {
2330 unsafe {
2331 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2332 ffi::g_slist_free(ptr);
2333 res
2334 }
2335 }
2336
2337 unsafe fn from_glib_full_num_as_vec(mut ptr: *mut ffi::GSList, num: usize) -> Vec<T> {
2338 unsafe {
2339 if num == 0 || ptr.is_null() {
2340 return Vec::new();
2341 }
2342 let orig_ptr = ptr;
2343 let mut res = Vec::with_capacity(num);
2344 for _ in 0..num {
2345 if ptr.is_null() {
2346 break;
2347 }
2348
2349 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2350 if !item_ptr.is_null() {
2351 res.push(from_glib_full(item_ptr));
2352 }
2353 ptr = (*ptr).next;
2354 }
2355 ffi::g_slist_free(orig_ptr);
2356 res
2357 }
2358 }
2359}
2360
2361impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList> for T
2362where
2363 T: GlibPtrDefault
2364 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2365 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2366{
2367 unsafe fn from_glib_none_as_vec(mut ptr: *mut ffi::GSList) -> Vec<T> {
2368 unsafe {
2369 let mut res = Vec::new();
2370 while !ptr.is_null() {
2371 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2372 if !item_ptr.is_null() {
2373 res.push(from_glib_none(item_ptr));
2374 }
2375 ptr = (*ptr).next;
2376 }
2377 res
2378 }
2379 }
2380
2381 unsafe fn from_glib_container_as_vec(ptr: *mut ffi::GSList) -> Vec<T> {
2382 unsafe {
2383 let res = FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr);
2384 ffi::g_slist_free(ptr);
2385 res
2386 }
2387 }
2388
2389 unsafe fn from_glib_full_as_vec(mut ptr: *mut ffi::GSList) -> Vec<T> {
2390 unsafe {
2391 let orig_ptr = ptr;
2392 let mut res = Vec::new();
2393 while !ptr.is_null() {
2394 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2395 if !item_ptr.is_null() {
2396 res.push(from_glib_full(item_ptr));
2397 }
2398 ptr = (*ptr).next;
2399 }
2400 ffi::g_slist_free(orig_ptr);
2401 res
2402 }
2403 }
2404}
2405
2406impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GList> for T
2407where
2408 T: GlibPtrDefault
2409 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2410 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2411{
2412 unsafe fn from_glib_none_num_as_vec(mut ptr: *mut ffi::GList, num: usize) -> Vec<T> {
2413 unsafe {
2414 if num == 0 || ptr.is_null() {
2415 return Vec::new();
2416 }
2417 let mut res = Vec::with_capacity(num);
2418 for _ in 0..num {
2419 if ptr.is_null() {
2420 break;
2421 }
2422
2423 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2424 if !item_ptr.is_null() {
2425 res.push(from_glib_none(item_ptr));
2426 }
2427 ptr = (*ptr).next;
2428 }
2429 res
2430 }
2431 }
2432
2433 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GList, num: usize) -> Vec<T> {
2434 unsafe {
2435 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2436 ffi::g_list_free(ptr);
2437 res
2438 }
2439 }
2440
2441 unsafe fn from_glib_full_num_as_vec(mut ptr: *mut ffi::GList, num: usize) -> Vec<T> {
2442 unsafe {
2443 if num == 0 || ptr.is_null() {
2444 return Vec::new();
2445 }
2446 let orig_ptr = ptr;
2447 let mut res = Vec::with_capacity(num);
2448 for _ in 0..num {
2449 if ptr.is_null() {
2450 break;
2451 }
2452
2453 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2454 if !item_ptr.is_null() {
2455 res.push(from_glib_full(item_ptr));
2456 }
2457 ptr = (*ptr).next;
2458 }
2459 ffi::g_list_free(orig_ptr);
2460 res
2461 }
2462 }
2463}
2464
2465impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GList> for T
2466where
2467 T: GlibPtrDefault
2468 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2469 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2470{
2471 unsafe fn from_glib_none_as_vec(mut ptr: *mut ffi::GList) -> Vec<T> {
2472 unsafe {
2473 let mut res = Vec::new();
2474 while !ptr.is_null() {
2475 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2476 if !item_ptr.is_null() {
2477 res.push(from_glib_none(item_ptr));
2478 }
2479 ptr = (*ptr).next;
2480 }
2481 res
2482 }
2483 }
2484
2485 unsafe fn from_glib_container_as_vec(ptr: *mut ffi::GList) -> Vec<T> {
2486 unsafe {
2487 let res = FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr);
2488 ffi::g_list_free(ptr);
2489 res
2490 }
2491 }
2492
2493 unsafe fn from_glib_full_as_vec(mut ptr: *mut ffi::GList) -> Vec<T> {
2494 unsafe {
2495 let orig_ptr = ptr;
2496 let mut res = Vec::new();
2497 while !ptr.is_null() {
2498 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2499 if !item_ptr.is_null() {
2500 res.push(from_glib_full(item_ptr));
2501 }
2502 ptr = (*ptr).next;
2503 }
2504 ffi::g_list_free(orig_ptr);
2505 res
2506 }
2507 }
2508}
2509
2510impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GList> for T
2511where
2512 T: GlibPtrDefault
2513 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2514 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2515{
2516 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GList, num: usize) -> Vec<T> {
2517 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(mut_override(ptr), num) }
2518 }
2519
2520 unsafe fn from_glib_container_num_as_vec(_: *const ffi::GList, _: usize) -> Vec<T> {
2521 unimplemented!()
2523 }
2524
2525 unsafe fn from_glib_full_num_as_vec(_: *const ffi::GList, _: usize) -> Vec<T> {
2526 unimplemented!()
2528 }
2529}
2530
2531impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GList> for T
2532where
2533 T: GlibPtrDefault
2534 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2535 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2536{
2537 unsafe fn from_glib_none_as_vec(ptr: *const ffi::GList) -> Vec<T> {
2538 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(mut_override(ptr)) }
2539 }
2540
2541 unsafe fn from_glib_container_as_vec(_: *const ffi::GList) -> Vec<T> {
2542 unimplemented!()
2544 }
2545
2546 unsafe fn from_glib_full_as_vec(_: *const ffi::GList) -> Vec<T> {
2547 unimplemented!()
2549 }
2550}
2551
2552impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GSList> for T
2553where
2554 T: GlibPtrDefault
2555 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2556 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2557{
2558 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GSList, num: usize) -> Vec<T> {
2559 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(mut_override(ptr), num) }
2560 }
2561
2562 unsafe fn from_glib_container_num_as_vec(_: *const ffi::GSList, _: usize) -> Vec<T> {
2563 unimplemented!()
2565 }
2566
2567 unsafe fn from_glib_full_num_as_vec(_: *const ffi::GSList, _: usize) -> Vec<T> {
2568 unimplemented!()
2570 }
2571}
2572
2573impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GSList> for T
2574where
2575 T: GlibPtrDefault
2576 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2577 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2578{
2579 unsafe fn from_glib_none_as_vec(ptr: *const ffi::GSList) -> Vec<T> {
2580 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(mut_override(ptr)) }
2581 }
2582
2583 unsafe fn from_glib_container_as_vec(_: *const ffi::GSList) -> Vec<T> {
2584 unimplemented!()
2586 }
2587
2588 unsafe fn from_glib_full_as_vec(_: *const ffi::GSList) -> Vec<T> {
2589 unimplemented!()
2591 }
2592}
2593
2594#[allow(clippy::implicit_hasher)]
2595impl FromGlibContainer<*const c_char, *mut ffi::GHashTable> for HashMap<String, String> {
2596 unsafe fn from_glib_none_num(ptr: *mut ffi::GHashTable, _: usize) -> Self {
2597 unsafe { FromGlibPtrContainer::from_glib_none(ptr) }
2598 }
2599
2600 unsafe fn from_glib_container_num(ptr: *mut ffi::GHashTable, _: usize) -> Self {
2601 unsafe { FromGlibPtrContainer::from_glib_full(ptr) }
2602 }
2603
2604 unsafe fn from_glib_full_num(ptr: *mut ffi::GHashTable, _: usize) -> Self {
2605 unsafe { FromGlibPtrContainer::from_glib_full(ptr) }
2606 }
2607}
2608
2609#[allow(clippy::implicit_hasher)]
2610impl FromGlibPtrContainer<*const c_char, *mut ffi::GHashTable> for HashMap<String, String> {
2611 unsafe fn from_glib_none(ptr: *mut ffi::GHashTable) -> Self {
2612 unsafe {
2613 unsafe extern "C" fn read_string_hash_table(
2614 key: ffi::gpointer,
2615 value: ffi::gpointer,
2616 hash_map: ffi::gpointer,
2617 ) {
2618 unsafe {
2619 let key: String = from_glib_none(key as *const c_char);
2620 let value: String = from_glib_none(value as *const c_char);
2621 let hash_map: &mut HashMap<String, String> =
2622 &mut *(hash_map as *mut HashMap<String, String>);
2623 hash_map.insert(key, value);
2624 }
2625 }
2626 let mut map = HashMap::with_capacity(ffi::g_hash_table_size(ptr) as usize);
2627 ffi::g_hash_table_foreach(
2628 ptr,
2629 Some(read_string_hash_table),
2630 &mut map as *mut HashMap<String, String> as *mut _,
2631 );
2632 map
2633 }
2634 }
2635
2636 unsafe fn from_glib_container(ptr: *mut ffi::GHashTable) -> Self {
2637 unsafe { FromGlibPtrContainer::from_glib_full(ptr) }
2638 }
2639
2640 unsafe fn from_glib_full(ptr: *mut ffi::GHashTable) -> Self {
2641 unsafe {
2642 let map = FromGlibPtrContainer::from_glib_none(ptr);
2643 ffi::g_hash_table_unref(ptr);
2644 map
2645 }
2646 }
2647}
2648
2649impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GPtrArray> for T
2650where
2651 T: GlibPtrDefault
2652 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2653 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2654{
2655 unsafe fn from_glib_none_num_as_vec(ptr: *mut ffi::GPtrArray, num: usize) -> Vec<T> {
2656 unsafe {
2657 if num == 0 || ptr.is_null() {
2658 return Vec::new();
2659 }
2660 let pdata = (*ptr).pdata;
2661 debug_assert!((*ptr).len as usize >= num);
2662 let mut res = Vec::with_capacity(num);
2663 for i in 0..num {
2664 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from(ptr::read(pdata.add(i)));
2665 if !item_ptr.is_null() {
2666 res.push(from_glib_none(item_ptr));
2667 }
2668 }
2669 res
2670 }
2671 }
2672
2673 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GPtrArray, num: usize) -> Vec<T> {
2674 unsafe {
2675 let res = FromGlibContainer::from_glib_none_num(ptr, num);
2676 if !ptr.is_null() {
2677 ffi::g_ptr_array_unref(ptr);
2678 }
2679 res
2680 }
2681 }
2682
2683 unsafe fn from_glib_full_num_as_vec(ptr: *mut ffi::GPtrArray, num: usize) -> Vec<T> {
2684 unsafe {
2685 if ptr.is_null() {
2686 return Vec::new();
2687 }
2688 if num == 0 {
2689 ffi::g_ptr_array_unref(ptr);
2690 return Vec::new();
2691 }
2692 let pdata = (*ptr).pdata;
2693 debug_assert!((*ptr).len as usize >= num);
2694 let mut res = Vec::with_capacity(num);
2695 for i in 0..num {
2696 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from(ptr::read(pdata.add(i)));
2697 if !item_ptr.is_null() {
2698 res.push(from_glib_none(item_ptr));
2699 }
2700 }
2701 ffi::g_ptr_array_unref(ptr);
2702 res
2703 }
2704 }
2705}
2706
2707impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GPtrArray> for T
2708where
2709 T: GlibPtrDefault
2710 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2711 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2712{
2713 unsafe fn from_glib_none_as_vec(ptr: *mut ffi::GPtrArray) -> Vec<T> {
2714 unsafe {
2715 let num = (*ptr).len as usize;
2716 FromGlibContainer::from_glib_none_num(ptr, num)
2717 }
2718 }
2719
2720 unsafe fn from_glib_container_as_vec(ptr: *mut ffi::GPtrArray) -> Vec<T> {
2721 unsafe {
2722 let num = (*ptr).len as usize;
2723 FromGlibContainer::from_glib_container_num(ptr, num)
2724 }
2725 }
2726
2727 unsafe fn from_glib_full_as_vec(ptr: *mut ffi::GPtrArray) -> Vec<T> {
2728 unsafe {
2729 let num = (*ptr).len as usize;
2730 FromGlibContainer::from_glib_full_num(ptr, num)
2731 }
2732 }
2733}
2734
2735impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GPtrArray> for T
2736where
2737 T: GlibPtrDefault
2738 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2739 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2740{
2741 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GPtrArray, num: usize) -> Vec<T> {
2742 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(mut_override(ptr), num) }
2743 }
2744
2745 unsafe fn from_glib_container_num_as_vec(_: *const ffi::GPtrArray, _: usize) -> Vec<T> {
2746 unimplemented!()
2748 }
2749
2750 unsafe fn from_glib_full_num_as_vec(_: *const ffi::GPtrArray, _: usize) -> Vec<T> {
2751 unimplemented!()
2753 }
2754}
2755
2756impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GPtrArray> for T
2757where
2758 T: GlibPtrDefault
2759 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2760 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2761{
2762 unsafe fn from_glib_none_as_vec(ptr: *const ffi::GPtrArray) -> Vec<T> {
2763 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(mut_override(ptr)) }
2764 }
2765
2766 unsafe fn from_glib_container_as_vec(_: *const ffi::GPtrArray) -> Vec<T> {
2767 unimplemented!()
2769 }
2770
2771 unsafe fn from_glib_full_as_vec(_: *const ffi::GPtrArray) -> Vec<T> {
2772 unimplemented!()
2774 }
2775}
2776
2777pub unsafe trait TransparentPtrType: Clone + Sized + GlibPtrDefault {}
2782
2783pub unsafe trait TransparentType: Clone + Sized {
2788 type GlibType;
2789}
2790
2791unsafe impl<T: TransparentPtrType> TransparentType for T {
2792 type GlibType = <T as GlibPtrDefault>::GlibType;
2793}
2794
2795#[cfg(test)]
2796mod tests {
2797 use std::{collections::HashMap, fs};
2798
2799 use tempfile::tempdir;
2800
2801 use super::*;
2802 use crate::{FileTest, GString};
2803
2804 #[test]
2805 fn boolean() {
2806 assert_eq!(true.into_glib(), ffi::GTRUE);
2807 assert_eq!(false.into_glib(), ffi::GFALSE);
2808 assert!(unsafe { bool::from_glib(ffi::GTRUE) });
2809 assert!(!unsafe { bool::from_glib(ffi::GFALSE) });
2810 assert!(unsafe { bool::from_glib(42) });
2811 }
2812
2813 #[test]
2814 fn ordering() {
2815 assert_eq!(Ordering::Less.into_glib(), -1);
2816 assert_eq!(Ordering::Equal.into_glib(), 0);
2817 assert_eq!(Ordering::Greater.into_glib(), 1);
2818 assert_eq!(Ordering::Less, unsafe { Ordering::from_glib(-42) });
2819 assert_eq!(Ordering::Less, unsafe { Ordering::from_glib(-1) });
2820 assert_eq!(Ordering::Equal, unsafe { Ordering::from_glib(0) });
2821 assert_eq!(Ordering::Greater, unsafe { Ordering::from_glib(1) });
2822 assert_eq!(Ordering::Greater, unsafe { Ordering::from_glib(42) });
2823 }
2824
2825 #[test]
2826 fn string() {
2827 let s = "ABC";
2828 let owned = "ABC".to_string();
2829 let cstring = CString::new("ABC").unwrap();
2830
2831 let stash = s.to_glib_none();
2832 assert_eq!(unsafe { CStr::from_ptr(stash.0) }, cstring.as_c_str());
2833
2834 let stash = owned.to_glib_none();
2835 assert_eq!(unsafe { CStr::from_ptr(stash.0) }, cstring.as_c_str());
2836
2837 let ptr: *mut c_char = s.to_glib_full();
2838 assert_eq!(unsafe { CStr::from_ptr(ptr) }, cstring.as_c_str());
2839
2840 unsafe {
2841 ffi::g_free(ptr as *mut _);
2842 }
2843
2844 let ptr: *mut c_char = owned.to_glib_full();
2845 assert_eq!(unsafe { CStr::from_ptr(ptr) }, cstring.as_c_str());
2846
2847 assert_eq!(s, unsafe { String::from_glib_none(ptr) });
2848 assert_eq!(owned, unsafe { String::from_glib_full(ptr) });
2849 }
2850
2851 #[test]
2852 fn string_hash_map() {
2853 let mut map = HashMap::new();
2854 map.insert("A".into(), "1".into());
2855 map.insert("B".into(), "2".into());
2856 map.insert("C".into(), "3".into());
2857 let ptr: *mut ffi::GHashTable = map.to_glib_full();
2858 let map = unsafe { HashMap::from_glib_full(ptr) };
2859 assert_eq!(map.get("A"), Some(&"1".into()));
2860 assert_eq!(map.get("B"), Some(&"2".into()));
2861 assert_eq!(map.get("C"), Some(&"3".into()));
2862 }
2863
2864 #[test]
2865 fn string_array() {
2866 let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
2867 let stash = v.to_glib_none();
2868 let ptr: *mut *mut c_char = stash.0;
2869 let ptr_copy = unsafe { ffi::g_strdupv(ptr) };
2870
2871 let actual: Vec<String> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
2872 assert_eq!(v, actual);
2873 }
2874
2875 #[test]
2876 fn gstring_array() {
2877 let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
2878 let stash = v.to_glib_none();
2879 let ptr: *mut *mut c_char = stash.0;
2880 let ptr_copy = unsafe { ffi::g_strdupv(ptr) };
2881
2882 let actual: Vec<GString> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
2883 assert_eq!(v, actual);
2884 }
2885
2886 #[test]
2887 fn ptr_array() {
2888 let strings = &["A", "B", "C"];
2889 let (ptr, _stash) =
2890 ToGlibContainerFromSlice::<*mut ffi::GPtrArray>::to_glib_none_from_slice(strings);
2891 let v: Vec<GString> = unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr) };
2892 assert_eq!(&v, strings);
2893 }
2894
2895 #[test]
2896 #[cfg(not(target_os = "macos"))]
2897 fn test_paths() {
2898 let tmp_dir = tempdir().unwrap();
2899
2900 let dir_1 = tmp_dir.path().join("abcd");
2903 fs::create_dir(&dir_1).unwrap();
2904 assert_eq!(crate::path_get_basename(&dir_1), Path::new("abcd"));
2905 assert_eq!(
2906 crate::path_get_basename(dir_1.canonicalize().unwrap()),
2907 Path::new("abcd")
2908 );
2909 #[cfg(not(windows))]
2912 assert_eq!(
2913 crate::path_get_dirname(dir_1.canonicalize().unwrap()),
2914 tmp_dir.path()
2915 );
2916 assert!(crate::file_test(
2917 &dir_1,
2918 FileTest::EXISTS | FileTest::IS_DIR
2919 ));
2920 assert!(crate::file_test(
2921 dir_1.canonicalize().unwrap(),
2922 FileTest::EXISTS | FileTest::IS_DIR
2923 ));
2924
2925 let dir_2 = tmp_dir.as_ref().join("øäöü");
2927 fs::create_dir(&dir_2).unwrap();
2928 assert_eq!(crate::path_get_basename(&dir_2), Path::new("øäöü"));
2929 assert_eq!(
2930 crate::path_get_basename(dir_2.canonicalize().unwrap()),
2931 Path::new("øäöü")
2932 );
2933 #[cfg(not(windows))]
2936 assert_eq!(
2937 crate::path_get_dirname(dir_2.canonicalize().unwrap()),
2938 tmp_dir.path()
2939 );
2940 assert!(crate::file_test(
2941 &dir_2,
2942 FileTest::EXISTS | FileTest::IS_DIR
2943 ));
2944 assert!(crate::file_test(
2945 dir_2.canonicalize().unwrap(),
2946 FileTest::EXISTS | FileTest::IS_DIR
2947 ));
2948 }
2949
2950 #[test]
2951 #[cfg(target_os = "macos")]
2952 fn test_paths() {
2953 let t_dir = tempdir().unwrap();
2954 let tmp_dir = t_dir.path().canonicalize().unwrap();
2955
2956 let dir_1 = tmp_dir.join("abcd");
2959 fs::create_dir(&dir_1).unwrap();
2960 assert_eq!(crate::path_get_basename(&dir_1), Path::new("abcd"));
2961 assert_eq!(
2962 crate::path_get_basename(dir_1.canonicalize().unwrap()),
2963 Path::new("abcd")
2964 );
2965 assert_eq!(
2966 crate::path_get_dirname(dir_1.canonicalize().unwrap()),
2967 tmp_dir
2968 );
2969 assert!(crate::file_test(
2970 &dir_1,
2971 FileTest::EXISTS | FileTest::IS_DIR
2972 ));
2973 assert!(crate::file_test(
2974 &dir_1.canonicalize().unwrap(),
2975 FileTest::EXISTS | FileTest::IS_DIR
2976 ));
2977 }
2978
2979 #[test]
2980 fn none_value() {
2981 const CLONG_NONE: libc::c_long = -1;
2982
2983 #[derive(Debug, PartialEq, Eq)]
2984 struct SpecialU32(u32);
2985 impl IntoGlib for SpecialU32 {
2986 type GlibType = libc::c_uint;
2987 fn into_glib(self) -> libc::c_uint {
2988 self.0 as libc::c_uint
2989 }
2990 }
2991 impl OptionIntoGlib for SpecialU32 {
2992 const GLIB_NONE: Self::GlibType = CLONG_NONE as libc::c_uint;
2993 }
2994
2995 assert_eq!(SpecialU32(0).into_glib(), 0);
2996 assert_eq!(SpecialU32(42).into_glib(), 42);
2997 assert_eq!(Some(SpecialU32(0)).into_glib(), 0);
2998 assert_eq!(Some(SpecialU32(42)).into_glib(), 42);
2999 assert_eq!(
3000 Option::None::<SpecialU32>.into_glib(),
3001 SpecialU32::GLIB_NONE
3002 );
3003
3004 impl TryFromGlib<libc::c_uint> for SpecialU32 {
3005 type Error = GlibNoneError;
3006 #[allow(clippy::unnecessary_cast)]
3007 unsafe fn try_from_glib(val: libc::c_uint) -> Result<Self, GlibNoneError> {
3008 if val == SpecialU32::GLIB_NONE {
3009 return Err(GlibNoneError);
3010 }
3011
3012 Ok(SpecialU32(val as u32))
3013 }
3014 }
3015
3016 assert_eq!(unsafe { SpecialU32::try_from_glib(0) }, Ok(SpecialU32(0)));
3017 assert_eq!(unsafe { SpecialU32::try_from_glib(42) }, Ok(SpecialU32(42)));
3018 assert_eq!(
3019 unsafe { SpecialU32::try_from_glib(SpecialU32::GLIB_NONE) },
3020 Err(GlibNoneError)
3021 );
3022
3023 assert_eq!(
3024 unsafe { Option::<SpecialU32>::from_glib(0) },
3025 Some(SpecialU32(0))
3026 );
3027 assert_eq!(
3028 unsafe { Option::<SpecialU32>::from_glib(42) },
3029 Some(SpecialU32(42))
3030 );
3031 assert!(unsafe { Option::<SpecialU32>::from_glib(SpecialU32::GLIB_NONE) }.is_none());
3032 }
3033
3034 #[test]
3035 fn invalid_value() {
3036 use std::num::TryFromIntError;
3037
3038 #[derive(Debug, PartialEq, Eq)]
3039 struct U32(u32);
3040
3041 impl TryFromGlib<libc::c_long> for U32 {
3042 type Error = TryFromIntError;
3043 unsafe fn try_from_glib(val: libc::c_long) -> Result<Self, TryFromIntError> {
3044 Ok(U32(u32::try_from(val)?))
3045 }
3046 }
3047
3048 assert_eq!(unsafe { U32::try_from_glib(0) }, Ok(U32(0)));
3049 assert_eq!(unsafe { U32::try_from_glib(42) }, Ok(U32(42)));
3050 assert!(unsafe { U32::try_from_glib(-1) }.is_err());
3051 assert!(unsafe { U32::try_from_glib(-42) }.is_err());
3052 }
3053
3054 #[test]
3055 fn none_or_invalid_value() {
3056 use std::num::TryFromIntError;
3057
3058 #[derive(Debug, PartialEq, Eq)]
3059 struct SpecialU32(u32);
3060 impl IntoGlib for SpecialU32 {
3061 type GlibType = libc::c_long;
3062 fn into_glib(self) -> libc::c_long {
3063 self.0 as libc::c_long
3064 }
3065 }
3066 impl OptionIntoGlib for SpecialU32 {
3067 const GLIB_NONE: Self::GlibType = -1;
3068 }
3069
3070 assert_eq!(SpecialU32(0).into_glib(), 0);
3071 assert_eq!(SpecialU32(42).into_glib(), 42);
3072 assert_eq!(Some(SpecialU32(42)).into_glib(), 42);
3073 assert_eq!(
3074 Option::None::<SpecialU32>.into_glib(),
3075 SpecialU32::GLIB_NONE
3076 );
3077
3078 impl TryFromGlib<libc::c_long> for SpecialU32 {
3079 type Error = GlibNoneOrInvalidError<TryFromIntError>;
3080 unsafe fn try_from_glib(
3081 val: libc::c_long,
3082 ) -> Result<Self, GlibNoneOrInvalidError<TryFromIntError>> {
3083 if val == SpecialU32::GLIB_NONE {
3084 return Err(GlibNoneOrInvalidError::None);
3085 }
3086
3087 Ok(SpecialU32(u32::try_from(val)?))
3088 }
3089 }
3090
3091 assert_eq!(unsafe { SpecialU32::try_from_glib(0) }, Ok(SpecialU32(0)));
3092 assert_eq!(unsafe { SpecialU32::try_from_glib(42) }, Ok(SpecialU32(42)));
3093 assert!(
3094 unsafe { SpecialU32::try_from_glib(SpecialU32::GLIB_NONE) }
3095 .unwrap_err()
3096 .is_none()
3097 );
3098 assert!(
3099 unsafe { SpecialU32::try_from_glib(-42) }
3100 .unwrap_err()
3101 .is_invalid()
3102 );
3103
3104 assert_eq!(
3105 unsafe { Result::<Option<SpecialU32>, _>::from_glib(0) },
3106 Ok(Some(SpecialU32(0)))
3107 );
3108 assert_eq!(
3109 unsafe { Result::<Option<SpecialU32>, _>::from_glib(42) },
3110 Ok(Some(SpecialU32(42)))
3111 );
3112 assert_eq!(
3113 unsafe { Result::<Option<SpecialU32>, _>::from_glib(SpecialU32::GLIB_NONE) },
3114 Ok(None)
3115 );
3116 assert!(unsafe { Result::<Option<SpecialU32>, _>::from_glib(-42) }.is_err());
3117 }
3118}