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