1use glib_sys;
51use libc::{c_char, size_t};
52use std::char;
53use std::cmp::Ordering;
54use std::collections::HashMap;
55use std::ffi::{CStr, CString};
56use std::ffi::{OsStr, OsString};
57use std::mem;
58#[cfg(not(windows))]
59use std::os::unix::prelude::*;
60use std::path::{Path, PathBuf};
61use std::ptr;
62
63pub trait Ptr: Copy + 'static {
65 fn is_null(&self) -> bool;
66 fn from<X>(ptr: *mut X) -> Self;
67 fn to<X>(self) -> *mut X;
68}
69
70impl<T: 'static> Ptr for *const T {
71 #[inline]
72 fn is_null(&self) -> bool {
73 (*self).is_null()
74 }
75
76 #[inline]
77 fn from<X>(ptr: *mut X) -> *const T {
78 ptr as *const T
79 }
80
81 #[inline]
82 fn to<X>(self) -> *mut X {
83 self as *mut X
84 }
85}
86
87impl<T: 'static> Ptr for *mut T {
88 #[inline]
89 fn is_null(&self) -> bool {
90 (*self).is_null()
91 }
92
93 #[inline]
94 fn from<X>(ptr: *mut X) -> *mut T {
95 ptr as *mut T
96 }
97
98 #[inline]
99 fn to<X>(self) -> *mut X {
100 self as *mut X
101 }
102}
103
104pub fn mut_override<T>(ptr: *const T) -> *mut T {
108 ptr as *mut T
109}
110
111pub fn const_override<T>(ptr: *mut T) -> *const T {
116 ptr as *const T
117}
118
119pub trait Uninitialized {
121 unsafe fn uninitialized() -> Self;
123}
124
125#[inline]
127pub unsafe fn uninitialized<T: Uninitialized>() -> T {
128 T::uninitialized()
129}
130
131pub trait ToBool: Copy {
132 fn to_bool(self) -> bool;
133}
134
135impl ToBool for bool {
136 #[inline]
137 fn to_bool(self) -> bool {
138 self
139 }
140}
141
142impl ToBool for glib_sys::gboolean {
143 #[inline]
144 fn to_bool(self) -> bool {
145 self != glib_sys::GFALSE
146 }
147}
148
149#[inline]
151pub fn some_if<B: ToBool, T, F: FnOnce() -> T>(cond: B, f: F) -> Option<T> {
152 if cond.to_bool() {
153 Some(f())
154 } else {
155 None
156 }
157}
158
159pub struct Stash<'a, P: Copy, T: ?Sized + ToGlibPtr<'a, P>>(
188 pub P,
189 pub <T as ToGlibPtr<'a, P>>::Storage,
190);
191
192pub struct StashMut<'a, P: Copy, T: ?Sized>(pub P, pub <T as ToGlibPtrMut<'a, P>>::Storage)
193where
194 T: ToGlibPtrMut<'a, P>;
195
196pub trait ToGlib {
198 type GlibType;
199
200 fn to_glib(&self) -> Self::GlibType;
201}
202
203impl ToGlib for bool {
204 type GlibType = glib_sys::gboolean;
205
206 #[inline]
207 fn to_glib(&self) -> glib_sys::gboolean {
208 if *self {
209 glib_sys::GTRUE
210 } else {
211 glib_sys::GFALSE
212 }
213 }
214}
215
216impl ToGlib for char {
217 type GlibType = u32;
218
219 #[inline]
220 fn to_glib(&self) -> u32 {
221 *self as u32
222 }
223}
224
225impl ToGlib for Option<char> {
226 type GlibType = u32;
227
228 #[inline]
229 fn to_glib(&self) -> u32 {
230 self.as_ref().map(|&c| c as u32).unwrap_or(0)
231 }
232}
233
234impl ToGlib for Ordering {
235 type GlibType = i32;
236
237 #[inline]
238 fn to_glib(&self) -> i32 {
239 match *self {
240 Ordering::Less => -1,
241 Ordering::Equal => 0,
242 Ordering::Greater => 1,
243 }
244 }
245}
246
247pub trait GlibPtrDefault {
251 type GlibType: Ptr;
252}
253
254impl<'a, T: ?Sized + GlibPtrDefault> GlibPtrDefault for &'a T {
255 type GlibType = <T as GlibPtrDefault>::GlibType;
256}
257
258pub trait ToGlibPtr<'a, P: Copy> {
260 type Storage;
261
262 fn to_glib_none(&'a self) -> Stash<'a, P, Self>;
266
267 fn to_glib_container(&'a self) -> Stash<'a, P, Self> {
272 unimplemented!();
273 }
274
275 fn to_glib_full(&self) -> P {
279 unimplemented!();
280 }
281}
282pub trait ToGlibPtrMut<'a, P: Copy> {
285 type Storage;
286
287 fn to_glib_none_mut(&'a mut self) -> StashMut<P, Self>;
291}
292
293impl<'a, P: Ptr, T: ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for Option<T> {
294 type Storage = Option<<T as ToGlibPtr<'a, P>>::Storage>;
295
296 #[inline]
297 fn to_glib_none(&'a self) -> Stash<'a, P, Option<T>> {
298 self.as_ref()
299 .map_or(Stash(Ptr::from::<()>(ptr::null_mut()), None), |s| {
300 let s = s.to_glib_none();
301 Stash(s.0, Some(s.1))
302 })
303 }
304
305 #[inline]
306 fn to_glib_full(&self) -> P {
307 self.as_ref()
308 .map_or(Ptr::from::<()>(ptr::null_mut()), ToGlibPtr::to_glib_full)
309 }
310}
311
312impl<'a, 'opt: 'a, P: Ptr, T: ToGlibPtrMut<'a, P>> ToGlibPtrMut<'a, P> for Option<&'opt mut T> {
313 type Storage = Option<<T as ToGlibPtrMut<'a, P>>::Storage>;
314
315 #[inline]
316 fn to_glib_none_mut(&'a mut self) -> StashMut<'a, P, Option<&'opt mut T>> {
317 self.as_mut()
318 .map_or(StashMut(Ptr::from::<()>(ptr::null_mut()), None), |s| {
319 let s = s.to_glib_none_mut();
320 StashMut(s.0, Some(s.1))
321 })
322 }
323}
324
325impl<'a, P: Ptr, T: ?Sized + ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for &'a T {
326 type Storage = <T as ToGlibPtr<'a, P>>::Storage;
327
328 #[inline]
329 fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
330 let s = (*self).to_glib_none();
331 Stash(s.0, s.1)
332 }
333
334 #[inline]
335 fn to_glib_full(&self) -> P {
336 (*self).to_glib_full()
337 }
338}
339
340impl<'a> ToGlibPtr<'a, *const c_char> for str {
341 type Storage = CString;
342
343 #[inline]
344 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
345 let tmp =
346 CString::new(self).expect("str::ToGlibPtr<*const c_char>: unexpected '\0' character");
347 Stash(tmp.as_ptr(), tmp)
348 }
349
350 #[inline]
351 fn to_glib_full(&self) -> *const c_char {
352 unsafe {
353 glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t)
354 as *const c_char
355 }
356 }
357}
358
359impl<'a> ToGlibPtr<'a, *mut c_char> for str {
360 type Storage = CString;
361
362 #[inline]
363 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
364 let tmp =
365 CString::new(self).expect("str::ToGlibPtr<*mut c_char>: unexpected '\0' character");
366 Stash(tmp.as_ptr() as *mut c_char, tmp)
367 }
368
369 #[inline]
370 fn to_glib_full(&self) -> *mut c_char {
371 unsafe { glib_sys::g_strndup(self.as_ptr() as *mut c_char, self.len() as size_t) }
372 }
373}
374
375impl<'a> ToGlibPtr<'a, *const c_char> for String {
376 type Storage = CString;
377
378 #[inline]
379 fn to_glib_none(&self) -> Stash<'a, *const c_char, String> {
380 let tmp = CString::new(&self[..])
381 .expect("String::ToGlibPtr<*const c_char>: unexpected '\0' character");
382 Stash(tmp.as_ptr(), tmp)
383 }
384
385 #[inline]
386 fn to_glib_full(&self) -> *const c_char {
387 unsafe {
388 glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t)
389 as *const c_char
390 }
391 }
392}
393
394impl<'a> ToGlibPtr<'a, *mut c_char> for String {
395 type Storage = CString;
396
397 #[inline]
398 fn to_glib_none(&self) -> Stash<'a, *mut c_char, String> {
399 let tmp = CString::new(&self[..])
400 .expect("String::ToGlibPtr<*mut c_char>: unexpected '\0' character");
401 Stash(tmp.as_ptr() as *mut c_char, tmp)
402 }
403
404 #[inline]
405 fn to_glib_full(&self) -> *mut c_char {
406 unsafe {
407 glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *mut c_char
408 }
409 }
410}
411
412impl GlibPtrDefault for str {
413 type GlibType = *mut c_char;
414}
415
416impl GlibPtrDefault for String {
417 type GlibType = *mut c_char;
418}
419
420#[cfg(not(windows))]
421fn path_to_c(path: &Path) -> CString {
422 CString::new(path.as_os_str().as_bytes()).expect("Invalid path with NUL bytes")
428}
429
430#[cfg(windows)]
431fn path_to_c(path: &Path) -> CString {
432 let path_str = path
441 .to_str()
442 .expect("Path can't be represented as UTF-8")
443 .to_owned();
444
445 if path_str.starts_with("\\\\?\\") {
451 CString::new(path_str[4..].as_bytes())
452 } else {
453 CString::new(path_str.as_bytes())
454 }
455 .expect("Invalid path with NUL bytes")
456}
457
458#[cfg(not(windows))]
459fn os_str_to_c(s: &OsStr) -> CString {
460 CString::new(s.as_bytes()).expect("Invalid OS String with NUL bytes")
467}
468
469#[cfg(windows)]
470fn os_str_to_c(s: &OsStr) -> CString {
471 let os_str = s
480 .to_str()
481 .expect("OS String can't be represented as UTF-8")
482 .to_owned();
483
484 CString::new(os_str.as_bytes()).expect("Invalid OS string with NUL bytes")
485}
486
487impl<'a> ToGlibPtr<'a, *const c_char> for Path {
488 type Storage = CString;
489
490 #[inline]
491 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
492 let tmp = path_to_c(self);
493 Stash(tmp.as_ptr(), tmp)
494 }
495}
496
497impl<'a> ToGlibPtr<'a, *mut c_char> for Path {
498 type Storage = CString;
499
500 #[inline]
501 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
502 let tmp = path_to_c(self);
503 Stash(tmp.as_ptr() as *mut c_char, tmp)
504 }
505}
506
507impl<'a> ToGlibPtr<'a, *const c_char> for PathBuf {
508 type Storage = CString;
509
510 #[inline]
511 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
512 let tmp = path_to_c(self);
513 Stash(tmp.as_ptr(), tmp)
514 }
515}
516
517impl<'a> ToGlibPtr<'a, *mut c_char> for PathBuf {
518 type Storage = CString;
519
520 #[inline]
521 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
522 let tmp = path_to_c(self);
523 Stash(tmp.as_ptr() as *mut c_char, tmp)
524 }
525}
526
527impl GlibPtrDefault for Path {
528 type GlibType = *mut c_char;
529}
530
531impl GlibPtrDefault for PathBuf {
532 type GlibType = *mut c_char;
533}
534
535impl<'a> ToGlibPtr<'a, *const c_char> for OsStr {
536 type Storage = CString;
537
538 #[inline]
539 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
540 let tmp = os_str_to_c(self);
541 Stash(tmp.as_ptr(), tmp)
542 }
543}
544
545impl<'a> ToGlibPtr<'a, *mut c_char> for OsStr {
546 type Storage = CString;
547
548 #[inline]
549 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
550 let tmp = os_str_to_c(self);
551 Stash(tmp.as_ptr() as *mut c_char, tmp)
552 }
553}
554
555impl<'a> ToGlibPtr<'a, *const c_char> for OsString {
556 type Storage = CString;
557
558 #[inline]
559 fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
560 let tmp = os_str_to_c(self);
561 Stash(tmp.as_ptr(), tmp)
562 }
563}
564
565impl<'a> ToGlibPtr<'a, *mut c_char> for OsString {
566 type Storage = CString;
567
568 #[inline]
569 fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
570 let tmp = os_str_to_c(self);
571 Stash(tmp.as_ptr() as *mut c_char, tmp)
572 }
573}
574
575impl GlibPtrDefault for OsStr {
576 type GlibType = *mut c_char;
577}
578
579impl GlibPtrDefault for OsString {
580 type GlibType = *mut c_char;
581}
582
583pub trait ToGlibContainerFromSlice<'a, P>
584where
585 Self: Sized,
586{
587 type Storage;
588
589 fn to_glib_none_from_slice(t: &'a [Self]) -> (P, Self::Storage);
590 fn to_glib_container_from_slice(t: &'a [Self]) -> (P, Self::Storage);
591 fn to_glib_full_from_slice(t: &[Self]) -> P;
592}
593
594macro_rules! impl_to_glib_container_from_slice_fundamental {
595 ($name:ty) => {
596 impl<'a> ToGlibContainerFromSlice<'a, *mut $name> for $name {
597 type Storage = &'a [$name];
598
599 fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut $name, &'a [$name]) {
600 (t.as_ptr() as *mut $name, t)
601 }
602
603 fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut $name, &'a [$name]) {
604 (ToGlibContainerFromSlice::to_glib_full_from_slice(t), t)
605 }
606
607 fn to_glib_full_from_slice(t: &[$name]) -> *mut $name {
608 if t.len() == 0 {
609 return ptr::null_mut();
610 }
611
612 unsafe {
613 let res = glib_sys::g_malloc(mem::size_of::<$name>() * t.len()) as *mut $name;
614 ptr::copy_nonoverlapping(t.as_ptr(), res, t.len());
615 res
616 }
617 }
618 }
619 };
620}
621
622impl_to_glib_container_from_slice_fundamental!(u8);
623impl_to_glib_container_from_slice_fundamental!(i8);
624impl_to_glib_container_from_slice_fundamental!(u16);
625impl_to_glib_container_from_slice_fundamental!(i16);
626impl_to_glib_container_from_slice_fundamental!(u32);
627impl_to_glib_container_from_slice_fundamental!(i32);
628impl_to_glib_container_from_slice_fundamental!(u64);
629impl_to_glib_container_from_slice_fundamental!(i64);
630impl_to_glib_container_from_slice_fundamental!(f32);
631impl_to_glib_container_from_slice_fundamental!(f64);
632
633macro_rules! impl_to_glib_container_from_slice_string {
634 ($name:ty, $ffi_name:ty) => {
635 impl<'a> ToGlibContainerFromSlice<'a, *mut $ffi_name> for $name {
636 type Storage = (Vec<Stash<'a, $ffi_name, $name>>, Option<Vec<$ffi_name>>);
637
638 fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut $ffi_name, Self::Storage) {
639 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
640 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
641 v_ptr.push(ptr::null_mut() as $ffi_name);
642
643 (v_ptr.as_ptr() as *mut $ffi_name, (v, Some(v_ptr)))
644 }
645
646 fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut $ffi_name, Self::Storage) {
647 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
648
649 let v_ptr = unsafe {
650 let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
651 as *mut $ffi_name;
652
653 for (i, s) in v.iter().enumerate() {
654 ptr::write(v_ptr.add(i), s.0);
655 }
656
657 v_ptr
658 };
659
660 (v_ptr, (v, None))
661 }
662
663 fn to_glib_full_from_slice(t: &[$name]) -> *mut $ffi_name {
664 unsafe {
665 let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
666 as *mut $ffi_name;
667
668 for (i, s) in t.iter().enumerate() {
669 ptr::write(v_ptr.add(i), s.to_glib_full());
670 }
671
672 v_ptr
673 }
674 }
675 }
676 impl<'a> ToGlibContainerFromSlice<'a, *const $ffi_name> for $name {
677 type Storage = (Vec<Stash<'a, $ffi_name, $name>>, Option<Vec<$ffi_name>>);
678
679 fn to_glib_none_from_slice(t: &'a [$name]) -> (*const $ffi_name, Self::Storage) {
680 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
681 let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
682 v_ptr.push(ptr::null_mut() as $ffi_name);
683
684 (v_ptr.as_ptr() as *const $ffi_name, (v, Some(v_ptr)))
685 }
686
687 fn to_glib_container_from_slice(t: &'a [$name]) -> (*const $ffi_name, Self::Storage) {
688 let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
689
690 let v_ptr = unsafe {
691 let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
692 as *mut $ffi_name;
693
694 for (i, s) in v.iter().enumerate() {
695 ptr::write(v_ptr.add(i), s.0);
696 }
697
698 v_ptr as *const $ffi_name
699 };
700
701 (v_ptr, (v, None))
702 }
703
704 fn to_glib_full_from_slice(t: &[$name]) -> *const $ffi_name {
705 unsafe {
706 let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
707 as *mut $ffi_name;
708
709 for (i, s) in t.iter().enumerate() {
710 ptr::write(v_ptr.add(i), s.to_glib_full());
711 }
712
713 v_ptr as *const $ffi_name
714 }
715 }
716 }
717 };
718}
719
720impl_to_glib_container_from_slice_string!(&'a str, *mut c_char);
721impl_to_glib_container_from_slice_string!(&'a str, *const c_char);
722impl_to_glib_container_from_slice_string!(String, *mut c_char);
723impl_to_glib_container_from_slice_string!(String, *const c_char);
724impl_to_glib_container_from_slice_string!(&'a Path, *mut c_char);
725impl_to_glib_container_from_slice_string!(&'a Path, *const c_char);
726impl_to_glib_container_from_slice_string!(PathBuf, *mut c_char);
727impl_to_glib_container_from_slice_string!(PathBuf, *const c_char);
728impl_to_glib_container_from_slice_string!(&'a OsStr, *mut c_char);
729impl_to_glib_container_from_slice_string!(&'a OsStr, *const c_char);
730impl_to_glib_container_from_slice_string!(OsString, *mut c_char);
731impl_to_glib_container_from_slice_string!(OsString, *const c_char);
732
733impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GList> for T
734where
735 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
736{
737 type Storage = (
738 Option<List>,
739 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
740 );
741
742 #[inline]
743 fn to_glib_none_from_slice(t: &'a [T]) -> (*mut glib_sys::GList, Self::Storage) {
744 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
745 let mut list: *mut glib_sys::GList = ptr::null_mut();
746 unsafe {
747 for stash in &stash_vec {
748 list = glib_sys::g_list_prepend(list, Ptr::to(stash.0));
749 }
750 }
751 (list, (Some(List(list)), stash_vec))
752 }
753
754 #[inline]
755 fn to_glib_container_from_slice(t: &'a [T]) -> (*mut glib_sys::GList, Self::Storage) {
756 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
757 let mut list: *mut glib_sys::GList = ptr::null_mut();
758 unsafe {
759 for stash in &stash_vec {
760 list = glib_sys::g_list_prepend(list, Ptr::to(stash.0));
761 }
762 }
763 (list, (None, stash_vec))
764 }
765
766 #[inline]
767 fn to_glib_full_from_slice(t: &[T]) -> *mut glib_sys::GList {
768 let mut list: *mut glib_sys::GList = ptr::null_mut();
769 unsafe {
770 for ptr in t.iter().rev().map(ToGlibPtr::to_glib_full) {
771 list = glib_sys::g_list_prepend(list, Ptr::to(ptr));
772 }
773 }
774 list
775 }
776}
777
778impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GList> for T
779where
780 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
781{
782 type Storage = (
783 Option<List>,
784 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
785 );
786
787 #[inline]
788 fn to_glib_none_from_slice(t: &'a [T]) -> (*const glib_sys::GList, Self::Storage) {
789 let (list, stash) =
790 ToGlibContainerFromSlice::<*mut glib_sys::GList>::to_glib_none_from_slice(t);
791 (list as *const glib_sys::GList, stash)
792 }
793
794 #[inline]
795 fn to_glib_container_from_slice(_t: &'a [T]) -> (*const glib_sys::GList, Self::Storage) {
796 unimplemented!()
797 }
798
799 #[inline]
800 fn to_glib_full_from_slice(_t: &[T]) -> *const glib_sys::GList {
801 unimplemented!()
802 }
803}
804
805pub struct List(*mut glib_sys::GList);
806
807impl Drop for List {
808 fn drop(&mut self) {
809 unsafe { glib_sys::g_list_free(self.0) }
810 }
811}
812
813impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GSList> for &'a T
814where
815 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
816{
817 type Storage = (
818 Option<SList>,
819 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
820 );
821
822 #[inline]
823 fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*mut glib_sys::GSList, Self::Storage) {
824 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
825 let mut list: *mut glib_sys::GSList = ptr::null_mut();
826 unsafe {
827 for stash in &stash_vec {
828 list = glib_sys::g_slist_prepend(list, Ptr::to(stash.0));
829 }
830 }
831 (list, (Some(SList(list)), stash_vec))
832 }
833
834 #[inline]
835 fn to_glib_container_from_slice(t: &'a [&'a T]) -> (*mut glib_sys::GSList, Self::Storage) {
836 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
837 let mut list: *mut glib_sys::GSList = ptr::null_mut();
838 unsafe {
839 for stash in &stash_vec {
840 list = glib_sys::g_slist_prepend(list, Ptr::to(stash.0));
841 }
842 }
843 (list, (None, stash_vec))
844 }
845
846 #[inline]
847 fn to_glib_full_from_slice(t: &[&'a T]) -> *mut glib_sys::GSList {
848 let mut list: *mut glib_sys::GSList = ptr::null_mut();
849 unsafe {
850 for ptr in t.iter().rev().map(ToGlibPtr::to_glib_full) {
851 list = glib_sys::g_slist_prepend(list, Ptr::to(ptr));
852 }
853 }
854 list
855 }
856}
857
858impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GSList> for &'a T
859where
860 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
861{
862 type Storage = (
863 Option<SList>,
864 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
865 );
866
867 #[inline]
868 fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*const glib_sys::GSList, Self::Storage) {
869 let (list, stash) =
870 ToGlibContainerFromSlice::<*mut glib_sys::GSList>::to_glib_none_from_slice(t);
871 (list as *const glib_sys::GSList, stash)
872 }
873
874 #[inline]
875 fn to_glib_container_from_slice(_t: &'a [&'a T]) -> (*const glib_sys::GSList, Self::Storage) {
876 unimplemented!()
877 }
878
879 #[inline]
880 fn to_glib_full_from_slice(_t: &[&'a T]) -> *const glib_sys::GSList {
881 unimplemented!()
882 }
883}
884
885pub struct SList(*mut glib_sys::GSList);
886
887impl Drop for SList {
888 fn drop(&mut self) {
889 unsafe { glib_sys::g_slist_free(self.0) }
890 }
891}
892
893impl<'a, P: Ptr, T: ToGlibContainerFromSlice<'a, P>> ToGlibPtr<'a, P> for [T] {
894 type Storage = T::Storage;
895
896 #[inline]
897 fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
898 let result = ToGlibContainerFromSlice::to_glib_none_from_slice(self);
899 Stash(result.0, result.1)
900 }
901
902 #[inline]
903 fn to_glib_container(&'a self) -> Stash<'a, P, Self> {
904 let result = ToGlibContainerFromSlice::to_glib_container_from_slice(self);
905 Stash(result.0, result.1)
906 }
907
908 #[inline]
909 fn to_glib_full(&self) -> P {
910 ToGlibContainerFromSlice::to_glib_full_from_slice(self)
911 }
912}
913
914#[allow(clippy::implicit_hasher)]
915impl<'a> ToGlibPtr<'a, *mut glib_sys::GHashTable> for HashMap<String, String> {
916 type Storage = (HashTable);
917
918 #[inline]
919 fn to_glib_none(&self) -> Stash<'a, *mut glib_sys::GHashTable, Self> {
920 let ptr = self.to_glib_full();
921 Stash(ptr, HashTable(ptr))
922 }
923
924 #[inline]
925 fn to_glib_full(&self) -> *mut glib_sys::GHashTable {
926 unsafe {
927 let ptr = glib_sys::g_hash_table_new_full(
928 Some(glib_sys::g_str_hash),
929 Some(glib_sys::g_str_equal),
930 Some(glib_sys::g_free),
931 Some(glib_sys::g_free),
932 );
933 for (k, v) in self {
934 let k: *mut c_char = k.to_glib_full();
935 let v: *mut c_char = v.to_glib_full();
936 glib_sys::g_hash_table_insert(ptr, k as *mut _, v as *mut _);
937 }
938 ptr
939 }
940 }
941}
942
943pub struct HashTable(*mut glib_sys::GHashTable);
944
945impl Drop for HashTable {
946 fn drop(&mut self) {
947 unsafe { glib_sys::g_hash_table_unref(self.0) }
948 }
949}
950
951impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GArray> for &'a T
952where
953 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
954{
955 type Storage = (
956 Option<Array>,
957 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
958 );
959
960 #[inline]
961 fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*const glib_sys::GArray, Self::Storage) {
962 let (list, stash) =
963 ToGlibContainerFromSlice::<*mut glib_sys::GArray>::to_glib_none_from_slice(t);
964 (list as *const glib_sys::GArray, stash)
965 }
966
967 #[inline]
968 fn to_glib_container_from_slice(_t: &'a [&'a T]) -> (*const glib_sys::GArray, Self::Storage) {
969 unimplemented!()
970 }
971
972 #[inline]
973 fn to_glib_full_from_slice(_t: &[&'a T]) -> *const glib_sys::GArray {
974 unimplemented!()
975 }
976}
977
978pub struct Array(*mut glib_sys::GArray);
979
980impl Drop for Array {
981 fn drop(&mut self) {
982 unsafe {
983 glib_sys::g_array_free(self.0, false.to_glib());
984 }
985 }
986}
987
988impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GArray> for T
989where
990 T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
991{
992 type Storage = (
993 Option<Array>,
994 Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
995 );
996
997 #[inline]
998 fn to_glib_none_from_slice(t: &'a [T]) -> (*mut glib_sys::GArray, Self::Storage) {
999 let stash_vec: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
1000 let mut arr: *mut glib_sys::GArray = ptr::null_mut();
1001 unsafe {
1002 for stash in &stash_vec {
1003 arr = glib_sys::g_array_append_vals(arr, Ptr::to(stash.0), 1);
1004 }
1005 }
1006 (arr, (Some(Array(arr)), stash_vec))
1007 }
1008
1009 #[inline]
1010 fn to_glib_container_from_slice(t: &'a [T]) -> (*mut glib_sys::GArray, Self::Storage) {
1011 let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
1012 let mut arr: *mut glib_sys::GArray = ptr::null_mut();
1013 unsafe {
1014 for stash in &stash_vec {
1015 arr = glib_sys::g_array_append_vals(arr, Ptr::to(stash.0), 1);
1016 }
1017 }
1018 (arr, (None, stash_vec))
1019 }
1020
1021 #[inline]
1022 fn to_glib_full_from_slice(t: &[T]) -> *mut glib_sys::GArray {
1023 let mut arr: *mut glib_sys::GArray = ptr::null_mut();
1024 unsafe {
1025 for ptr in t.iter().map(ToGlibPtr::to_glib_full) {
1026 arr = glib_sys::g_array_append_vals(arr, Ptr::to(ptr), 1);
1027 }
1028 }
1029 arr
1030 }
1031}
1032
1033pub trait FromGlib<T>: Sized {
1035 fn from_glib(val: T) -> Self;
1036}
1037
1038#[inline]
1040pub fn from_glib<G, T: FromGlib<G>>(val: G) -> T {
1041 FromGlib::from_glib(val)
1042}
1043
1044impl FromGlib<glib_sys::gboolean> for bool {
1045 #[inline]
1046 fn from_glib(val: glib_sys::gboolean) -> bool {
1047 val != glib_sys::GFALSE
1048 }
1049}
1050
1051impl FromGlib<u32> for char {
1052 #[inline]
1053 fn from_glib(val: u32) -> char {
1054 char::from_u32(val).expect("Valid Unicode character expected")
1055 }
1056}
1057
1058impl FromGlib<i32> for Ordering {
1059 #[inline]
1060 fn from_glib(val: i32) -> Ordering {
1061 if val < 0 {
1062 Ordering::Less
1063 } else if val > 0 {
1064 Ordering::Greater
1065 } else {
1066 Ordering::Equal
1067 }
1068 }
1069}
1070
1071impl FromGlib<u32> for Option<char> {
1072 #[inline]
1073 fn from_glib(val: u32) -> Option<char> {
1074 match val {
1075 0 => None,
1076 _ => char::from_u32(val),
1077 }
1078 }
1079}
1080
1081impl FromGlib<i32> for Option<u32> {
1082 #[inline]
1083 fn from_glib(val: i32) -> Option<u32> {
1084 if val >= 0 {
1085 Some(val as u32)
1086 } else {
1087 None
1088 }
1089 }
1090}
1091
1092impl FromGlib<i64> for Option<u64> {
1093 #[inline]
1094 fn from_glib(val: i64) -> Option<u64> {
1095 if val >= 0 {
1096 Some(val as u64)
1097 } else {
1098 None
1099 }
1100 }
1101}
1102
1103impl FromGlib<i32> for Option<u64> {
1104 #[inline]
1105 fn from_glib(val: i32) -> Option<u64> {
1106 FromGlib::from_glib(i64::from(val))
1107 }
1108}
1109
1110pub trait FromGlibPtrNone<P: Ptr>: Sized {
1112 unsafe fn from_glib_none(ptr: P) -> Self;
1113}
1114
1115pub trait FromGlibPtrFull<P: Ptr>: Sized {
1117 unsafe fn from_glib_full(ptr: P) -> Self;
1118}
1119
1120pub trait FromGlibPtrBorrow<P: Ptr>: Sized {
1122 unsafe fn from_glib_borrow(_ptr: P) -> Self {
1123 unimplemented!();
1124 }
1125}
1126
1127#[inline]
1129pub unsafe fn from_glib_none<P: Ptr, T: FromGlibPtrNone<P>>(ptr: P) -> T {
1130 FromGlibPtrNone::from_glib_none(ptr)
1131}
1132
1133#[inline]
1135pub unsafe fn from_glib_full<P: Ptr, T: FromGlibPtrFull<P>>(ptr: P) -> T {
1136 FromGlibPtrFull::from_glib_full(ptr)
1137}
1138
1139#[inline]
1141pub unsafe fn from_glib_borrow<P: Ptr, T: FromGlibPtrBorrow<P>>(ptr: P) -> T {
1142 FromGlibPtrBorrow::from_glib_borrow(ptr)
1143}
1144
1145impl<P: Ptr, T: FromGlibPtrNone<P>> FromGlibPtrNone<P> for Option<T> {
1146 #[inline]
1147 unsafe fn from_glib_none(ptr: P) -> Option<T> {
1148 if ptr.is_null() {
1149 None
1150 } else {
1151 Some(from_glib_none(ptr))
1152 }
1153 }
1154}
1155
1156impl<P: Ptr, T: FromGlibPtrBorrow<P>> FromGlibPtrBorrow<P> for Option<T> {
1157 #[inline]
1158 unsafe fn from_glib_borrow(ptr: P) -> Option<T> {
1159 if ptr.is_null() {
1160 None
1161 } else {
1162 Some(from_glib_borrow(ptr))
1163 }
1164 }
1165}
1166
1167impl<P: Ptr, T: FromGlibPtrFull<P>> FromGlibPtrFull<P> for Option<T> {
1168 #[inline]
1169 unsafe fn from_glib_full(ptr: P) -> Option<T> {
1170 if ptr.is_null() {
1171 None
1172 } else {
1173 Some(from_glib_full(ptr))
1174 }
1175 }
1176}
1177
1178impl FromGlibPtrNone<*const c_char> for String {
1179 #[inline]
1180 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1181 assert!(!ptr.is_null());
1182 String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned()
1183 }
1184}
1185
1186impl FromGlibPtrFull<*const c_char> for String {
1188 #[inline]
1189 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1190 let res = from_glib_none(ptr);
1191 glib_sys::g_free(ptr as *mut _);
1192 res
1193 }
1194}
1195
1196impl FromGlibPtrNone<*mut c_char> for String {
1198 #[inline]
1199 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1200 assert!(!ptr.is_null());
1201 String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned()
1202 }
1203}
1204
1205impl FromGlibPtrFull<*mut c_char> for String {
1207 #[inline]
1208 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1209 let res = from_glib_none(ptr);
1210 glib_sys::g_free(ptr as *mut _);
1211 res
1212 }
1213}
1214
1215#[cfg(not(windows))]
1216unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
1217 assert!(!ptr.is_null());
1218
1219 OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec()).into()
1223}
1224
1225#[cfg(windows)]
1226unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
1227 assert!(!ptr.is_null());
1228
1229 String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
1234 .expect("Invalid, non-UTF8 path")
1235 .into()
1236}
1237
1238#[cfg(not(windows))]
1239unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
1240 assert!(!ptr.is_null());
1241
1242 OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec())
1246}
1247
1248#[cfg(windows)]
1249unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
1250 assert!(!ptr.is_null());
1251
1252 String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
1258 .expect("Invalid, non-UTF8 path")
1259 .into()
1260}
1261
1262impl FromGlibPtrNone<*const c_char> for PathBuf {
1263 #[inline]
1264 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1265 assert!(!ptr.is_null());
1266 c_to_path_buf(ptr)
1267 }
1268}
1269
1270impl FromGlibPtrFull<*const c_char> for PathBuf {
1271 #[inline]
1272 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1273 let res = from_glib_none(ptr);
1274 glib_sys::g_free(ptr as *mut _);
1275 res
1276 }
1277}
1278
1279impl FromGlibPtrNone<*mut c_char> for PathBuf {
1280 #[inline]
1281 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1282 assert!(!ptr.is_null());
1283 c_to_path_buf(ptr)
1284 }
1285}
1286
1287impl FromGlibPtrFull<*mut c_char> for PathBuf {
1288 #[inline]
1289 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1290 let res = from_glib_none(ptr);
1291 glib_sys::g_free(ptr as *mut _);
1292 res
1293 }
1294}
1295
1296impl FromGlibPtrNone<*const c_char> for OsString {
1297 #[inline]
1298 unsafe fn from_glib_none(ptr: *const c_char) -> Self {
1299 assert!(!ptr.is_null());
1300 c_to_os_string(ptr)
1301 }
1302}
1303
1304impl FromGlibPtrFull<*const c_char> for OsString {
1305 #[inline]
1306 unsafe fn from_glib_full(ptr: *const c_char) -> Self {
1307 let res = from_glib_none(ptr);
1308 glib_sys::g_free(ptr as *mut _);
1309 res
1310 }
1311}
1312
1313impl FromGlibPtrNone<*mut c_char> for OsString {
1314 #[inline]
1315 unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
1316 assert!(!ptr.is_null());
1317 c_to_os_string(ptr)
1318 }
1319}
1320
1321impl FromGlibPtrFull<*mut c_char> for OsString {
1322 #[inline]
1323 unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
1324 let res = from_glib_none(ptr);
1325 glib_sys::g_free(ptr as *mut _);
1326 res
1327 }
1328}
1329
1330pub trait FromGlibContainer<T, P: Ptr>: Sized {
1332 unsafe fn from_glib_none_num(ptr: P, num: usize) -> Self;
1336
1337 unsafe fn from_glib_container_num(ptr: P, num: usize) -> Self;
1341
1342 unsafe fn from_glib_full_num(ptr: P, num: usize) -> Self;
1346}
1347
1348pub trait FromGlibPtrContainer<P: Ptr, PP: Ptr>: FromGlibContainer<P, PP> + Sized {
1350 unsafe fn from_glib_none(ptr: PP) -> Self;
1352
1353 unsafe fn from_glib_container(ptr: PP) -> Self;
1355
1356 unsafe fn from_glib_full(ptr: PP) -> Self;
1358}
1359
1360pub unsafe fn c_ptr_array_len<P: Ptr>(mut ptr: *const P) -> usize {
1361 let mut len = 0;
1362
1363 if !ptr.is_null() {
1364 while !(*ptr).is_null() {
1365 len += 1;
1366 ptr = ptr.offset(1);
1367 }
1368 }
1369 len
1370}
1371
1372pub trait FromGlibContainerAsVec<T, P: Ptr>
1373where
1374 Self: Sized,
1375{
1376 unsafe fn from_glib_none_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
1377 unsafe fn from_glib_container_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
1378 unsafe fn from_glib_full_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
1379}
1380
1381pub trait FromGlibPtrArrayContainerAsVec<P: Ptr, PP: Ptr>: FromGlibContainerAsVec<P, PP>
1382where
1383 Self: Sized,
1384{
1385 unsafe fn from_glib_none_as_vec(ptr: PP) -> Vec<Self>;
1386 unsafe fn from_glib_container_as_vec(ptr: PP) -> Vec<Self>;
1387 unsafe fn from_glib_full_as_vec(ptr: PP) -> Vec<Self>;
1388}
1389
1390impl FromGlibContainerAsVec<bool, *const glib_sys::gboolean> for bool {
1391 unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::gboolean, num: usize) -> Vec<Self> {
1392 if num == 0 || ptr.is_null() {
1393 return Vec::new();
1394 }
1395
1396 let mut res = Vec::with_capacity(num);
1397 for i in 0..num {
1398 res.push(from_glib(ptr::read(ptr.add(i))));
1399 }
1400 res
1401 }
1402
1403 unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::gboolean, _: usize) -> Vec<Self> {
1404 unimplemented!();
1406 }
1407
1408 unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::gboolean, _: usize) -> Vec<Self> {
1409 unimplemented!();
1411 }
1412}
1413
1414impl FromGlibContainerAsVec<bool, *mut glib_sys::gboolean> for bool {
1415 unsafe fn from_glib_none_num_as_vec(ptr: *mut glib_sys::gboolean, num: usize) -> Vec<Self> {
1416 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
1417 }
1418
1419 unsafe fn from_glib_container_num_as_vec(
1420 ptr: *mut glib_sys::gboolean,
1421 num: usize,
1422 ) -> Vec<Self> {
1423 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
1424 glib_sys::g_free(ptr as *mut _);
1425 res
1426 }
1427
1428 unsafe fn from_glib_full_num_as_vec(ptr: *mut glib_sys::gboolean, num: usize) -> Vec<Self> {
1429 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
1430 }
1431}
1432
1433macro_rules! impl_from_glib_container_as_vec_fundamental {
1434 ($name:ty) => {
1435 impl FromGlibContainerAsVec<$name, *const $name> for $name {
1436 unsafe fn from_glib_none_num_as_vec(ptr: *const $name, num: usize) -> Vec<Self> {
1437 if num == 0 || ptr.is_null() {
1438 return Vec::new();
1439 }
1440
1441 let mut res = Vec::with_capacity(num);
1442 for i in 0..num {
1443 res.push(ptr::read(ptr.add(i)));
1444 }
1445 res
1446 }
1447
1448 unsafe fn from_glib_container_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
1449 unimplemented!();
1451 }
1452
1453 unsafe fn from_glib_full_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
1454 unimplemented!();
1456 }
1457 }
1458
1459 impl FromGlibContainerAsVec<$name, *mut $name> for $name {
1460 unsafe fn from_glib_none_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
1461 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
1462 }
1463
1464 unsafe fn from_glib_container_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
1465 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
1466 glib_sys::g_free(ptr as *mut _);
1467 res
1468 }
1469
1470 unsafe fn from_glib_full_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
1471 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
1472 }
1473 }
1474 };
1475}
1476
1477impl_from_glib_container_as_vec_fundamental!(u8);
1478impl_from_glib_container_as_vec_fundamental!(i8);
1479impl_from_glib_container_as_vec_fundamental!(u16);
1480impl_from_glib_container_as_vec_fundamental!(i16);
1481impl_from_glib_container_as_vec_fundamental!(u32);
1482impl_from_glib_container_as_vec_fundamental!(i32);
1483impl_from_glib_container_as_vec_fundamental!(u64);
1484impl_from_glib_container_as_vec_fundamental!(i64);
1485impl_from_glib_container_as_vec_fundamental!(f32);
1486impl_from_glib_container_as_vec_fundamental!(f64);
1487
1488macro_rules! impl_from_glib_container_as_vec_string {
1489 ($name:ty, $ffi_name:ty) => {
1490 impl FromGlibContainerAsVec<$ffi_name, *const $ffi_name> for $name {
1491 unsafe fn from_glib_none_num_as_vec(ptr: *const $ffi_name, num: usize) -> Vec<Self> {
1492 if num == 0 || ptr.is_null() {
1493 return Vec::new();
1494 }
1495
1496 let mut res = Vec::with_capacity(num);
1497 for i in 0..num {
1498 res.push(from_glib_none(ptr::read(ptr.add(i)) as $ffi_name));
1499 }
1500 res
1501 }
1502
1503 unsafe fn from_glib_container_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
1504 unimplemented!();
1506 }
1507
1508 unsafe fn from_glib_full_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
1509 unimplemented!();
1511 }
1512 }
1513
1514 impl FromGlibContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
1515 unsafe fn from_glib_none_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
1516 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
1517 }
1518
1519 unsafe fn from_glib_container_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
1520 let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
1521 glib_sys::g_free(ptr as *mut _);
1522 res
1523 }
1524
1525 unsafe fn from_glib_full_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
1526 if num == 0 || ptr.is_null() {
1527 return Vec::new();
1528 }
1529
1530 let mut res = Vec::with_capacity(num);
1531 for i in 0..num {
1532 res.push(from_glib_full(ptr::read(ptr.add(i))));
1533 }
1534 glib_sys::g_free(ptr as *mut _);
1535 res
1536 }
1537 }
1538
1539 impl FromGlibPtrArrayContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
1540 unsafe fn from_glib_none_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
1541 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
1542 }
1543
1544 unsafe fn from_glib_container_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
1545 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
1546 }
1547
1548 unsafe fn from_glib_full_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
1549 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
1550 }
1551 }
1552
1553 impl FromGlibPtrArrayContainerAsVec<$ffi_name, *const $ffi_name> for $name {
1554 unsafe fn from_glib_none_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
1555 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
1556 }
1557
1558 unsafe fn from_glib_container_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
1559 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
1560 }
1561
1562 unsafe fn from_glib_full_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
1563 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
1564 }
1565 }
1566 };
1567}
1568
1569impl_from_glib_container_as_vec_string!(String, *const c_char);
1571impl_from_glib_container_as_vec_string!(String, *mut c_char);
1572
1573impl_from_glib_container_as_vec_string!(PathBuf, *const c_char);
1574impl_from_glib_container_as_vec_string!(PathBuf, *mut c_char);
1575impl_from_glib_container_as_vec_string!(OsString, *const c_char);
1576impl_from_glib_container_as_vec_string!(OsString, *mut c_char);
1577
1578impl<P, PP: Ptr, T: FromGlibContainerAsVec<P, PP>> FromGlibContainer<P, PP> for Vec<T> {
1579 unsafe fn from_glib_none_num(ptr: PP, num: usize) -> Vec<T> {
1580 FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num)
1581 }
1582
1583 unsafe fn from_glib_container_num(ptr: PP, num: usize) -> Vec<T> {
1584 FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
1585 }
1586
1587 unsafe fn from_glib_full_num(ptr: PP, num: usize) -> Vec<T> {
1588 FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, num)
1589 }
1590}
1591
1592impl<P: Ptr, PP: Ptr, T: FromGlibPtrArrayContainerAsVec<P, PP>> FromGlibPtrContainer<P, PP>
1593 for Vec<T>
1594{
1595 unsafe fn from_glib_none(ptr: PP) -> Vec<T> {
1596 FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr)
1597 }
1598
1599 unsafe fn from_glib_container(ptr: PP) -> Vec<T> {
1600 FromGlibPtrArrayContainerAsVec::from_glib_container_as_vec(ptr)
1601 }
1602
1603 unsafe fn from_glib_full(ptr: PP) -> Vec<T> {
1604 FromGlibPtrArrayContainerAsVec::from_glib_full_as_vec(ptr)
1605 }
1606}
1607
1608impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GSList> for T
1609where
1610 T: GlibPtrDefault
1611 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1612 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1613{
1614 unsafe fn from_glib_none_num_as_vec(mut ptr: *mut glib_sys::GSList, num: usize) -> Vec<T> {
1615 if num == 0 || ptr.is_null() {
1616 return Vec::new();
1617 }
1618 let mut res = Vec::with_capacity(num);
1619 for _ in 0..num {
1620 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
1621 if !item_ptr.is_null() {
1622 res.push(from_glib_none(item_ptr));
1623 }
1624 ptr = (*ptr).next;
1625 }
1626 res
1627 }
1628
1629 unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GSList, num: usize) -> Vec<T> {
1630 let res = FromGlibContainer::from_glib_none_num(ptr, num);
1631 if !ptr.is_null() {
1632 glib_sys::g_slist_free(ptr as *mut _);
1633 }
1634 res
1635 }
1636
1637 unsafe fn from_glib_full_num_as_vec(mut ptr: *mut glib_sys::GSList, num: usize) -> Vec<T> {
1638 if num == 0 || ptr.is_null() {
1639 return Vec::new();
1640 }
1641 let orig_ptr = ptr;
1642 let mut res = Vec::with_capacity(num);
1643 for _ in 0..num {
1644 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
1645 if !item_ptr.is_null() {
1646 res.push(from_glib_full(item_ptr));
1647 }
1648 ptr = (*ptr).next;
1649 }
1650 glib_sys::g_slist_free(orig_ptr as *mut _);
1651 res
1652 }
1653}
1654
1655impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GSList> for T
1656where
1657 T: GlibPtrDefault
1658 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1659 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1660{
1661 unsafe fn from_glib_none_as_vec(ptr: *mut glib_sys::GSList) -> Vec<T> {
1662 let num = glib_sys::g_slist_length(ptr) as usize;
1663 FromGlibContainer::from_glib_none_num(ptr, num)
1664 }
1665
1666 unsafe fn from_glib_container_as_vec(ptr: *mut glib_sys::GSList) -> Vec<T> {
1667 let num = glib_sys::g_slist_length(ptr) as usize;
1668 FromGlibContainer::from_glib_container_num(ptr, num)
1669 }
1670
1671 unsafe fn from_glib_full_as_vec(ptr: *mut glib_sys::GSList) -> Vec<T> {
1672 let num = glib_sys::g_slist_length(ptr) as usize;
1673 FromGlibContainer::from_glib_full_num(ptr, num)
1674 }
1675}
1676
1677impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GList> for T
1678where
1679 T: GlibPtrDefault
1680 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1681 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1682{
1683 unsafe fn from_glib_none_num_as_vec(mut ptr: *mut glib_sys::GList, num: usize) -> Vec<T> {
1684 if num == 0 || ptr.is_null() {
1685 return Vec::new();
1686 }
1687 let mut res = Vec::with_capacity(num);
1688 for _ in 0..num {
1689 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
1690 if !item_ptr.is_null() {
1691 res.push(from_glib_none(item_ptr));
1692 }
1693 ptr = (*ptr).next;
1694 }
1695 res
1696 }
1697
1698 unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GList, num: usize) -> Vec<T> {
1699 let res = FromGlibContainer::from_glib_none_num(ptr, num);
1700 if !ptr.is_null() {
1701 glib_sys::g_list_free(ptr as *mut _);
1702 }
1703 res
1704 }
1705
1706 unsafe fn from_glib_full_num_as_vec(mut ptr: *mut glib_sys::GList, num: usize) -> Vec<T> {
1707 if num == 0 || ptr.is_null() {
1708 return Vec::new();
1709 }
1710 let orig_ptr = ptr;
1711 let mut res = Vec::with_capacity(num);
1712 for _ in 0..num {
1713 let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
1714 if !item_ptr.is_null() {
1715 res.push(from_glib_full(item_ptr));
1716 }
1717 ptr = (*ptr).next;
1718 }
1719 glib_sys::g_list_free(orig_ptr as *mut _);
1720 res
1721 }
1722}
1723
1724impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GList> for T
1725where
1726 T: GlibPtrDefault
1727 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1728 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1729{
1730 unsafe fn from_glib_none_as_vec(ptr: *mut glib_sys::GList) -> Vec<T> {
1731 let num = glib_sys::g_list_length(ptr) as usize;
1732 FromGlibContainer::from_glib_none_num(ptr, num)
1733 }
1734
1735 unsafe fn from_glib_container_as_vec(ptr: *mut glib_sys::GList) -> Vec<T> {
1736 let num = glib_sys::g_list_length(ptr) as usize;
1737 FromGlibContainer::from_glib_container_num(ptr, num)
1738 }
1739
1740 unsafe fn from_glib_full_as_vec(ptr: *mut glib_sys::GList) -> Vec<T> {
1741 let num = glib_sys::g_list_length(ptr) as usize;
1742 FromGlibContainer::from_glib_full_num(ptr, num)
1743 }
1744}
1745
1746impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GList> for T
1747where
1748 T: GlibPtrDefault
1749 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1750 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1751{
1752 unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GList, num: usize) -> Vec<T> {
1753 FromGlibContainer::from_glib_none_num(mut_override(ptr), num)
1754 }
1755
1756 unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GList, _: usize) -> Vec<T> {
1757 unimplemented!()
1759 }
1760
1761 unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GList, _: usize) -> Vec<T> {
1762 unimplemented!()
1764 }
1765}
1766
1767impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GList>
1768 for T
1769where
1770 T: GlibPtrDefault
1771 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1772 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1773{
1774 unsafe fn from_glib_none_as_vec(ptr: *const glib_sys::GList) -> Vec<T> {
1775 FromGlibPtrContainer::from_glib_none(mut_override(ptr))
1776 }
1777
1778 unsafe fn from_glib_container_as_vec(_: *const glib_sys::GList) -> Vec<T> {
1779 unimplemented!()
1781 }
1782
1783 unsafe fn from_glib_full_as_vec(_: *const glib_sys::GList) -> Vec<T> {
1784 unimplemented!()
1786 }
1787}
1788
1789impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GSList> for T
1790where
1791 T: GlibPtrDefault
1792 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1793 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1794{
1795 unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GSList, num: usize) -> Vec<T> {
1796 FromGlibContainer::from_glib_none_num(mut_override(ptr), num)
1797 }
1798
1799 unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GSList, _: usize) -> Vec<T> {
1800 unimplemented!()
1802 }
1803
1804 unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GSList, _: usize) -> Vec<T> {
1805 unimplemented!()
1807 }
1808}
1809
1810impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GSList>
1811 for T
1812where
1813 T: GlibPtrDefault
1814 + FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
1815 + FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
1816{
1817 unsafe fn from_glib_none_as_vec(ptr: *const glib_sys::GSList) -> Vec<T> {
1818 FromGlibPtrContainer::from_glib_none(mut_override(ptr))
1819 }
1820
1821 unsafe fn from_glib_container_as_vec(_: *const glib_sys::GSList) -> Vec<T> {
1822 unimplemented!()
1824 }
1825
1826 unsafe fn from_glib_full_as_vec(_: *const glib_sys::GSList) -> Vec<T> {
1827 unimplemented!()
1829 }
1830}
1831
1832#[allow(clippy::implicit_hasher)]
1833impl FromGlibContainer<*const c_char, *mut glib_sys::GHashTable> for HashMap<String, String> {
1834 unsafe fn from_glib_none_num(ptr: *mut glib_sys::GHashTable, _: usize) -> Self {
1835 FromGlibPtrContainer::from_glib_none(ptr)
1836 }
1837
1838 unsafe fn from_glib_container_num(ptr: *mut glib_sys::GHashTable, _: usize) -> Self {
1839 FromGlibPtrContainer::from_glib_full(ptr)
1840 }
1841
1842 unsafe fn from_glib_full_num(ptr: *mut glib_sys::GHashTable, _: usize) -> Self {
1843 FromGlibPtrContainer::from_glib_full(ptr)
1844 }
1845}
1846
1847#[allow(clippy::implicit_hasher)]
1848impl FromGlibPtrContainer<*const c_char, *mut glib_sys::GHashTable> for HashMap<String, String> {
1849 unsafe fn from_glib_none(ptr: *mut glib_sys::GHashTable) -> Self {
1850 unsafe extern "C" fn read_string_hash_table(
1851 key: glib_sys::gpointer,
1852 value: glib_sys::gpointer,
1853 hash_map: glib_sys::gpointer,
1854 ) {
1855 let key: String = from_glib_none(key as *const c_char);
1856 let value: String = from_glib_none(value as *const c_char);
1857 let hash_map: &mut HashMap<String, String> =
1858 &mut *(hash_map as *mut HashMap<String, String>);
1859 hash_map.insert(key, value);
1860 }
1861 let mut map = HashMap::new();
1862 glib_sys::g_hash_table_foreach(
1863 ptr,
1864 Some(read_string_hash_table),
1865 &mut map as *mut HashMap<String, String> as *mut _,
1866 );
1867 map
1868 }
1869
1870 unsafe fn from_glib_container(ptr: *mut glib_sys::GHashTable) -> Self {
1871 FromGlibPtrContainer::from_glib_full(ptr)
1872 }
1873
1874 unsafe fn from_glib_full(ptr: *mut glib_sys::GHashTable) -> Self {
1875 let map = FromGlibPtrContainer::from_glib_none(ptr);
1876 glib_sys::g_hash_table_unref(ptr);
1877 map
1878 }
1879}
1880
1881#[cfg(test)]
1882mod tests {
1883 extern crate tempfile;
1884 use self::tempfile::tempdir;
1885 use std::fs;
1886
1887 use super::*;
1888 use glib_sys;
1889 use gstring::GString;
1890 use std::collections::HashMap;
1891
1892 #[test]
1893 fn string_hash_map() {
1894 let mut map = HashMap::new();
1895 map.insert("A".into(), "1".into());
1896 map.insert("B".into(), "2".into());
1897 map.insert("C".into(), "3".into());
1898 let ptr: *mut glib_sys::GHashTable = map.to_glib_full();
1899 let map = unsafe { HashMap::from_glib_full(ptr) };
1900 assert_eq!(map.get("A"), Some(&"1".into()));
1901 assert_eq!(map.get("B"), Some(&"2".into()));
1902 assert_eq!(map.get("C"), Some(&"3".into()));
1903 }
1904
1905 #[test]
1906 fn string_array() {
1907 let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
1908 let stash = v.to_glib_none();
1909 let ptr: *mut *mut c_char = stash.0;
1910 let ptr_copy = unsafe { glib_sys::g_strdupv(ptr) };
1911
1912 let actual: Vec<String> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
1913 assert_eq!(v, actual);
1914 }
1915
1916 #[test]
1917 fn gstring_array() {
1918 let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
1919 let stash = v.to_glib_none();
1920 let ptr: *mut *mut c_char = stash.0;
1921 let ptr_copy = unsafe { glib_sys::g_strdupv(ptr) };
1922
1923 let actual: Vec<GString> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
1924 assert_eq!(v, actual);
1925 }
1926
1927 #[test]
1928 #[cfg(not(target_os = "macos"))]
1929 fn test_paths() {
1930 let tmp_dir = tempdir().unwrap();
1931
1932 let dir_1 = tmp_dir.path().join("abcd");
1935 fs::create_dir(&dir_1).unwrap();
1936 assert_eq!(::functions::path_get_basename(&dir_1), Some("abcd".into()));
1937 assert_eq!(
1938 ::functions::path_get_basename(dir_1.canonicalize().unwrap()),
1939 Some("abcd".into())
1940 );
1941 assert_eq!(
1942 ::functions::path_get_dirname(dir_1.canonicalize().unwrap()),
1943 Some(tmp_dir.path().into())
1944 );
1945 assert!(::functions::file_test(
1946 &dir_1,
1947 ::FileTest::EXISTS | ::FileTest::IS_DIR
1948 ));
1949 assert!(::functions::file_test(
1950 &dir_1.canonicalize().unwrap(),
1951 ::FileTest::EXISTS | ::FileTest::IS_DIR
1952 ));
1953
1954 let dir_2 = tmp_dir.as_ref().join("øäöü");
1956 fs::create_dir(&dir_2).unwrap();
1957 assert_eq!(
1958 ::functions::path_get_basename(&dir_2),
1959 Some("øäöü".into())
1960 );
1961 assert_eq!(
1962 ::functions::path_get_basename(dir_2.canonicalize().unwrap()),
1963 Some("øäöü".into())
1964 );
1965 assert_eq!(
1966 ::functions::path_get_dirname(dir_2.canonicalize().unwrap()),
1967 Some(tmp_dir.path().into())
1968 );
1969 assert!(::functions::file_test(
1970 &dir_2,
1971 ::FileTest::EXISTS | ::FileTest::IS_DIR
1972 ));
1973 assert!(::functions::file_test(
1974 &dir_2.canonicalize().unwrap(),
1975 ::FileTest::EXISTS | ::FileTest::IS_DIR
1976 ));
1977 }
1978
1979 #[test]
1980 #[cfg(target_os = "macos")]
1981 fn test_paths() {
1982 let t_dir = tempdir().unwrap();
1983 let tmp_dir = t_dir.path().canonicalize().unwrap();
1984
1985 let dir_1 = tmp_dir.join("abcd");
1988 fs::create_dir(&dir_1).unwrap();
1989 assert_eq!(::functions::path_get_basename(&dir_1), Some("abcd".into()));
1990 assert_eq!(
1991 ::functions::path_get_basename(dir_1.canonicalize().unwrap()),
1992 Some("abcd".into())
1993 );
1994 assert_eq!(
1995 ::functions::path_get_dirname(dir_1.canonicalize().unwrap()),
1996 Some(tmp_dir)
1997 );
1998 assert!(::functions::file_test(
1999 &dir_1,
2000 ::FileTest::EXISTS | ::FileTest::IS_DIR
2001 ));
2002 assert!(::functions::file_test(
2003 &dir_1.canonicalize().unwrap(),
2004 ::FileTest::EXISTS | ::FileTest::IS_DIR
2005 ));
2006 }
2007}