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