use glib_sys;
use libc::{c_char, size_t};
use std::char;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::ffi::{OsStr, OsString};
use std::mem;
#[cfg(not(windows))]
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::ptr;
pub trait Ptr: Copy + 'static {
fn is_null(&self) -> bool;
fn from<X>(ptr: *mut X) -> Self;
fn to<X>(self) -> *mut X;
}
impl<T: 'static> Ptr for *const T {
#[inline]
fn is_null(&self) -> bool {
(*self).is_null()
}
#[inline]
fn from<X>(ptr: *mut X) -> *const T {
ptr as *const T
}
#[inline]
fn to<X>(self) -> *mut X {
self as *mut X
}
}
impl<T: 'static> Ptr for *mut T {
#[inline]
fn is_null(&self) -> bool {
(*self).is_null()
}
#[inline]
fn from<X>(ptr: *mut X) -> *mut T {
ptr as *mut T
}
#[inline]
fn to<X>(self) -> *mut X {
self as *mut X
}
}
pub fn mut_override<T>(ptr: *const T) -> *mut T {
ptr as *mut T
}
pub fn const_override<T>(ptr: *mut T) -> *const T {
ptr as *const T
}
pub trait Uninitialized {
unsafe fn uninitialized() -> Self;
}
#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn uninitialized<T: Uninitialized>() -> T {
T::uninitialized()
}
pub trait ToBool: Copy {
fn to_bool(self) -> bool;
}
impl ToBool for bool {
#[inline]
fn to_bool(self) -> bool {
self
}
}
impl ToBool for glib_sys::gboolean {
#[inline]
fn to_bool(self) -> bool {
self != glib_sys::GFALSE
}
}
#[inline]
pub fn some_if<B: ToBool, T, F: FnOnce() -> T>(cond: B, f: F) -> Option<T> {
if cond.to_bool() {
Some(f())
} else {
None
}
}
pub struct Stash<'a, P: Copy, T: ?Sized + ToGlibPtr<'a, P>>(
pub P,
pub <T as ToGlibPtr<'a, P>>::Storage,
);
pub struct StashMut<'a, P: Copy, T: ?Sized>(pub P, pub <T as ToGlibPtrMut<'a, P>>::Storage)
where
T: ToGlibPtrMut<'a, P>;
pub trait ToGlib {
type GlibType;
fn to_glib(&self) -> Self::GlibType;
}
impl ToGlib for bool {
type GlibType = glib_sys::gboolean;
#[inline]
fn to_glib(&self) -> glib_sys::gboolean {
if *self {
glib_sys::GTRUE
} else {
glib_sys::GFALSE
}
}
}
impl ToGlib for char {
type GlibType = u32;
#[inline]
fn to_glib(&self) -> u32 {
*self as u32
}
}
impl ToGlib for Option<char> {
type GlibType = u32;
#[inline]
fn to_glib(&self) -> u32 {
self.as_ref().map(|&c| c as u32).unwrap_or(0)
}
}
impl ToGlib for Ordering {
type GlibType = i32;
#[inline]
fn to_glib(&self) -> i32 {
match *self {
Ordering::Less => -1,
Ordering::Equal => 0,
Ordering::Greater => 1,
}
}
}
pub trait GlibPtrDefault {
type GlibType: Ptr;
}
impl<'a, T: ?Sized + GlibPtrDefault> GlibPtrDefault for &'a T {
type GlibType = <T as GlibPtrDefault>::GlibType;
}
pub trait ToGlibPtr<'a, P: Copy> {
type Storage;
fn to_glib_none(&'a self) -> Stash<'a, P, Self>;
fn to_glib_container(&'a self) -> Stash<'a, P, Self> {
unimplemented!();
}
fn to_glib_full(&self) -> P {
unimplemented!();
}
}
pub trait ToGlibPtrMut<'a, P: Copy> {
type Storage;
fn to_glib_none_mut(&'a mut self) -> StashMut<P, Self>;
}
impl<'a, P: Ptr, T: ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for Option<T> {
type Storage = Option<<T as ToGlibPtr<'a, P>>::Storage>;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, P, Option<T>> {
self.as_ref()
.map_or(Stash(Ptr::from::<()>(ptr::null_mut()), None), |s| {
let s = s.to_glib_none();
Stash(s.0, Some(s.1))
})
}
#[inline]
fn to_glib_full(&self) -> P {
self.as_ref()
.map_or(Ptr::from::<()>(ptr::null_mut()), ToGlibPtr::to_glib_full)
}
}
impl<'a, 'opt: 'a, P: Ptr, T: ToGlibPtrMut<'a, P>> ToGlibPtrMut<'a, P> for Option<&'opt mut T> {
type Storage = Option<<T as ToGlibPtrMut<'a, P>>::Storage>;
#[inline]
fn to_glib_none_mut(&'a mut self) -> StashMut<'a, P, Option<&'opt mut T>> {
self.as_mut()
.map_or(StashMut(Ptr::from::<()>(ptr::null_mut()), None), |s| {
let s = s.to_glib_none_mut();
StashMut(s.0, Some(s.1))
})
}
}
impl<'a, P: Ptr, T: ?Sized + ToGlibPtr<'a, P>> ToGlibPtr<'a, P> for &'a T {
type Storage = <T as ToGlibPtr<'a, P>>::Storage;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
let s = (*self).to_glib_none();
Stash(s.0, s.1)
}
#[inline]
fn to_glib_full(&self) -> P {
(*self).to_glib_full()
}
}
impl<'a> ToGlibPtr<'a, *const c_char> for str {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
let tmp =
CString::new(self).expect("str::ToGlibPtr<*const c_char>: unexpected '\0' character");
Stash(tmp.as_ptr(), tmp)
}
#[inline]
fn to_glib_full(&self) -> *const c_char {
unsafe {
glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t)
as *const c_char
}
}
}
impl<'a> ToGlibPtr<'a, *mut c_char> for str {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
let tmp =
CString::new(self).expect("str::ToGlibPtr<*mut c_char>: unexpected '\0' character");
Stash(tmp.as_ptr() as *mut c_char, tmp)
}
#[inline]
fn to_glib_full(&self) -> *mut c_char {
unsafe { glib_sys::g_strndup(self.as_ptr() as *mut c_char, self.len() as size_t) }
}
}
impl<'a> ToGlibPtr<'a, *const c_char> for String {
type Storage = CString;
#[inline]
fn to_glib_none(&self) -> Stash<'a, *const c_char, String> {
let tmp = CString::new(&self[..])
.expect("String::ToGlibPtr<*const c_char>: unexpected '\0' character");
Stash(tmp.as_ptr(), tmp)
}
#[inline]
fn to_glib_full(&self) -> *const c_char {
unsafe {
glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t)
as *const c_char
}
}
}
impl<'a> ToGlibPtr<'a, *mut c_char> for String {
type Storage = CString;
#[inline]
fn to_glib_none(&self) -> Stash<'a, *mut c_char, String> {
let tmp = CString::new(&self[..])
.expect("String::ToGlibPtr<*mut c_char>: unexpected '\0' character");
Stash(tmp.as_ptr() as *mut c_char, tmp)
}
#[inline]
fn to_glib_full(&self) -> *mut c_char {
unsafe {
glib_sys::g_strndup(self.as_ptr() as *const c_char, self.len() as size_t) as *mut c_char
}
}
}
impl GlibPtrDefault for str {
type GlibType = *mut c_char;
}
impl GlibPtrDefault for String {
type GlibType = *mut c_char;
}
#[cfg(not(windows))]
fn path_to_c(path: &Path) -> CString {
CString::new(path.as_os_str().as_bytes()).expect("Invalid path with NUL bytes")
}
#[cfg(windows)]
fn path_to_c(path: &Path) -> CString {
let path_str = path
.to_str()
.expect("Path can't be represented as UTF-8")
.to_owned();
if path_str.starts_with("\\\\?\\") {
CString::new(path_str[4..].as_bytes())
} else {
CString::new(path_str.as_bytes())
}
.expect("Invalid path with NUL bytes")
}
#[cfg(not(windows))]
fn os_str_to_c(s: &OsStr) -> CString {
CString::new(s.as_bytes()).expect("Invalid OS String with NUL bytes")
}
#[cfg(windows)]
fn os_str_to_c(s: &OsStr) -> CString {
let os_str = s
.to_str()
.expect("OS String can't be represented as UTF-8")
.to_owned();
CString::new(os_str.as_bytes()).expect("Invalid OS string with NUL bytes")
}
impl<'a> ToGlibPtr<'a, *const c_char> for Path {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
let tmp = path_to_c(self);
Stash(tmp.as_ptr(), tmp)
}
}
impl<'a> ToGlibPtr<'a, *mut c_char> for Path {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
let tmp = path_to_c(self);
Stash(tmp.as_ptr() as *mut c_char, tmp)
}
}
impl<'a> ToGlibPtr<'a, *const c_char> for PathBuf {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
let tmp = path_to_c(self);
Stash(tmp.as_ptr(), tmp)
}
}
impl<'a> ToGlibPtr<'a, *mut c_char> for PathBuf {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
let tmp = path_to_c(self);
Stash(tmp.as_ptr() as *mut c_char, tmp)
}
}
impl GlibPtrDefault for Path {
type GlibType = *mut c_char;
}
impl GlibPtrDefault for PathBuf {
type GlibType = *mut c_char;
}
impl<'a> ToGlibPtr<'a, *const c_char> for OsStr {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
let tmp = os_str_to_c(self);
Stash(tmp.as_ptr(), tmp)
}
}
impl<'a> ToGlibPtr<'a, *mut c_char> for OsStr {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
let tmp = os_str_to_c(self);
Stash(tmp.as_ptr() as *mut c_char, tmp)
}
}
impl<'a> ToGlibPtr<'a, *const c_char> for OsString {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *const c_char, Self> {
let tmp = os_str_to_c(self);
Stash(tmp.as_ptr(), tmp)
}
}
impl<'a> ToGlibPtr<'a, *mut c_char> for OsString {
type Storage = CString;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, *mut c_char, Self> {
let tmp = os_str_to_c(self);
Stash(tmp.as_ptr() as *mut c_char, tmp)
}
}
impl GlibPtrDefault for OsStr {
type GlibType = *mut c_char;
}
impl GlibPtrDefault for OsString {
type GlibType = *mut c_char;
}
pub trait ToGlibContainerFromSlice<'a, P>
where
Self: Sized,
{
type Storage;
fn to_glib_none_from_slice(t: &'a [Self]) -> (P, Self::Storage);
fn to_glib_container_from_slice(t: &'a [Self]) -> (P, Self::Storage);
fn to_glib_full_from_slice(t: &[Self]) -> P;
}
macro_rules! impl_to_glib_container_from_slice_fundamental {
($name:ty) => {
impl<'a> ToGlibContainerFromSlice<'a, *mut $name> for $name {
type Storage = &'a [$name];
fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut $name, &'a [$name]) {
(t.as_ptr() as *mut $name, t)
}
fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut $name, &'a [$name]) {
(ToGlibContainerFromSlice::to_glib_full_from_slice(t), t)
}
fn to_glib_full_from_slice(t: &[$name]) -> *mut $name {
if t.len() == 0 {
return ptr::null_mut();
}
unsafe {
let res = glib_sys::g_malloc(mem::size_of::<$name>() * t.len()) as *mut $name;
ptr::copy_nonoverlapping(t.as_ptr(), res, t.len());
res
}
}
}
};
}
impl_to_glib_container_from_slice_fundamental!(u8);
impl_to_glib_container_from_slice_fundamental!(i8);
impl_to_glib_container_from_slice_fundamental!(u16);
impl_to_glib_container_from_slice_fundamental!(i16);
impl_to_glib_container_from_slice_fundamental!(u32);
impl_to_glib_container_from_slice_fundamental!(i32);
impl_to_glib_container_from_slice_fundamental!(u64);
impl_to_glib_container_from_slice_fundamental!(i64);
impl_to_glib_container_from_slice_fundamental!(f32);
impl_to_glib_container_from_slice_fundamental!(f64);
macro_rules! impl_to_glib_container_from_slice_string {
($name:ty, $ffi_name:ty) => {
impl<'a> ToGlibContainerFromSlice<'a, *mut $ffi_name> for $name {
type Storage = (Vec<Stash<'a, $ffi_name, $name>>, Option<Vec<$ffi_name>>);
fn to_glib_none_from_slice(t: &'a [$name]) -> (*mut $ffi_name, Self::Storage) {
let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
v_ptr.push(ptr::null_mut() as $ffi_name);
(v_ptr.as_ptr() as *mut $ffi_name, (v, Some(v_ptr)))
}
fn to_glib_container_from_slice(t: &'a [$name]) -> (*mut $ffi_name, Self::Storage) {
let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let v_ptr = unsafe {
let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
as *mut $ffi_name;
for (i, s) in v.iter().enumerate() {
ptr::write(v_ptr.add(i), s.0);
}
v_ptr
};
(v_ptr, (v, None))
}
fn to_glib_full_from_slice(t: &[$name]) -> *mut $ffi_name {
unsafe {
let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
as *mut $ffi_name;
for (i, s) in t.iter().enumerate() {
ptr::write(v_ptr.add(i), s.to_glib_full());
}
v_ptr
}
}
}
impl<'a> ToGlibContainerFromSlice<'a, *const $ffi_name> for $name {
type Storage = (Vec<Stash<'a, $ffi_name, $name>>, Option<Vec<$ffi_name>>);
fn to_glib_none_from_slice(t: &'a [$name]) -> (*const $ffi_name, Self::Storage) {
let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let mut v_ptr: Vec<_> = v.iter().map(|s| s.0).collect();
v_ptr.push(ptr::null_mut() as $ffi_name);
(v_ptr.as_ptr() as *const $ffi_name, (v, Some(v_ptr)))
}
fn to_glib_container_from_slice(t: &'a [$name]) -> (*const $ffi_name, Self::Storage) {
let v: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let v_ptr = unsafe {
let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
as *mut $ffi_name;
for (i, s) in v.iter().enumerate() {
ptr::write(v_ptr.add(i), s.0);
}
v_ptr as *const $ffi_name
};
(v_ptr, (v, None))
}
fn to_glib_full_from_slice(t: &[$name]) -> *const $ffi_name {
unsafe {
let v_ptr = glib_sys::g_malloc0(mem::size_of::<$ffi_name>() * (t.len() + 1))
as *mut $ffi_name;
for (i, s) in t.iter().enumerate() {
ptr::write(v_ptr.add(i), s.to_glib_full());
}
v_ptr as *const $ffi_name
}
}
}
};
}
impl_to_glib_container_from_slice_string!(&'a str, *mut c_char);
impl_to_glib_container_from_slice_string!(&'a str, *const c_char);
impl_to_glib_container_from_slice_string!(String, *mut c_char);
impl_to_glib_container_from_slice_string!(String, *const c_char);
impl_to_glib_container_from_slice_string!(&'a Path, *mut c_char);
impl_to_glib_container_from_slice_string!(&'a Path, *const c_char);
impl_to_glib_container_from_slice_string!(PathBuf, *mut c_char);
impl_to_glib_container_from_slice_string!(PathBuf, *const c_char);
impl_to_glib_container_from_slice_string!(&'a OsStr, *mut c_char);
impl_to_glib_container_from_slice_string!(&'a OsStr, *const c_char);
impl_to_glib_container_from_slice_string!(OsString, *mut c_char);
impl_to_glib_container_from_slice_string!(OsString, *const c_char);
impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GList> for T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<List>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [T]) -> (*mut glib_sys::GList, Self::Storage) {
let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
let mut list: *mut glib_sys::GList = ptr::null_mut();
unsafe {
for stash in &stash_vec {
list = glib_sys::g_list_prepend(list, Ptr::to(stash.0));
}
}
(list, (Some(List(list)), stash_vec))
}
#[inline]
fn to_glib_container_from_slice(t: &'a [T]) -> (*mut glib_sys::GList, Self::Storage) {
let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
let mut list: *mut glib_sys::GList = ptr::null_mut();
unsafe {
for stash in &stash_vec {
list = glib_sys::g_list_prepend(list, Ptr::to(stash.0));
}
}
(list, (None, stash_vec))
}
#[inline]
fn to_glib_full_from_slice(t: &[T]) -> *mut glib_sys::GList {
let mut list: *mut glib_sys::GList = ptr::null_mut();
unsafe {
for ptr in t.iter().rev().map(ToGlibPtr::to_glib_full) {
list = glib_sys::g_list_prepend(list, Ptr::to(ptr));
}
}
list
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GList> for T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<List>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [T]) -> (*const glib_sys::GList, Self::Storage) {
let (list, stash) =
ToGlibContainerFromSlice::<*mut glib_sys::GList>::to_glib_none_from_slice(t);
(list as *const glib_sys::GList, stash)
}
#[inline]
fn to_glib_container_from_slice(_t: &'a [T]) -> (*const glib_sys::GList, Self::Storage) {
unimplemented!()
}
#[inline]
fn to_glib_full_from_slice(_t: &[T]) -> *const glib_sys::GList {
unimplemented!()
}
}
pub struct List(*mut glib_sys::GList);
impl Drop for List {
fn drop(&mut self) {
unsafe { glib_sys::g_list_free(self.0) }
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GSList> for &'a T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<SList>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*mut glib_sys::GSList, Self::Storage) {
let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
let mut list: *mut glib_sys::GSList = ptr::null_mut();
unsafe {
for stash in &stash_vec {
list = glib_sys::g_slist_prepend(list, Ptr::to(stash.0));
}
}
(list, (Some(SList(list)), stash_vec))
}
#[inline]
fn to_glib_container_from_slice(t: &'a [&'a T]) -> (*mut glib_sys::GSList, Self::Storage) {
let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
let mut list: *mut glib_sys::GSList = ptr::null_mut();
unsafe {
for stash in &stash_vec {
list = glib_sys::g_slist_prepend(list, Ptr::to(stash.0));
}
}
(list, (None, stash_vec))
}
#[inline]
fn to_glib_full_from_slice(t: &[&'a T]) -> *mut glib_sys::GSList {
let mut list: *mut glib_sys::GSList = ptr::null_mut();
unsafe {
for ptr in t.iter().rev().map(ToGlibPtr::to_glib_full) {
list = glib_sys::g_slist_prepend(list, Ptr::to(ptr));
}
}
list
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GSList> for &'a T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<SList>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*const glib_sys::GSList, Self::Storage) {
let (list, stash) =
ToGlibContainerFromSlice::<*mut glib_sys::GSList>::to_glib_none_from_slice(t);
(list as *const glib_sys::GSList, stash)
}
#[inline]
fn to_glib_container_from_slice(_t: &'a [&'a T]) -> (*const glib_sys::GSList, Self::Storage) {
unimplemented!()
}
#[inline]
fn to_glib_full_from_slice(_t: &[&'a T]) -> *const glib_sys::GSList {
unimplemented!()
}
}
pub struct SList(*mut glib_sys::GSList);
impl Drop for SList {
fn drop(&mut self) {
unsafe { glib_sys::g_slist_free(self.0) }
}
}
impl<'a, P: Ptr, T: ToGlibContainerFromSlice<'a, P>> ToGlibPtr<'a, P> for [T] {
type Storage = T::Storage;
#[inline]
fn to_glib_none(&'a self) -> Stash<'a, P, Self> {
let result = ToGlibContainerFromSlice::to_glib_none_from_slice(self);
Stash(result.0, result.1)
}
#[inline]
fn to_glib_container(&'a self) -> Stash<'a, P, Self> {
let result = ToGlibContainerFromSlice::to_glib_container_from_slice(self);
Stash(result.0, result.1)
}
#[inline]
fn to_glib_full(&self) -> P {
ToGlibContainerFromSlice::to_glib_full_from_slice(self)
}
}
#[allow(clippy::implicit_hasher)]
impl<'a> ToGlibPtr<'a, *mut glib_sys::GHashTable> for HashMap<String, String> {
type Storage = HashTable;
#[inline]
fn to_glib_none(&self) -> Stash<'a, *mut glib_sys::GHashTable, Self> {
let ptr = self.to_glib_full();
Stash(ptr, HashTable(ptr))
}
#[inline]
fn to_glib_full(&self) -> *mut glib_sys::GHashTable {
unsafe {
let ptr = glib_sys::g_hash_table_new_full(
Some(glib_sys::g_str_hash),
Some(glib_sys::g_str_equal),
Some(glib_sys::g_free),
Some(glib_sys::g_free),
);
for (k, v) in self {
let k: *mut c_char = k.to_glib_full();
let v: *mut c_char = v.to_glib_full();
glib_sys::g_hash_table_insert(ptr, k as *mut _, v as *mut _);
}
ptr
}
}
}
pub struct HashTable(*mut glib_sys::GHashTable);
impl Drop for HashTable {
fn drop(&mut self) {
unsafe { glib_sys::g_hash_table_unref(self.0) }
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GArray> for &'a T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<Array>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, &'a T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [&'a T]) -> (*const glib_sys::GArray, Self::Storage) {
let (list, stash) =
ToGlibContainerFromSlice::<*mut glib_sys::GArray>::to_glib_none_from_slice(t);
(list as *const glib_sys::GArray, stash)
}
#[inline]
fn to_glib_container_from_slice(_t: &'a [&'a T]) -> (*const glib_sys::GArray, Self::Storage) {
unimplemented!()
}
#[inline]
fn to_glib_full_from_slice(_t: &[&'a T]) -> *const glib_sys::GArray {
unimplemented!()
}
}
pub struct Array(*mut glib_sys::GArray);
impl Drop for Array {
fn drop(&mut self) {
unsafe {
glib_sys::g_array_free(self.0, false.to_glib());
}
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GArray> for T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<Array>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [T]) -> (*mut glib_sys::GArray, Self::Storage) {
let stash_vec: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let mut arr: *mut glib_sys::GArray = ptr::null_mut();
unsafe {
for stash in &stash_vec {
arr = glib_sys::g_array_append_vals(arr, Ptr::to(stash.0), 1);
}
}
(arr, (Some(Array(arr)), stash_vec))
}
#[inline]
fn to_glib_container_from_slice(t: &'a [T]) -> (*mut glib_sys::GArray, Self::Storage) {
let stash_vec: Vec<_> = t.iter().rev().map(ToGlibPtr::to_glib_none).collect();
let mut arr: *mut glib_sys::GArray = ptr::null_mut();
unsafe {
for stash in &stash_vec {
arr = glib_sys::g_array_append_vals(arr, Ptr::to(stash.0), 1);
}
}
(arr, (None, stash_vec))
}
#[inline]
fn to_glib_full_from_slice(t: &[T]) -> *mut glib_sys::GArray {
let mut arr: *mut glib_sys::GArray = ptr::null_mut();
unsafe {
for ptr in t.iter().map(ToGlibPtr::to_glib_full) {
arr = glib_sys::g_array_append_vals(arr, Ptr::to(ptr), 1);
}
}
arr
}
}
pub struct PtrArray(*mut glib_sys::GPtrArray);
impl Drop for PtrArray {
fn drop(&mut self) {
unsafe {
glib_sys::g_ptr_array_unref(self.0);
}
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *mut glib_sys::GPtrArray> for T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<PtrArray>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [T]) -> (*mut glib_sys::GPtrArray, Self::Storage) {
let stash_vec: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let arr = unsafe { glib_sys::g_ptr_array_sized_new(t.len() as _) };
unsafe {
for stash in &stash_vec {
glib_sys::g_ptr_array_add(arr, Ptr::to(stash.0));
}
}
(arr, (Some(PtrArray(arr)), stash_vec))
}
#[inline]
fn to_glib_container_from_slice(t: &'a [T]) -> (*mut glib_sys::GPtrArray, Self::Storage) {
let stash_vec: Vec<_> = t.iter().map(ToGlibPtr::to_glib_none).collect();
let arr = unsafe { glib_sys::g_ptr_array_sized_new(t.len() as _) };
unsafe {
for stash in &stash_vec {
glib_sys::g_ptr_array_add(arr, Ptr::to(stash.0));
}
}
(arr, (None, stash_vec))
}
#[inline]
fn to_glib_full_from_slice(t: &[T]) -> *mut glib_sys::GPtrArray {
let arr = unsafe { glib_sys::g_ptr_array_sized_new(t.len() as _) };
unsafe {
for ptr in t.iter().map(ToGlibPtr::to_glib_full) {
glib_sys::g_ptr_array_add(arr, Ptr::to(ptr));
}
}
arr
}
}
impl<'a, T> ToGlibContainerFromSlice<'a, *const glib_sys::GPtrArray> for T
where
T: GlibPtrDefault + ToGlibPtr<'a, <T as GlibPtrDefault>::GlibType>,
{
type Storage = (
Option<PtrArray>,
Vec<Stash<'a, <T as GlibPtrDefault>::GlibType, T>>,
);
#[inline]
fn to_glib_none_from_slice(t: &'a [T]) -> (*const glib_sys::GPtrArray, Self::Storage) {
let (arr, stash) =
ToGlibContainerFromSlice::<*mut glib_sys::GPtrArray>::to_glib_none_from_slice(t);
(arr as *const glib_sys::GPtrArray, stash)
}
#[inline]
fn to_glib_container_from_slice(_t: &'a [T]) -> (*const glib_sys::GPtrArray, Self::Storage) {
unimplemented!()
}
#[inline]
fn to_glib_full_from_slice(_t: &[T]) -> *const glib_sys::GPtrArray {
unimplemented!()
}
}
pub trait FromGlib<T>: Sized {
fn from_glib(val: T) -> Self;
}
#[inline]
pub fn from_glib<G, T: FromGlib<G>>(val: G) -> T {
FromGlib::from_glib(val)
}
impl FromGlib<glib_sys::gboolean> for bool {
#[inline]
fn from_glib(val: glib_sys::gboolean) -> bool {
val != glib_sys::GFALSE
}
}
impl FromGlib<u32> for char {
#[inline]
fn from_glib(val: u32) -> char {
char::from_u32(val).expect("Valid Unicode character expected")
}
}
impl FromGlib<i32> for Ordering {
#[inline]
fn from_glib(val: i32) -> Ordering {
if val < 0 {
Ordering::Less
} else if val > 0 {
Ordering::Greater
} else {
Ordering::Equal
}
}
}
impl FromGlib<u32> for Option<char> {
#[inline]
fn from_glib(val: u32) -> Option<char> {
match val {
0 => None,
_ => char::from_u32(val),
}
}
}
impl FromGlib<i32> for Option<u32> {
#[inline]
fn from_glib(val: i32) -> Option<u32> {
if val >= 0 {
Some(val as u32)
} else {
None
}
}
}
impl FromGlib<i64> for Option<u64> {
#[inline]
fn from_glib(val: i64) -> Option<u64> {
if val >= 0 {
Some(val as u64)
} else {
None
}
}
}
impl FromGlib<i32> for Option<u64> {
#[inline]
fn from_glib(val: i32) -> Option<u64> {
FromGlib::from_glib(i64::from(val))
}
}
pub trait FromGlibPtrNone<P: Ptr>: Sized {
unsafe fn from_glib_none(ptr: P) -> Self;
}
pub trait FromGlibPtrFull<P: Ptr>: Sized {
unsafe fn from_glib_full(ptr: P) -> Self;
}
pub trait FromGlibPtrBorrow<P: Ptr>: Sized {
unsafe fn from_glib_borrow(_ptr: P) -> Self {
unimplemented!();
}
}
#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn from_glib_none<P: Ptr, T: FromGlibPtrNone<P>>(ptr: P) -> T {
FromGlibPtrNone::from_glib_none(ptr)
}
#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn from_glib_full<P: Ptr, T: FromGlibPtrFull<P>>(ptr: P) -> T {
FromGlibPtrFull::from_glib_full(ptr)
}
#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn from_glib_borrow<P: Ptr, T: FromGlibPtrBorrow<P>>(ptr: P) -> T {
FromGlibPtrBorrow::from_glib_borrow(ptr)
}
impl<P: Ptr, T: FromGlibPtrNone<P>> FromGlibPtrNone<P> for Option<T> {
#[inline]
unsafe fn from_glib_none(ptr: P) -> Option<T> {
if ptr.is_null() {
None
} else {
Some(from_glib_none(ptr))
}
}
}
impl<P: Ptr, T: FromGlibPtrBorrow<P>> FromGlibPtrBorrow<P> for Option<T> {
#[inline]
unsafe fn from_glib_borrow(ptr: P) -> Option<T> {
if ptr.is_null() {
None
} else {
Some(from_glib_borrow(ptr))
}
}
}
impl<P: Ptr, T: FromGlibPtrFull<P>> FromGlibPtrFull<P> for Option<T> {
#[inline]
unsafe fn from_glib_full(ptr: P) -> Option<T> {
if ptr.is_null() {
None
} else {
Some(from_glib_full(ptr))
}
}
}
impl FromGlibPtrNone<*const c_char> for String {
#[inline]
unsafe fn from_glib_none(ptr: *const c_char) -> Self {
assert!(!ptr.is_null());
String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned()
}
}
impl FromGlibPtrFull<*const c_char> for String {
#[inline]
unsafe fn from_glib_full(ptr: *const c_char) -> Self {
let res = from_glib_none(ptr);
glib_sys::g_free(ptr as *mut _);
res
}
}
impl FromGlibPtrNone<*mut c_char> for String {
#[inline]
unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
assert!(!ptr.is_null());
String::from_utf8_lossy(CStr::from_ptr(ptr).to_bytes()).into_owned()
}
}
impl FromGlibPtrFull<*mut c_char> for String {
#[inline]
unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
let res = from_glib_none(ptr);
glib_sys::g_free(ptr as *mut _);
res
}
}
#[cfg(not(windows))]
unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
assert!(!ptr.is_null());
OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec()).into()
}
#[cfg(windows)]
unsafe fn c_to_path_buf(ptr: *const c_char) -> PathBuf {
assert!(!ptr.is_null());
String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
.expect("Invalid, non-UTF8 path")
.into()
}
#[cfg(not(windows))]
unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
assert!(!ptr.is_null());
OsString::from_vec(CStr::from_ptr(ptr).to_bytes().to_vec())
}
#[cfg(windows)]
unsafe fn c_to_os_string(ptr: *const c_char) -> OsString {
assert!(!ptr.is_null());
String::from_utf8(CStr::from_ptr(ptr).to_bytes().into())
.expect("Invalid, non-UTF8 path")
.into()
}
impl FromGlibPtrNone<*const c_char> for PathBuf {
#[inline]
unsafe fn from_glib_none(ptr: *const c_char) -> Self {
assert!(!ptr.is_null());
c_to_path_buf(ptr)
}
}
impl FromGlibPtrFull<*const c_char> for PathBuf {
#[inline]
unsafe fn from_glib_full(ptr: *const c_char) -> Self {
let res = from_glib_none(ptr);
glib_sys::g_free(ptr as *mut _);
res
}
}
impl FromGlibPtrNone<*mut c_char> for PathBuf {
#[inline]
unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
assert!(!ptr.is_null());
c_to_path_buf(ptr)
}
}
impl FromGlibPtrFull<*mut c_char> for PathBuf {
#[inline]
unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
let res = from_glib_none(ptr);
glib_sys::g_free(ptr as *mut _);
res
}
}
impl FromGlibPtrNone<*const c_char> for OsString {
#[inline]
unsafe fn from_glib_none(ptr: *const c_char) -> Self {
assert!(!ptr.is_null());
c_to_os_string(ptr)
}
}
impl FromGlibPtrFull<*const c_char> for OsString {
#[inline]
unsafe fn from_glib_full(ptr: *const c_char) -> Self {
let res = from_glib_none(ptr);
glib_sys::g_free(ptr as *mut _);
res
}
}
impl FromGlibPtrNone<*mut c_char> for OsString {
#[inline]
unsafe fn from_glib_none(ptr: *mut c_char) -> Self {
assert!(!ptr.is_null());
c_to_os_string(ptr)
}
}
impl FromGlibPtrFull<*mut c_char> for OsString {
#[inline]
unsafe fn from_glib_full(ptr: *mut c_char) -> Self {
let res = from_glib_none(ptr);
glib_sys::g_free(ptr as *mut _);
res
}
}
pub trait FromGlibContainer<T, P: Ptr>: Sized {
unsafe fn from_glib_none_num(ptr: P, num: usize) -> Self;
unsafe fn from_glib_container_num(ptr: P, num: usize) -> Self;
unsafe fn from_glib_full_num(ptr: P, num: usize) -> Self;
}
pub trait FromGlibPtrContainer<P: Ptr, PP: Ptr>: FromGlibContainer<P, PP> + Sized {
unsafe fn from_glib_none(ptr: PP) -> Self;
unsafe fn from_glib_container(ptr: PP) -> Self;
unsafe fn from_glib_full(ptr: PP) -> Self;
}
#[allow(clippy::missing_safety_doc)]
pub unsafe fn c_ptr_array_len<P: Ptr>(mut ptr: *const P) -> usize {
let mut len = 0;
if !ptr.is_null() {
while !(*ptr).is_null() {
len += 1;
ptr = ptr.offset(1);
}
}
len
}
pub trait FromGlibContainerAsVec<T, P: Ptr>
where
Self: Sized,
{
unsafe fn from_glib_none_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
unsafe fn from_glib_container_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
unsafe fn from_glib_full_num_as_vec(ptr: P, num: usize) -> Vec<Self>;
}
pub trait FromGlibPtrArrayContainerAsVec<P: Ptr, PP: Ptr>: FromGlibContainerAsVec<P, PP>
where
Self: Sized,
{
unsafe fn from_glib_none_as_vec(ptr: PP) -> Vec<Self>;
unsafe fn from_glib_container_as_vec(ptr: PP) -> Vec<Self>;
unsafe fn from_glib_full_as_vec(ptr: PP) -> Vec<Self>;
}
impl FromGlibContainerAsVec<bool, *const glib_sys::gboolean> for bool {
unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::gboolean, num: usize) -> Vec<Self> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let mut res = Vec::with_capacity(num);
for i in 0..num {
res.push(from_glib(ptr::read(ptr.add(i))));
}
res
}
unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::gboolean, _: usize) -> Vec<Self> {
unimplemented!();
}
unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::gboolean, _: usize) -> Vec<Self> {
unimplemented!();
}
}
impl FromGlibContainerAsVec<bool, *mut glib_sys::gboolean> for bool {
unsafe fn from_glib_none_num_as_vec(ptr: *mut glib_sys::gboolean, num: usize) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
}
unsafe fn from_glib_container_num_as_vec(
ptr: *mut glib_sys::gboolean,
num: usize,
) -> Vec<Self> {
let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
glib_sys::g_free(ptr as *mut _);
res
}
unsafe fn from_glib_full_num_as_vec(ptr: *mut glib_sys::gboolean, num: usize) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
}
}
macro_rules! impl_from_glib_container_as_vec_fundamental {
($name:ty) => {
impl FromGlibContainerAsVec<$name, *const $name> for $name {
unsafe fn from_glib_none_num_as_vec(ptr: *const $name, num: usize) -> Vec<Self> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let mut res = Vec::with_capacity(num);
for i in 0..num {
res.push(ptr::read(ptr.add(i)));
}
res
}
unsafe fn from_glib_container_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
unimplemented!();
}
unsafe fn from_glib_full_num_as_vec(_: *const $name, _: usize) -> Vec<Self> {
unimplemented!();
}
}
impl FromGlibContainerAsVec<$name, *mut $name> for $name {
unsafe fn from_glib_none_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
}
unsafe fn from_glib_container_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
glib_sys::g_free(ptr as *mut _);
res
}
unsafe fn from_glib_full_num_as_vec(ptr: *mut $name, num: usize) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
}
}
};
}
impl_from_glib_container_as_vec_fundamental!(u8);
impl_from_glib_container_as_vec_fundamental!(i8);
impl_from_glib_container_as_vec_fundamental!(u16);
impl_from_glib_container_as_vec_fundamental!(i16);
impl_from_glib_container_as_vec_fundamental!(u32);
impl_from_glib_container_as_vec_fundamental!(i32);
impl_from_glib_container_as_vec_fundamental!(u64);
impl_from_glib_container_as_vec_fundamental!(i64);
impl_from_glib_container_as_vec_fundamental!(f32);
impl_from_glib_container_as_vec_fundamental!(f64);
macro_rules! impl_from_glib_container_as_vec_string {
($name:ty, $ffi_name:ty) => {
impl FromGlibContainerAsVec<$ffi_name, *const $ffi_name> for $name {
unsafe fn from_glib_none_num_as_vec(ptr: *const $ffi_name, num: usize) -> Vec<Self> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let mut res = Vec::with_capacity(num);
for i in 0..num {
res.push(from_glib_none(ptr::read(ptr.add(i)) as $ffi_name));
}
res
}
unsafe fn from_glib_container_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
unimplemented!();
}
unsafe fn from_glib_full_num_as_vec(_: *const $ffi_name, _: usize) -> Vec<Self> {
unimplemented!();
}
}
impl FromGlibContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
unsafe fn from_glib_none_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
}
unsafe fn from_glib_container_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
glib_sys::g_free(ptr as *mut _);
res
}
unsafe fn from_glib_full_num_as_vec(ptr: *mut $ffi_name, num: usize) -> Vec<Self> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let mut res = Vec::with_capacity(num);
for i in 0..num {
res.push(from_glib_full(ptr::read(ptr.add(i))));
}
glib_sys::g_free(ptr as *mut _);
res
}
}
impl FromGlibPtrArrayContainerAsVec<$ffi_name, *mut $ffi_name> for $name {
unsafe fn from_glib_none_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
}
unsafe fn from_glib_container_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
}
unsafe fn from_glib_full_as_vec(ptr: *mut $ffi_name) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
}
}
impl FromGlibPtrArrayContainerAsVec<$ffi_name, *const $ffi_name> for $name {
unsafe fn from_glib_none_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, c_ptr_array_len(ptr))
}
unsafe fn from_glib_container_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, c_ptr_array_len(ptr))
}
unsafe fn from_glib_full_as_vec(ptr: *const $ffi_name) -> Vec<Self> {
FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, c_ptr_array_len(ptr))
}
}
};
}
impl_from_glib_container_as_vec_string!(String, *const c_char);
impl_from_glib_container_as_vec_string!(String, *mut c_char);
impl_from_glib_container_as_vec_string!(PathBuf, *const c_char);
impl_from_glib_container_as_vec_string!(PathBuf, *mut c_char);
impl_from_glib_container_as_vec_string!(OsString, *const c_char);
impl_from_glib_container_as_vec_string!(OsString, *mut c_char);
impl<P, PP: Ptr, T: FromGlibContainerAsVec<P, PP>> FromGlibContainer<P, PP> for Vec<T> {
unsafe fn from_glib_none_num(ptr: PP, num: usize) -> Vec<T> {
FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num)
}
unsafe fn from_glib_container_num(ptr: PP, num: usize) -> Vec<T> {
FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
}
unsafe fn from_glib_full_num(ptr: PP, num: usize) -> Vec<T> {
FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, num)
}
}
impl<P: Ptr, PP: Ptr, T: FromGlibPtrArrayContainerAsVec<P, PP>> FromGlibPtrContainer<P, PP>
for Vec<T>
{
unsafe fn from_glib_none(ptr: PP) -> Vec<T> {
FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr)
}
unsafe fn from_glib_container(ptr: PP) -> Vec<T> {
FromGlibPtrArrayContainerAsVec::from_glib_container_as_vec(ptr)
}
unsafe fn from_glib_full(ptr: PP) -> Vec<T> {
FromGlibPtrArrayContainerAsVec::from_glib_full_as_vec(ptr)
}
}
impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GSList> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_num_as_vec(mut ptr: *mut glib_sys::GSList, num: usize) -> Vec<T> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let mut res = Vec::with_capacity(num);
for _ in 0..num {
let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
if !item_ptr.is_null() {
res.push(from_glib_none(item_ptr));
}
ptr = (*ptr).next;
}
res
}
unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GSList, num: usize) -> Vec<T> {
let res = FromGlibContainer::from_glib_none_num(ptr, num);
if !ptr.is_null() {
glib_sys::g_slist_free(ptr as *mut _);
}
res
}
unsafe fn from_glib_full_num_as_vec(mut ptr: *mut glib_sys::GSList, num: usize) -> Vec<T> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let orig_ptr = ptr;
let mut res = Vec::with_capacity(num);
for _ in 0..num {
let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
if !item_ptr.is_null() {
res.push(from_glib_full(item_ptr));
}
ptr = (*ptr).next;
}
glib_sys::g_slist_free(orig_ptr as *mut _);
res
}
}
impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GSList> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_as_vec(ptr: *mut glib_sys::GSList) -> Vec<T> {
let num = glib_sys::g_slist_length(ptr) as usize;
FromGlibContainer::from_glib_none_num(ptr, num)
}
unsafe fn from_glib_container_as_vec(ptr: *mut glib_sys::GSList) -> Vec<T> {
let num = glib_sys::g_slist_length(ptr) as usize;
FromGlibContainer::from_glib_container_num(ptr, num)
}
unsafe fn from_glib_full_as_vec(ptr: *mut glib_sys::GSList) -> Vec<T> {
let num = glib_sys::g_slist_length(ptr) as usize;
FromGlibContainer::from_glib_full_num(ptr, num)
}
}
impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GList> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_num_as_vec(mut ptr: *mut glib_sys::GList, num: usize) -> Vec<T> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let mut res = Vec::with_capacity(num);
for _ in 0..num {
let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
if !item_ptr.is_null() {
res.push(from_glib_none(item_ptr));
}
ptr = (*ptr).next;
}
res
}
unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GList, num: usize) -> Vec<T> {
let res = FromGlibContainer::from_glib_none_num(ptr, num);
if !ptr.is_null() {
glib_sys::g_list_free(ptr as *mut _);
}
res
}
unsafe fn from_glib_full_num_as_vec(mut ptr: *mut glib_sys::GList, num: usize) -> Vec<T> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let orig_ptr = ptr;
let mut res = Vec::with_capacity(num);
for _ in 0..num {
let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from((*ptr).data);
if !item_ptr.is_null() {
res.push(from_glib_full(item_ptr));
}
ptr = (*ptr).next;
}
glib_sys::g_list_free(orig_ptr as *mut _);
res
}
}
impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GList> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_as_vec(ptr: *mut glib_sys::GList) -> Vec<T> {
let num = glib_sys::g_list_length(ptr) as usize;
FromGlibContainer::from_glib_none_num(ptr, num)
}
unsafe fn from_glib_container_as_vec(ptr: *mut glib_sys::GList) -> Vec<T> {
let num = glib_sys::g_list_length(ptr) as usize;
FromGlibContainer::from_glib_container_num(ptr, num)
}
unsafe fn from_glib_full_as_vec(ptr: *mut glib_sys::GList) -> Vec<T> {
let num = glib_sys::g_list_length(ptr) as usize;
FromGlibContainer::from_glib_full_num(ptr, num)
}
}
impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GList> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GList, num: usize) -> Vec<T> {
FromGlibContainer::from_glib_none_num(mut_override(ptr), num)
}
unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GList, _: usize) -> Vec<T> {
unimplemented!()
}
unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GList, _: usize) -> Vec<T> {
unimplemented!()
}
}
impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GList>
for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_as_vec(ptr: *const glib_sys::GList) -> Vec<T> {
FromGlibPtrContainer::from_glib_none(mut_override(ptr))
}
unsafe fn from_glib_container_as_vec(_: *const glib_sys::GList) -> Vec<T> {
unimplemented!()
}
unsafe fn from_glib_full_as_vec(_: *const glib_sys::GList) -> Vec<T> {
unimplemented!()
}
}
impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GSList> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GSList, num: usize) -> Vec<T> {
FromGlibContainer::from_glib_none_num(mut_override(ptr), num)
}
unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GSList, _: usize) -> Vec<T> {
unimplemented!()
}
unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GSList, _: usize) -> Vec<T> {
unimplemented!()
}
}
impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GSList>
for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_as_vec(ptr: *const glib_sys::GSList) -> Vec<T> {
FromGlibPtrContainer::from_glib_none(mut_override(ptr))
}
unsafe fn from_glib_container_as_vec(_: *const glib_sys::GSList) -> Vec<T> {
unimplemented!()
}
unsafe fn from_glib_full_as_vec(_: *const glib_sys::GSList) -> Vec<T> {
unimplemented!()
}
}
#[allow(clippy::implicit_hasher)]
impl FromGlibContainer<*const c_char, *mut glib_sys::GHashTable> for HashMap<String, String> {
unsafe fn from_glib_none_num(ptr: *mut glib_sys::GHashTable, _: usize) -> Self {
FromGlibPtrContainer::from_glib_none(ptr)
}
unsafe fn from_glib_container_num(ptr: *mut glib_sys::GHashTable, _: usize) -> Self {
FromGlibPtrContainer::from_glib_full(ptr)
}
unsafe fn from_glib_full_num(ptr: *mut glib_sys::GHashTable, _: usize) -> Self {
FromGlibPtrContainer::from_glib_full(ptr)
}
}
#[allow(clippy::implicit_hasher)]
impl FromGlibPtrContainer<*const c_char, *mut glib_sys::GHashTable> for HashMap<String, String> {
unsafe fn from_glib_none(ptr: *mut glib_sys::GHashTable) -> Self {
unsafe extern "C" fn read_string_hash_table(
key: glib_sys::gpointer,
value: glib_sys::gpointer,
hash_map: glib_sys::gpointer,
) {
let key: String = from_glib_none(key as *const c_char);
let value: String = from_glib_none(value as *const c_char);
let hash_map: &mut HashMap<String, String> =
&mut *(hash_map as *mut HashMap<String, String>);
hash_map.insert(key, value);
}
let mut map = HashMap::new();
glib_sys::g_hash_table_foreach(
ptr,
Some(read_string_hash_table),
&mut map as *mut HashMap<String, String> as *mut _,
);
map
}
unsafe fn from_glib_container(ptr: *mut glib_sys::GHashTable) -> Self {
FromGlibPtrContainer::from_glib_full(ptr)
}
unsafe fn from_glib_full(ptr: *mut glib_sys::GHashTable) -> Self {
let map = FromGlibPtrContainer::from_glib_none(ptr);
glib_sys::g_hash_table_unref(ptr);
map
}
}
impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GPtrArray> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_num_as_vec(ptr: *mut glib_sys::GPtrArray, num: usize) -> Vec<T> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let pdata = (*ptr).pdata;
assert!((*ptr).len as usize >= num);
let mut res = Vec::with_capacity(num);
for i in 0..num {
let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from(ptr::read(pdata.add(i)));
if !item_ptr.is_null() {
res.push(from_glib_none(item_ptr));
}
}
res
}
unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GPtrArray, num: usize) -> Vec<T> {
let res = FromGlibContainer::from_glib_none_num(ptr, num);
if !ptr.is_null() {
glib_sys::g_ptr_array_unref(ptr);
}
res
}
unsafe fn from_glib_full_num_as_vec(ptr: *mut glib_sys::GPtrArray, num: usize) -> Vec<T> {
if num == 0 || ptr.is_null() {
return Vec::new();
}
let pdata = (*ptr).pdata;
assert!((*ptr).len as usize >= num);
let mut res = Vec::with_capacity(num);
for i in 0..num {
let item_ptr: <T as GlibPtrDefault>::GlibType = Ptr::from(ptr::read(pdata.add(i)));
if !item_ptr.is_null() {
res.push(from_glib_none(item_ptr));
}
}
glib_sys::g_ptr_array_unref(ptr);
res
}
}
impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *mut glib_sys::GPtrArray>
for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_as_vec(ptr: *mut glib_sys::GPtrArray) -> Vec<T> {
let num = (*ptr).len as usize;
FromGlibContainer::from_glib_none_num(ptr, num)
}
unsafe fn from_glib_container_as_vec(ptr: *mut glib_sys::GPtrArray) -> Vec<T> {
let num = (*ptr).len as usize;
FromGlibContainer::from_glib_container_num(ptr, num)
}
unsafe fn from_glib_full_as_vec(ptr: *mut glib_sys::GPtrArray) -> Vec<T> {
let num = (*ptr).len as usize;
FromGlibContainer::from_glib_full_num(ptr, num)
}
}
impl<T> FromGlibContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GPtrArray> for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GPtrArray, num: usize) -> Vec<T> {
FromGlibContainer::from_glib_none_num(mut_override(ptr), num)
}
unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GPtrArray, _: usize) -> Vec<T> {
unimplemented!()
}
unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GPtrArray, _: usize) -> Vec<T> {
unimplemented!()
}
}
impl<T> FromGlibPtrArrayContainerAsVec<<T as GlibPtrDefault>::GlibType, *const glib_sys::GPtrArray>
for T
where
T: GlibPtrDefault
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>,
{
unsafe fn from_glib_none_as_vec(ptr: *const glib_sys::GPtrArray) -> Vec<T> {
FromGlibPtrContainer::from_glib_none(mut_override(ptr))
}
unsafe fn from_glib_container_as_vec(_: *const glib_sys::GPtrArray) -> Vec<T> {
unimplemented!()
}
unsafe fn from_glib_full_as_vec(_: *const glib_sys::GPtrArray) -> Vec<T> {
unimplemented!()
}
}
#[cfg(test)]
mod tests {
extern crate tempfile;
use self::tempfile::tempdir;
use std::fs;
use super::*;
use glib_sys;
use gstring::GString;
use std::collections::HashMap;
#[test]
fn string_hash_map() {
let mut map = HashMap::new();
map.insert("A".into(), "1".into());
map.insert("B".into(), "2".into());
map.insert("C".into(), "3".into());
let ptr: *mut glib_sys::GHashTable = map.to_glib_full();
let map = unsafe { HashMap::from_glib_full(ptr) };
assert_eq!(map.get("A"), Some(&"1".into()));
assert_eq!(map.get("B"), Some(&"2".into()));
assert_eq!(map.get("C"), Some(&"3".into()));
}
#[test]
fn string_array() {
let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
let stash = v.to_glib_none();
let ptr: *mut *mut c_char = stash.0;
let ptr_copy = unsafe { glib_sys::g_strdupv(ptr) };
let actual: Vec<String> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
assert_eq!(v, actual);
}
#[test]
fn gstring_array() {
let v = vec!["A".to_string(), "B".to_string(), "C".to_string()];
let stash = v.to_glib_none();
let ptr: *mut *mut c_char = stash.0;
let ptr_copy = unsafe { glib_sys::g_strdupv(ptr) };
let actual: Vec<GString> = unsafe { FromGlibPtrContainer::from_glib_full(ptr_copy) };
assert_eq!(v, actual);
}
#[test]
fn ptr_array() {
let strings = &["A", "B", "C"];
let (ptr, _stash) =
ToGlibContainerFromSlice::<*mut glib_sys::GPtrArray>::to_glib_none_from_slice(strings);
let v: Vec<GString> = unsafe { FromGlibPtrArrayContainerAsVec::from_glib_none_as_vec(ptr) };
assert_eq!(&v, strings);
}
#[test]
#[cfg(not(target_os = "macos"))]
fn test_paths() {
let tmp_dir = tempdir().unwrap();
let dir_1 = tmp_dir.path().join("abcd");
fs::create_dir(&dir_1).unwrap();
assert_eq!(::path_get_basename(&dir_1), Some("abcd".into()));
assert_eq!(
::path_get_basename(dir_1.canonicalize().unwrap()),
Some("abcd".into())
);
assert_eq!(
::path_get_dirname(dir_1.canonicalize().unwrap()),
Some(tmp_dir.path().into())
);
assert!(::file_test(&dir_1, ::FileTest::EXISTS | ::FileTest::IS_DIR));
assert!(::file_test(
&dir_1.canonicalize().unwrap(),
::FileTest::EXISTS | ::FileTest::IS_DIR
));
let dir_2 = tmp_dir.as_ref().join("øäöü");
fs::create_dir(&dir_2).unwrap();
assert_eq!(::path_get_basename(&dir_2), Some("øäöü".into()));
assert_eq!(
::path_get_basename(dir_2.canonicalize().unwrap()),
Some("øäöü".into())
);
assert_eq!(
::path_get_dirname(dir_2.canonicalize().unwrap()),
Some(tmp_dir.path().into())
);
assert!(::file_test(&dir_2, ::FileTest::EXISTS | ::FileTest::IS_DIR));
assert!(::file_test(
&dir_2.canonicalize().unwrap(),
::FileTest::EXISTS | ::FileTest::IS_DIR
));
}
#[test]
#[cfg(target_os = "macos")]
fn test_paths() {
let t_dir = tempdir().unwrap();
let tmp_dir = t_dir.path().canonicalize().unwrap();
let dir_1 = tmp_dir.join("abcd");
fs::create_dir(&dir_1).unwrap();
assert_eq!(::path_get_basename(&dir_1), Some("abcd".into()));
assert_eq!(
::path_get_basename(dir_1.canonicalize().unwrap()),
Some("abcd".into())
);
assert_eq!(
::path_get_dirname(dir_1.canonicalize().unwrap()),
Some(tmp_dir)
);
assert!(::file_test(&dir_1, ::FileTest::EXISTS | ::FileTest::IS_DIR));
assert!(::file_test(
&dir_1.canonicalize().unwrap(),
::FileTest::EXISTS | ::FileTest::IS_DIR
));
}
}