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(windows)]
1747pub(crate) unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
1748 debug_assert!(!ptr.is_null());
1749
1750 String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
1755 .expect("Invalid, non-UTF8 path")
1756 .into()
1757}
1758
1759#[cfg(not(windows))]
1760pub(crate) unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
1761 unsafe {
1762 debug_assert!(!ptr.is_null());
1763
1764 OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec())
1768 }
1769}
1770
1771#[cfg(windows)]
1772pub(crate) unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
1773 debug_assert!(!ptr.is_null());
1774
1775 String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
1781 .expect("Invalid, non-UTF8 path")
1782 .into()
1783}
1784
1785impl FromGlibPtrNone<*const c_char> for PathBuf {
1786 #[inline]
1787 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1788 unsafe {
1789 debug_assert!(!ptr.is_null());
1790 c_to_path_buf(ptr)
1791 }
1792 }
1793}
1794
1795impl FromGlibPtrFull<*const c_char> for PathBuf {
1796 #[inline]
1797 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1798 unsafe {
1799 let res = from_glib_none(ptr);
1800 ffi::g_free(ptr as *mut _);
1801 res
1802 }
1803 }
1804}
1805
1806impl FromGlibPtrNone<*mut c_char> for PathBuf {
1807 #[inline]
1808 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1809 unsafe {
1810 debug_assert!(!ptr.is_null());
1811 c_to_path_buf(ptr)
1812 }
1813 }
1814}
1815
1816impl FromGlibPtrFull<*mut c_char> for PathBuf {
1817 #[inline]
1818 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1819 unsafe {
1820 let res = from_glib_none(ptr);
1821 ffi::g_free(ptr as *mut _);
1822 res
1823 }
1824 }
1825}
1826
1827#[cfg(not(windows))]
1828pub(crate) unsafe fn c_to_path_buf_num(ptr: *const c_char, num: usize) -> PathBuf {
1829 unsafe {
1830 debug_assert!(!ptr.is_null());
1831 let slice = std::slice::from_raw_parts(ptr as *const u8, num);
1832 OsString::from_vec(slice.to_vec()).into()
1833 }
1834}
1835
1836#[cfg(windows)]
1837pub(crate) unsafe fn c_to_path_buf_num(ptr: *const c_char, num: usize) -> PathBuf {
1838 debug_assert!(!ptr.is_null());
1839 let slice = std::slice::from_raw_parts(ptr as *const u8, num);
1840 String::from_utf8(slice.into())
1841 .expect("Invalid, non-UTF8 path")
1842 .into()
1843}
1844
1845#[doc(hidden)]
1846impl FromGlibContainer<*const c_char, *const i8> for PathBuf {
1847 unsafe fn from_glib_none_num(ptr: *const i8, num: usize) -> Self {
1848 unsafe { c_to_path_buf_num(ptr as *const _, num) }
1849 }
1850
1851 unsafe fn from_glib_container_num(ptr: *const i8, num: usize) -> Self {
1852 unsafe { c_to_path_buf_num(ptr as *const _, num) }
1853 }
1854
1855 unsafe fn from_glib_full_num(ptr: *const i8, num: usize) -> Self {
1856 unsafe {
1857 let res = c_to_path_buf_num(ptr as *const _, num);
1858 ffi::g_free(ptr as *mut _);
1859 res
1860 }
1861 }
1862}
1863
1864#[doc(hidden)]
1865impl FromGlibContainer<*const c_char, *mut i8> for PathBuf {
1866 unsafe fn from_glib_none_num(ptr: *mut i8, num: usize) -> Self {
1867 unsafe { FromGlibContainer::from_glib_none_num(ptr as *const i8, num) }
1868 }
1869
1870 unsafe fn from_glib_container_num(ptr: *mut i8, num: usize) -> Self {
1871 unsafe { FromGlibContainer::from_glib_container_num(ptr as *const i8, num) }
1872 }
1873
1874 unsafe fn from_glib_full_num(ptr: *mut i8, num: usize) -> Self {
1875 unsafe { FromGlibContainer::from_glib_full_num(ptr as *const i8, num) }
1876 }
1877}
1878
1879#[doc(hidden)]
1880impl FromGlibContainer<*const c_char, *const u8> for PathBuf {
1881 unsafe fn from_glib_none_num(ptr: *const u8, num: usize) -> Self {
1882 unsafe { FromGlibContainer::from_glib_none_num(ptr as *const i8, num) }
1883 }
1884
1885 unsafe fn from_glib_container_num(ptr: *const u8, num: usize) -> Self {
1886 unsafe { FromGlibContainer::from_glib_container_num(ptr as *const i8, num) }
1887 }
1888
1889 unsafe fn from_glib_full_num(ptr: *const u8, num: usize) -> Self {
1890 unsafe { FromGlibContainer::from_glib_full_num(ptr as *const i8, num) }
1891 }
1892}
1893
1894#[doc(hidden)]
1895impl FromGlibContainer<*const c_char, *mut u8> for PathBuf {
1896 unsafe fn from_glib_none_num(ptr: *mut u8, num: usize) -> Self {
1897 unsafe { FromGlibContainer::from_glib_none_num(ptr as *const i8, num) }
1898 }
1899
1900 unsafe fn from_glib_container_num(ptr: *mut u8, num: usize) -> Self {
1901 unsafe { FromGlibContainer::from_glib_container_num(ptr as *const i8, num) }
1902 }
1903
1904 unsafe fn from_glib_full_num(ptr: *mut u8, num: usize) -> Self {
1905 unsafe { FromGlibContainer::from_glib_full_num(ptr as *const i8, num) }
1906 }
1907}
1908
1909impl FromGlibPtrNone<*const c_char> for OsString {
1910 #[inline]
1911 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1912 unsafe {
1913 debug_assert!(!ptr.is_null());
1914 c_to_os_string(ptr)
1915 }
1916 }
1917}
1918
1919impl FromGlibPtrFull<*const c_char> for OsString {
1920 #[inline]
1921 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1922 unsafe {
1923 let res = from_glib_none(ptr);
1924 ffi::g_free(ptr as *mut _);
1925 res
1926 }
1927 }
1928}
1929
1930impl FromGlibPtrNone<*mut c_char> for OsString {
1931 #[inline]
1932 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1933 unsafe {
1934 debug_assert!(!ptr.is_null());
1935 c_to_os_string(ptr)
1936 }
1937 }
1938}
1939
1940impl FromGlibPtrFull<*mut c_char> for OsString {
1941 #[inline]
1942 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1943 unsafe {
1944 let res = from_glib_none(ptr);
1945 ffi::g_free(ptr as *mut _);
1946 res
1947 }
1948 }
1949}
1950
1951pub trait FromGlibContainer<T, P: Ptr>: Sized {
1953 unsafe fn from_glib_none_num(ptr: P, num: usize) -> Self;
1957
1958 unsafe fn from_glib_container_num(ptr: P, num: usize) -> Self;
1962
1963 unsafe fn from_glib_full_num(ptr: P, num: usize) -> Self;
1967}
1968
1969pub trait FromGlibPtrContainer<P: Ptr, PP: Ptr>: FromGlibContainer<P, PP> + Sized {
1971 unsafe fn from_glib_none(ptr: PP) -> Self;
1973
1974 unsafe fn from_glib_container(ptr: PP) -> Self;
1976
1977 unsafe fn from_glib_full(ptr: PP) -> Self;
1979}
1980
1981pub unsafe fn c_ptr_array_len<P: Ptr>(mut ptr: *const P) -> usize {
1982 unsafe {
1983 let mut len = 0;
1984
1985 if !ptr.is_null() {
1986 while !(*ptr).is_null() {
1987 len += 1;
1988 ptr = ptr.offset(1);
1989 }
1990 }
1991 len
1992 }
1993}
1994
1995pub trait FromGlibContainerAsVec<T, P: Ptr>
1996where
1997 Self: Sized,
1998{
1999 unsafe fn from_glib_none_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
2000 unsafe fn from_glib_container_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
2001 unsafe fn from_glib_full_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
2002}
2003
2004pub trait FromGlibPtrArrayContainerAsVec<P: Ptr, PP: Ptr>: FromGlibContainerAsVec<P, PP>
2005where
2006 Self: Sized,
2007{
2008 unsafe fn from_glib_none_as_vec(ptr: PP) -> Vec<Self>;
2009 unsafe fn from_glib_container_as_vec(ptr: PP) -> Vec<Self>;
2010 unsafe fn from_glib_full_as_vec(ptr: PP) -> Vec<Self>;
2011}
2012
2013impl FromGlibContainerAsVec<bool, *const ffi::gboolean> for bool {
2014 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::gboolean, num: usize) -> Vec<Self> {
2015 unsafe {
2016 if num == 0 || ptr.is_null() {
2017 return Vec::new();
2018 }
2019
2020 let mut res = Vec::<Self>::with_capacity(num);
2021 let res_ptr = res.as_mut_ptr();
2022 for i in 0..num {
2023 *res_ptr.add(i) = from_glib(ptr::read(ptr.add(i)));
2024 }
2025 res.set_len(num);
2026 res
2027 }
2028 }
2029
2030 unsafe fn from_glib_container_num_as_vec(_: *const ffi::gboolean, _: usize) -> Vec<Self> {
2031 unimplemented!();
2033 }
2034
2035 unsafe fn from_glib_full_num_as_vec(_: *const ffi::gboolean, _: usize) -> Vec<Self> {
2036 unimplemented!();
2038 }
2039}
2040
2041impl FromGlibContainerAsVec<bool, *mut ffi::gboolean> for bool {
2042 unsafe fn from_glib_none_num_as_vec(ptr: *mut ffi::gboolean, num: usize) -> Vec<Self> {
2043 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) }
2044 }
2045
2046 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::gboolean, num: usize) -> Vec<Self> {
2047 unsafe {
2048 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2049 ffi::g_free(ptr as *mut _);
2050 res
2051 }
2052 }
2053
2054 unsafe fn from_glib_full_num_as_vec(ptr: *mut ffi::gboolean, num: usize) -> Vec<Self> {
2055 unsafe { FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) }
2056 }
2057}
2058
2059macro_rules! impl_from_glib_container_as_vec_fundamental {
2060 ($name:ty) => {
2061 unsafe impl TransparentType for $name {
2062 type GlibType = $name;
2063 }
2064
2065 impl FromGlibContainerAsVec<$name, *const $name> for $name {
2066 unsafe fn from_glib_none_num_as_vec(ptr: *const $name, num: usize) -> Vec<Self> {
2067 unsafe {
2068 if num == 0 || ptr.is_null() {
2069 return Vec::new();
2070 }
2071
2072 let mut res = Vec::with_capacity(num);
2073 let res_ptr = res.as_mut_ptr();
2074 std::ptr::copy_nonoverlapping(ptr, res_ptr, num);
2075 res.set_len(num);
2076 res
2077 }
2078 }
2079
2080 unsafe fn from_glib_container_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
2081 unimplemented!();
2083 }
2084
2085 unsafe fn from_glib_full_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
2086 unimplemented!();
2088 }
2089 }
2090
2091 impl FromGlibContainerAsVec<$name, *mut $name> for $name {
2092 unsafe fn from_glib_none_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
2093 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) }
2094 }
2095
2096 unsafe fn from_glib_container_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
2097 unsafe {
2098 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2099 ffi::g_free(ptr as *mut _);
2100 res
2101 }
2102 }
2103
2104 unsafe fn from_glib_full_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
2105 unsafe { FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) }
2106 }
2107 }
2108 };
2109}
2110
2111impl_from_glib_container_as_vec_fundamental!(u8);
2112impl_from_glib_container_as_vec_fundamental!(i8);
2113impl_from_glib_container_as_vec_fundamental!(u16);
2114impl_from_glib_container_as_vec_fundamental!(i16);
2115impl_from_glib_container_as_vec_fundamental!(u32);
2116impl_from_glib_container_as_vec_fundamental!(i32);
2117impl_from_glib_container_as_vec_fundamental!(u64);
2118impl_from_glib_container_as_vec_fundamental!(i64);
2119impl_from_glib_container_as_vec_fundamental!(f32);
2120impl_from_glib_container_as_vec_fundamental!(f64);
2121
2122macro_rules! impl_from_glib_container_as_vec_string {
2123 ($name:ty, $ffi_name:ty) => {
2124 impl FromGlibContainerAsVec<$ffi_name, *const $ffi_name> for $name {
2125 unsafe fn from_glib_none_num_as_vec(ptr: *const $ffi_name, num: usize) -> Vec<Self> {
2126 unsafe {
2127 if num == 0 || ptr.is_null() {
2128 return Vec::new();
2129 }
2130
2131 let mut res = Vec::<Self>::with_capacity(num);
2132 let res_ptr = res.as_mut_ptr();
2133 for i in 0..num {
2134 std::ptr::write(
2135 res_ptr.add(i),
2136 from_glib_none(ptr::read(ptr.add(i)) as $ffi_name),
2137 );
2138 }
2139 res.set_len(num);
2140 res
2141 }
2142 }
2143
2144 unsafe fn from_glib_container_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
2145 unimplemented!();
2147 }
2148
2149 unsafe fn from_glib_full_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
2150 unimplemented!();
2152 }
2153 }
2154
2155 impl FromGlibContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
2156 unsafe fn from_glib_none_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
2157 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num) }
2158 }
2159
2160 unsafe fn from_glib_container_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
2161 unsafe {
2162 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2163 ffi::g_free(ptr as *mut _);
2164 res
2165 }
2166 }
2167
2168 unsafe fn from_glib_full_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
2169 unsafe {
2170 if num == 0 || ptr.is_null() {
2171 ffi::g_free(ptr as *mut _);
2172 return Vec::new();
2173 }
2174
2175 let mut res = Vec::<Self>::with_capacity(num);
2176 let res_ptr = res.as_mut_ptr();
2177 for i in 0..num {
2178 std::ptr::write(
2179 res_ptr.add(i),
2180 from_glib_full(ptr::read(ptr.add(i)) as $ffi_name),
2181 );
2182 }
2183 res.set_len(num);
2184 ffi::g_free(ptr as *mut _);
2185 res
2186 }
2187 }
2188 }
2189
2190 impl FromGlibPtrArrayContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
2191 unsafe fn from_glib_none_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
2192 unsafe {
2193 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
2194 }
2195 }
2196
2197 unsafe fn from_glib_container_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
2198 unsafe {
2199 FromGlibContainerAsVec::from_glib_container_num_as_vec(
2200 ptr,
2201 c_ptr_array_len(ptr),
2202 )
2203 }
2204 }
2205
2206 unsafe fn from_glib_full_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
2207 unsafe {
2208 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
2209 }
2210 }
2211 }
2212
2213 impl FromGlibPtrArrayContainerAsVec<$ffi_name, *const $ffi_name> for $name {
2214 unsafe fn from_glib_none_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
2215 unsafe {
2216 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
2217 }
2218 }
2219
2220 unsafe fn from_glib_container_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
2221 unsafe {
2222 FromGlibContainerAsVec::from_glib_container_num_as_vec(
2223 ptr,
2224 c_ptr_array_len(ptr),
2225 )
2226 }
2227 }
2228
2229 unsafe fn from_glib_full_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
2230 unsafe {
2231 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
2232 }
2233 }
2234 }
2235 };
2236}
2237
2238impl_from_glib_container_as_vec_string!(String, *const c_char);
2240impl_from_glib_container_as_vec_string!(String, *mut c_char);
2241
2242impl_from_glib_container_as_vec_string!(PathBuf, *const c_char);
2243impl_from_glib_container_as_vec_string!(PathBuf, *mut c_char);
2244impl_from_glib_container_as_vec_string!(OsString, *const c_char);
2245impl_from_glib_container_as_vec_string!(OsString, *mut c_char);
2246
2247impl<P, PP: Ptr, T: FromGlibContainerAsVec<P, PP>> FromGlibContainer<P, PP> for Vec<T> {
2248 unsafe fn from_glib_none_num(ptr: PP, num: usize) -> Vec<T> {
2249 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num) }
2250 }
2251
2252 unsafe fn from_glib_container_num(ptr: PP, num: usize) -> Vec<T> {
2253 unsafe { FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num) }
2254 }
2255
2256 unsafe fn from_glib_full_num(ptr: PP, num: usize) -> Vec<T> {
2257 unsafe { FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, num) }
2258 }
2259}
2260
2261impl<P: Ptr, PP: Ptr, T: FromGlibPtrArrayContainerAsVec<P, PP>> FromGlibPtrContainer<P, PP>
2262 for Vec<T>
2263{
2264 unsafe fn from_glib_none(ptr: PP) -> Vec<T> {
2265 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr) }
2266 }
2267
2268 unsafe fn from_glib_container(ptr: PP) -> Vec<T> {
2269 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_container_as_vec(ptr) }
2270 }
2271
2272 unsafe fn from_glib_full(ptr: PP) -> Vec<T> {
2273 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_full_as_vec(ptr) }
2274 }
2275}
2276
2277impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList> for T
2278where
2279 T: GlibPtrDefault
2280 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2281 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2282{
2283 unsafe fn from_glib_none_num_as_vec(mut ptr: *mut ffi::GSList, num: usize) -> Vec<T> {
2284 unsafe {
2285 if num == 0 || ptr.is_null() {
2286 return Vec::new();
2287 }
2288 let mut res = Vec::with_capacity(num);
2289 for _ in 0..num {
2290 if ptr.is_null() {
2291 break;
2292 }
2293
2294 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2295 if !item_ptr.is_null() {
2296 res.push(from_glib_none(item_ptr));
2297 }
2298 ptr = (*ptr).next;
2299 }
2300 res
2301 }
2302 }
2303
2304 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GSList, num: usize) -> Vec<T> {
2305 unsafe {
2306 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2307 ffi::g_slist_free(ptr);
2308 res
2309 }
2310 }
2311
2312 unsafe fn from_glib_full_num_as_vec(mut ptr: *mut ffi::GSList, num: usize) -> Vec<T> {
2313 unsafe {
2314 if num == 0 || ptr.is_null() {
2315 return Vec::new();
2316 }
2317 let orig_ptr = ptr;
2318 let mut res = Vec::with_capacity(num);
2319 for _ in 0..num {
2320 if ptr.is_null() {
2321 break;
2322 }
2323
2324 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2325 if !item_ptr.is_null() {
2326 res.push(from_glib_full(item_ptr));
2327 }
2328 ptr = (*ptr).next;
2329 }
2330 ffi::g_slist_free(orig_ptr);
2331 res
2332 }
2333 }
2334}
2335
2336impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList> for T
2337where
2338 T: GlibPtrDefault
2339 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2340 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2341{
2342 unsafe fn from_glib_none_as_vec(mut ptr: *mut ffi::GSList) -> Vec<T> {
2343 unsafe {
2344 let mut res = Vec::new();
2345 while !ptr.is_null() {
2346 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2347 if !item_ptr.is_null() {
2348 res.push(from_glib_none(item_ptr));
2349 }
2350 ptr = (*ptr).next;
2351 }
2352 res
2353 }
2354 }
2355
2356 unsafe fn from_glib_container_as_vec(ptr: *mut ffi::GSList) -> Vec<T> {
2357 unsafe {
2358 let res = FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr);
2359 ffi::g_slist_free(ptr);
2360 res
2361 }
2362 }
2363
2364 unsafe fn from_glib_full_as_vec(mut ptr: *mut ffi::GSList) -> Vec<T> {
2365 unsafe {
2366 let orig_ptr = ptr;
2367 let mut res = Vec::new();
2368 while !ptr.is_null() {
2369 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2370 if !item_ptr.is_null() {
2371 res.push(from_glib_full(item_ptr));
2372 }
2373 ptr = (*ptr).next;
2374 }
2375 ffi::g_slist_free(orig_ptr);
2376 res
2377 }
2378 }
2379}
2380
2381impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GList> for T
2382where
2383 T: GlibPtrDefault
2384 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2385 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2386{
2387 unsafe fn from_glib_none_num_as_vec(mut ptr: *mut ffi::GList, num: usize) -> Vec<T> {
2388 unsafe {
2389 if num == 0 || ptr.is_null() {
2390 return Vec::new();
2391 }
2392 let mut res = Vec::with_capacity(num);
2393 for _ in 0..num {
2394 if ptr.is_null() {
2395 break;
2396 }
2397
2398 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2399 if !item_ptr.is_null() {
2400 res.push(from_glib_none(item_ptr));
2401 }
2402 ptr = (*ptr).next;
2403 }
2404 res
2405 }
2406 }
2407
2408 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GList, num: usize) -> Vec<T> {
2409 unsafe {
2410 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
2411 ffi::g_list_free(ptr);
2412 res
2413 }
2414 }
2415
2416 unsafe fn from_glib_full_num_as_vec(mut ptr: *mut ffi::GList, num: usize) -> Vec<T> {
2417 unsafe {
2418 if num == 0 || ptr.is_null() {
2419 return Vec::new();
2420 }
2421 let orig_ptr = ptr;
2422 let mut res = Vec::with_capacity(num);
2423 for _ in 0..num {
2424 if ptr.is_null() {
2425 break;
2426 }
2427
2428 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2429 if !item_ptr.is_null() {
2430 res.push(from_glib_full(item_ptr));
2431 }
2432 ptr = (*ptr).next;
2433 }
2434 ffi::g_list_free(orig_ptr);
2435 res
2436 }
2437 }
2438}
2439
2440impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GList> for T
2441where
2442 T: GlibPtrDefault
2443 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2444 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2445{
2446 unsafe fn from_glib_none_as_vec(mut ptr: *mut ffi::GList) -> Vec<T> {
2447 unsafe {
2448 let mut res = Vec::new();
2449 while !ptr.is_null() {
2450 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2451 if !item_ptr.is_null() {
2452 res.push(from_glib_none(item_ptr));
2453 }
2454 ptr = (*ptr).next;
2455 }
2456 res
2457 }
2458 }
2459
2460 unsafe fn from_glib_container_as_vec(ptr: *mut ffi::GList) -> Vec<T> {
2461 unsafe {
2462 let res = FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr);
2463 ffi::g_list_free(ptr);
2464 res
2465 }
2466 }
2467
2468 unsafe fn from_glib_full_as_vec(mut ptr: *mut ffi::GList) -> Vec<T> {
2469 unsafe {
2470 let orig_ptr = ptr;
2471 let mut res = Vec::new();
2472 while !ptr.is_null() {
2473 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
2474 if !item_ptr.is_null() {
2475 res.push(from_glib_full(item_ptr));
2476 }
2477 ptr = (*ptr).next;
2478 }
2479 ffi::g_list_free(orig_ptr);
2480 res
2481 }
2482 }
2483}
2484
2485impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GList> for T
2486where
2487 T: GlibPtrDefault
2488 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2489 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2490{
2491 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GList, num: usize) -> Vec<T> {
2492 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(mut_override(ptr), num) }
2493 }
2494
2495 unsafe fn from_glib_container_num_as_vec(_: *const ffi::GList, _: usize) -> Vec<T> {
2496 unimplemented!()
2498 }
2499
2500 unsafe fn from_glib_full_num_as_vec(_: *const ffi::GList, _: usize) -> Vec<T> {
2501 unimplemented!()
2503 }
2504}
2505
2506impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GList> for T
2507where
2508 T: GlibPtrDefault
2509 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2510 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2511{
2512 unsafe fn from_glib_none_as_vec(ptr: *const ffi::GList) -> Vec<T> {
2513 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(mut_override(ptr)) }
2514 }
2515
2516 unsafe fn from_glib_container_as_vec(_: *const ffi::GList) -> Vec<T> {
2517 unimplemented!()
2519 }
2520
2521 unsafe fn from_glib_full_as_vec(_: *const ffi::GList) -> Vec<T> {
2522 unimplemented!()
2524 }
2525}
2526
2527impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GSList> for T
2528where
2529 T: GlibPtrDefault
2530 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2531 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2532{
2533 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GSList, num: usize) -> Vec<T> {
2534 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(mut_override(ptr), num) }
2535 }
2536
2537 unsafe fn from_glib_container_num_as_vec(_: *const ffi::GSList, _: usize) -> Vec<T> {
2538 unimplemented!()
2540 }
2541
2542 unsafe fn from_glib_full_num_as_vec(_: *const ffi::GSList, _: usize) -> Vec<T> {
2543 unimplemented!()
2545 }
2546}
2547
2548impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GSList> for T
2549where
2550 T: GlibPtrDefault
2551 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2552 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2553{
2554 unsafe fn from_glib_none_as_vec(ptr: *const ffi::GSList) -> Vec<T> {
2555 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(mut_override(ptr)) }
2556 }
2557
2558 unsafe fn from_glib_container_as_vec(_: *const ffi::GSList) -> Vec<T> {
2559 unimplemented!()
2561 }
2562
2563 unsafe fn from_glib_full_as_vec(_: *const ffi::GSList) -> Vec<T> {
2564 unimplemented!()
2566 }
2567}
2568
2569#[allow(clippy::implicit_hasher)]
2570impl FromGlibContainer<*const c_char, *mut ffi::GHashTable> for HashMap<String, String> {
2571 unsafe fn from_glib_none_num(ptr: *mut ffi::GHashTable, _: usize) -> Self {
2572 unsafe { FromGlibPtrContainer::from_glib_none(ptr) }
2573 }
2574
2575 unsafe fn from_glib_container_num(ptr: *mut ffi::GHashTable, _: usize) -> Self {
2576 unsafe { FromGlibPtrContainer::from_glib_full(ptr) }
2577 }
2578
2579 unsafe fn from_glib_full_num(ptr: *mut ffi::GHashTable, _: usize) -> Self {
2580 unsafe { FromGlibPtrContainer::from_glib_full(ptr) }
2581 }
2582}
2583
2584#[allow(clippy::implicit_hasher)]
2585impl FromGlibPtrContainer<*const c_char, *mut ffi::GHashTable> for HashMap<String, String> {
2586 unsafe fn from_glib_none(ptr: *mut ffi::GHashTable) -> Self {
2587 unsafe {
2588 unsafe extern "C" fn read_string_hash_table(
2589 key: ffi::gpointer,
2590 value: ffi::gpointer,
2591 hash_map: ffi::gpointer,
2592 ) {
2593 unsafe {
2594 let key: String = from_glib_none(key as *const c_char);
2595 let value: String = from_glib_none(value as *const c_char);
2596 let hash_map: &mut HashMap<String, String> =
2597 &mut *(hash_map as *mut HashMap<String, String>);
2598 hash_map.insert(key, value);
2599 }
2600 }
2601 let mut map = HashMap::with_capacity(ffi::g_hash_table_size(ptr) as usize);
2602 ffi::g_hash_table_foreach(
2603 ptr,
2604 Some(read_string_hash_table),
2605 &mut map as *mut HashMap<String, String> as *mut _,
2606 );
2607 map
2608 }
2609 }
2610
2611 unsafe fn from_glib_container(ptr: *mut ffi::GHashTable) -> Self {
2612 unsafe { FromGlibPtrContainer::from_glib_full(ptr) }
2613 }
2614
2615 unsafe fn from_glib_full(ptr: *mut ffi::GHashTable) -> Self {
2616 unsafe {
2617 let map = FromGlibPtrContainer::from_glib_none(ptr);
2618 ffi::g_hash_table_unref(ptr);
2619 map
2620 }
2621 }
2622}
2623
2624impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GPtrArray> for T
2625where
2626 T: GlibPtrDefault
2627 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2628 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2629{
2630 unsafe fn from_glib_none_num_as_vec(ptr: *mut ffi::GPtrArray, num: usize) -> Vec<T> {
2631 unsafe {
2632 if num == 0 || ptr.is_null() {
2633 return Vec::new();
2634 }
2635 let pdata = (*ptr).pdata;
2636 debug_assert!((*ptr).len as usize >= num);
2637 let mut res = Vec::with_capacity(num);
2638 for i in 0..num {
2639 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from(ptr::read(pdata.add(i)));
2640 if !item_ptr.is_null() {
2641 res.push(from_glib_none(item_ptr));
2642 }
2643 }
2644 res
2645 }
2646 }
2647
2648 unsafe fn from_glib_container_num_as_vec(ptr: *mut ffi::GPtrArray, num: usize) -> Vec<T> {
2649 unsafe {
2650 let res = FromGlibContainer::from_glib_none_num(ptr, num);
2651 if !ptr.is_null() {
2652 ffi::g_ptr_array_unref(ptr);
2653 }
2654 res
2655 }
2656 }
2657
2658 unsafe fn from_glib_full_num_as_vec(ptr: *mut ffi::GPtrArray, num: usize) -> Vec<T> {
2659 unsafe {
2660 if ptr.is_null() {
2661 return Vec::new();
2662 }
2663 if num == 0 {
2664 ffi::g_ptr_array_unref(ptr);
2665 return Vec::new();
2666 }
2667 let pdata = (*ptr).pdata;
2668 debug_assert!((*ptr).len as usize >= num);
2669 let mut res = Vec::with_capacity(num);
2670 for i in 0..num {
2671 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from(ptr::read(pdata.add(i)));
2672 if !item_ptr.is_null() {
2673 res.push(from_glib_none(item_ptr));
2674 }
2675 }
2676 ffi::g_ptr_array_unref(ptr);
2677 res
2678 }
2679 }
2680}
2681
2682impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut ffi::GPtrArray> for T
2683where
2684 T: GlibPtrDefault
2685 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2686 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2687{
2688 unsafe fn from_glib_none_as_vec(ptr: *mut ffi::GPtrArray) -> Vec<T> {
2689 unsafe {
2690 let num = (*ptr).len as usize;
2691 FromGlibContainer::from_glib_none_num(ptr, num)
2692 }
2693 }
2694
2695 unsafe fn from_glib_container_as_vec(ptr: *mut ffi::GPtrArray) -> Vec<T> {
2696 unsafe {
2697 let num = (*ptr).len as usize;
2698 FromGlibContainer::from_glib_container_num(ptr, num)
2699 }
2700 }
2701
2702 unsafe fn from_glib_full_as_vec(ptr: *mut ffi::GPtrArray) -> Vec<T> {
2703 unsafe {
2704 let num = (*ptr).len as usize;
2705 FromGlibContainer::from_glib_full_num(ptr, num)
2706 }
2707 }
2708}
2709
2710impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GPtrArray> for T
2711where
2712 T: GlibPtrDefault
2713 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2714 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2715{
2716 unsafe fn from_glib_none_num_as_vec(ptr: *const ffi::GPtrArray, num: usize) -> Vec<T> {
2717 unsafe { FromGlibContainerAsVec::from_glib_none_num_as_vec(mut_override(ptr), num) }
2718 }
2719
2720 unsafe fn from_glib_container_num_as_vec(_: *const ffi::GPtrArray, _: usize) -> Vec<T> {
2721 unimplemented!()
2723 }
2724
2725 unsafe fn from_glib_full_num_as_vec(_: *const ffi::GPtrArray, _: usize) -> Vec<T> {
2726 unimplemented!()
2728 }
2729}
2730
2731impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const ffi::GPtrArray> for T
2732where
2733 T: GlibPtrDefault
2734 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
2735 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
2736{
2737 unsafe fn from_glib_none_as_vec(ptr: *const ffi::GPtrArray) -> Vec<T> {
2738 unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(mut_override(ptr)) }
2739 }
2740
2741 unsafe fn from_glib_container_as_vec(_: *const ffi::GPtrArray) -> Vec<T> {
2742 unimplemented!()
2744 }
2745
2746 unsafe fn from_glib_full_as_vec(_: *const ffi::GPtrArray) -> Vec<T> {
2747 unimplemented!()
2749 }
2750}
2751
2752pub unsafe trait TransparentPtrType: Clone + Sized + GlibPtrDefault {}
2757
2758pub unsafe trait TransparentType: Clone + Sized {
2763 type GlibType;
2764}
2765
2766unsafe impl<T: TransparentPtrType> TransparentType for T {
2767 type GlibType = <T as GlibPtrDefault>::GlibType;
2768}
2769
2770#[cfg(test)]
2771mod tests {
2772 use std::{collections::HashMap, fs};
2773
2774 use tempfile::tempdir;
2775
2776 use super::*;
2777 use crate::{FileTest, GString};
2778
2779 #[test]
2780 fn boolean() {
2781 assert_eq!(true.into_glib(), ffi::GTRUE);
2782 assert_eq!(false.into_glib(), ffi::GFALSE);
2783 assert!(unsafe { bool::from_glib(ffi::GTRUE) });
2784 assert!(!unsafe { bool::from_glib(ffi::GFALSE) });
2785 assert!(unsafe { bool::from_glib(42) });
2786 }
2787
2788 #[test]
2789 fn ordering() {
2790 assert_eq!(Ordering::Less.into_glib(), -1);
2791 assert_eq!(Ordering::Equal.into_glib(), 0);
2792 assert_eq!(Ordering::Greater.into_glib(), 1);
2793 assert_eq!(Ordering::Less, unsafe { Ordering::from_glib(-42) });
2794 assert_eq!(Ordering::Less, unsafe { Ordering::from_glib(-1) });
2795 assert_eq!(Ordering::Equal, unsafe { Ordering::from_glib(0) });
2796 assert_eq!(Ordering::Greater, unsafe { Ordering::from_glib(1) });
2797 assert_eq!(Ordering::Greater, unsafe { Ordering::from_glib(42) });
2798 }
2799
2800 #[test]
2801 fn string() {
2802 let s = "ABC";
2803 let owned = "ABC".to_string();
2804 let cstring = CString::new("ABC").unwrap();
2805
2806 let stash = s.to_glib_none();
2807 assert_eq!(unsafe { CStr::from_ptr(stash.0) }, cstring.as_c_str());
2808
2809 let stash = owned.to_glib_none();
2810 assert_eq!(unsafe { CStr::from_ptr(stash.0) }, cstring.as_c_str());
2811
2812 let ptr: *mut c_char = s.to_glib_full();
2813 assert_eq!(unsafe { CStr::from_ptr(ptr) }, cstring.as_c_str());
2814
2815 unsafe {
2816 ffi::g_free(ptr as *mut _);
2817 }
2818
2819 let ptr: *mut c_char = owned.to_glib_full();
2820 assert_eq!(unsafe { CStr::from_ptr(ptr) }, cstring.as_c_str());
2821
2822 assert_eq!(s, unsafe { String::from_glib_none(ptr) });
2823 assert_eq!(owned, unsafe { String::from_glib_full(ptr) });
2824 }
2825
2826 #[test]
2827 fn string_hash_map() {
2828 let mut map = HashMap::new();
2829 map.insert("A".into(), "1".into());
2830 map.insert("B".into(), "2".into());
2831 map.insert("C".into(), "3".into());
2832 let ptr: *mut ffi::GHashTable = map.to_glib_full();
2833 let map = unsafe { HashMap::from_glib_full(ptr) };
2834 assert_eq!(map.get("A"), Some(&"1".into()));
2835 assert_eq!(map.get("B"), Some(&"2".into()));
2836 assert_eq!(map.get("C"), Some(&"3".into()));
2837 }
2838
2839 #[test]
2840 fn string_array() {
2841 let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
2842 let stash = v.to_glib_none();
2843 let ptr: *mut *mut c_char = stash.0;
2844 let ptr_copy = unsafe { ffi::g_strdupv(ptr) };
2845
2846 let actual: Vec<String> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
2847 assert_eq!(v, actual);
2848 }
2849
2850 #[test]
2851 fn gstring_array() {
2852 let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
2853 let stash = v.to_glib_none();
2854 let ptr: *mut *mut c_char = stash.0;
2855 let ptr_copy = unsafe { ffi::g_strdupv(ptr) };
2856
2857 let actual: Vec<GString> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
2858 assert_eq!(v, actual);
2859 }
2860
2861 #[test]
2862 fn ptr_array() {
2863 let strings = &["A", "B", "C"];
2864 let (ptr, _stash) =
2865 ToGlibContainerFromSlice::<*mut ffi::GPtrArray>::to_glib_none_from_slice(strings);
2866 let v: Vec<GString> = unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr) };
2867 assert_eq!(&v, strings);
2868 }
2869
2870 #[test]
2871 #[cfg(not(target_os = "macos"))]
2872 fn test_paths() {
2873 let tmp_dir = tempdir().unwrap();
2874
2875 let dir_1 = tmp_dir.path().join("abcd");
2878 fs::create_dir(&dir_1).unwrap();
2879 assert_eq!(crate::path_get_basename(&dir_1), Path::new("abcd"));
2880 assert_eq!(
2881 crate::path_get_basename(dir_1.canonicalize().unwrap()),
2882 Path::new("abcd")
2883 );
2884 #[cfg(not(windows))]
2887 assert_eq!(
2888 crate::path_get_dirname(dir_1.canonicalize().unwrap()),
2889 tmp_dir.path()
2890 );
2891 assert!(crate::file_test(
2892 &dir_1,
2893 FileTest::EXISTS | FileTest::IS_DIR
2894 ));
2895 assert!(crate::file_test(
2896 dir_1.canonicalize().unwrap(),
2897 FileTest::EXISTS | FileTest::IS_DIR
2898 ));
2899
2900 let dir_2 = tmp_dir.as_ref().join("øäöü");
2902 fs::create_dir(&dir_2).unwrap();
2903 assert_eq!(crate::path_get_basename(&dir_2), Path::new("øäöü"));
2904 assert_eq!(
2905 crate::path_get_basename(dir_2.canonicalize().unwrap()),
2906 Path::new("øäöü")
2907 );
2908 #[cfg(not(windows))]
2911 assert_eq!(
2912 crate::path_get_dirname(dir_2.canonicalize().unwrap()),
2913 tmp_dir.path()
2914 );
2915 assert!(crate::file_test(
2916 &dir_2,
2917 FileTest::EXISTS | FileTest::IS_DIR
2918 ));
2919 assert!(crate::file_test(
2920 dir_2.canonicalize().unwrap(),
2921 FileTest::EXISTS | FileTest::IS_DIR
2922 ));
2923 }
2924
2925 #[test]
2926 #[cfg(target_os = "macos")]
2927 fn test_paths() {
2928 let t_dir = tempdir().unwrap();
2929 let tmp_dir = t_dir.path().canonicalize().unwrap();
2930
2931 let dir_1 = tmp_dir.join("abcd");
2934 fs::create_dir(&dir_1).unwrap();
2935 assert_eq!(crate::path_get_basename(&dir_1), Path::new("abcd"));
2936 assert_eq!(
2937 crate::path_get_basename(dir_1.canonicalize().unwrap()),
2938 Path::new("abcd")
2939 );
2940 assert_eq!(
2941 crate::path_get_dirname(dir_1.canonicalize().unwrap()),
2942 tmp_dir
2943 );
2944 assert!(crate::file_test(
2945 &dir_1,
2946 FileTest::EXISTS | FileTest::IS_DIR
2947 ));
2948 assert!(crate::file_test(
2949 &dir_1.canonicalize().unwrap(),
2950 FileTest::EXISTS | FileTest::IS_DIR
2951 ));
2952 }
2953
2954 #[test]
2955 fn none_value() {
2956 const CLONG_NONE: libc::c_long = -1;
2957
2958 #[derive(Debug, PartialEq, Eq)]
2959 struct SpecialU32(u32);
2960 impl IntoGlib for SpecialU32 {
2961 type GlibType = libc::c_uint;
2962 fn into_glib(self) -> libc::c_uint {
2963 self.0 as libc::c_uint
2964 }
2965 }
2966 impl OptionIntoGlib for SpecialU32 {
2967 const GLIB_NONE: Self::GlibType = CLONG_NONE as libc::c_uint;
2968 }
2969
2970 assert_eq!(SpecialU32(0).into_glib(), 0);
2971 assert_eq!(SpecialU32(42).into_glib(), 42);
2972 assert_eq!(Some(SpecialU32(0)).into_glib(), 0);
2973 assert_eq!(Some(SpecialU32(42)).into_glib(), 42);
2974 assert_eq!(
2975 Option::None::<SpecialU32>.into_glib(),
2976 SpecialU32::GLIB_NONE
2977 );
2978
2979 impl TryFromGlib<libc::c_uint> for SpecialU32 {
2980 type Error = GlibNoneError;
2981 #[allow(clippy::unnecessary_cast)]
2982 unsafe fn try_from_glib(val: libc::c_uint) -> Result<Self, GlibNoneError> {
2983 if val == SpecialU32::GLIB_NONE {
2984 return Err(GlibNoneError);
2985 }
2986
2987 Ok(SpecialU32(val as u32))
2988 }
2989 }
2990
2991 assert_eq!(unsafe { SpecialU32::try_from_glib(0) }, Ok(SpecialU32(0)));
2992 assert_eq!(unsafe { SpecialU32::try_from_glib(42) }, Ok(SpecialU32(42)));
2993 assert_eq!(
2994 unsafe { SpecialU32::try_from_glib(SpecialU32::GLIB_NONE) },
2995 Err(GlibNoneError)
2996 );
2997
2998 assert_eq!(
2999 unsafe { Option::<SpecialU32>::from_glib(0) },
3000 Some(SpecialU32(0))
3001 );
3002 assert_eq!(
3003 unsafe { Option::<SpecialU32>::from_glib(42) },
3004 Some(SpecialU32(42))
3005 );
3006 assert!(unsafe { Option::<SpecialU32>::from_glib(SpecialU32::GLIB_NONE) }.is_none());
3007 }
3008
3009 #[test]
3010 fn invalid_value() {
3011 use std::num::TryFromIntError;
3012
3013 #[derive(Debug, PartialEq, Eq)]
3014 struct U32(u32);
3015
3016 impl TryFromGlib<libc::c_long> for U32 {
3017 type Error = TryFromIntError;
3018 unsafe fn try_from_glib(val: libc::c_long) -> Result<Self, TryFromIntError> {
3019 Ok(U32(u32::try_from(val)?))
3020 }
3021 }
3022
3023 assert_eq!(unsafe { U32::try_from_glib(0) }, Ok(U32(0)));
3024 assert_eq!(unsafe { U32::try_from_glib(42) }, Ok(U32(42)));
3025 assert!(unsafe { U32::try_from_glib(-1) }.is_err());
3026 assert!(unsafe { U32::try_from_glib(-42) }.is_err());
3027 }
3028
3029 #[test]
3030 fn none_or_invalid_value() {
3031 use std::num::TryFromIntError;
3032
3033 #[derive(Debug, PartialEq, Eq)]
3034 struct SpecialU32(u32);
3035 impl IntoGlib for SpecialU32 {
3036 type GlibType = libc::c_long;
3037 fn into_glib(self) -> libc::c_long {
3038 self.0 as libc::c_long
3039 }
3040 }
3041 impl OptionIntoGlib for SpecialU32 {
3042 const GLIB_NONE: Self::GlibType = -1;
3043 }
3044
3045 assert_eq!(SpecialU32(0).into_glib(), 0);
3046 assert_eq!(SpecialU32(42).into_glib(), 42);
3047 assert_eq!(Some(SpecialU32(42)).into_glib(), 42);
3048 assert_eq!(
3049 Option::None::<SpecialU32>.into_glib(),
3050 SpecialU32::GLIB_NONE
3051 );
3052
3053 impl TryFromGlib<libc::c_long> for SpecialU32 {
3054 type Error = GlibNoneOrInvalidError<TryFromIntError>;
3055 unsafe fn try_from_glib(
3056 val: libc::c_long,
3057 ) -> Result<Self, GlibNoneOrInvalidError<TryFromIntError>> {
3058 if val == SpecialU32::GLIB_NONE {
3059 return Err(GlibNoneOrInvalidError::None);
3060 }
3061
3062 Ok(SpecialU32(u32::try_from(val)?))
3063 }
3064 }
3065
3066 assert_eq!(unsafe { SpecialU32::try_from_glib(0) }, Ok(SpecialU32(0)));
3067 assert_eq!(unsafe { SpecialU32::try_from_glib(42) }, Ok(SpecialU32(42)));
3068 assert!(
3069 unsafe { SpecialU32::try_from_glib(SpecialU32::GLIB_NONE) }
3070 .unwrap_err()
3071 .is_none()
3072 );
3073 assert!(
3074 unsafe { SpecialU32::try_from_glib(-42) }
3075 .unwrap_err()
3076 .is_invalid()
3077 );
3078
3079 assert_eq!(
3080 unsafe { Result::<Option<SpecialU32>, _>::from_glib(0) },
3081 Ok(Some(SpecialU32(0)))
3082 );
3083 assert_eq!(
3084 unsafe { Result::<Option<SpecialU32>, _>::from_glib(42) },
3085 Ok(Some(SpecialU32(42)))
3086 );
3087 assert_eq!(
3088 unsafe { Result::<Option<SpecialU32>, _>::from_glib(SpecialU32::GLIB_NONE) },
3089 Ok(None)
3090 );
3091 assert!(unsafe { Result::<Option<SpecialU32>, _>::from_glib(-42) }.is_err());
3092 }
3093}