use crate::translate::*;
use std::iter::FusedIterator;
use std::marker::PhantomData;
use std::{fmt, mem, ptr};
#[derive(Debug, PartialEq, Eq)]
enum ContainerTransfer {
Full,
Container,
None,
}
pub struct PtrSlice<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> {
ptr: ptr::NonNull<T::GlibType>,
len: usize,
transfer: ContainerTransfer,
}
impl<
T: fmt::Debug
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> fmt::Debug for PtrSlice<T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_slice().fmt(f)
}
}
unsafe impl<
T: Send
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Send for PtrSlice<T>
{
}
unsafe impl<
T: Sync
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Sync for PtrSlice<T>
{
}
impl<
T: PartialEq
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> PartialEq for PtrSlice<T>
{
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<
T: Eq
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Eq for PtrSlice<T>
{
}
impl<
T: PartialOrd
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> PartialOrd for PtrSlice<T>
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<
T: Ord
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Ord for PtrSlice<T>
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<
T: std::hash::Hash
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> std::hash::Hash for PtrSlice<T>
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state)
}
}
impl<
T: PartialEq
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> PartialEq<[T]> for PtrSlice<T>
{
fn eq(&self, other: &[T]) -> bool {
self.as_slice() == other
}
}
impl<
T: PartialEq
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> PartialEq<PtrSlice<T>> for [T]
{
fn eq(&self, other: &PtrSlice<T>) -> bool {
self == other.as_slice()
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> PtrSlice<T>
{
pub unsafe fn from_glib_borrow<'a>(ptr: *const <T as GlibPtrDefault>::GlibType) -> &'a [T] {
let mut len = 0;
if !ptr.is_null() {
while !(*ptr.add(len)).is_null() {
len += 1;
}
}
Self::from_glib_borrow_num(ptr, len)
}
pub unsafe fn from_glib_borrow_num<'a>(
ptr: *const <T as GlibPtrDefault>::GlibType,
len: usize,
) -> &'a [T] {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
assert!(!ptr.is_null() || len == 0);
if len == 0 {
&[]
} else {
std::slice::from_raw_parts(ptr as *const T, len)
}
}
pub unsafe fn from_glib_none_num_static(
ptr: *const <T as GlibPtrDefault>::GlibType,
len: usize,
) -> Self {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
assert!(!ptr.is_null() || len == 0);
PtrSlice {
ptr: if len == 0 {
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr as *mut _)
},
len,
transfer: ContainerTransfer::None,
}
}
pub unsafe fn from_glib_container_num_static(
ptr: *mut <T as GlibPtrDefault>::GlibType,
len: usize,
) -> Self {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
assert!(!ptr.is_null() || len == 0);
PtrSlice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Container,
}
}
pub unsafe fn from_glib_container_num(
ptr: *mut <T as GlibPtrDefault>::GlibType,
len: usize,
) -> Self {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
assert!(!ptr.is_null() || len == 0);
for i in 0..len {
let p = ptr.add(i);
let v: T = from_glib_none(*p);
ptr::write((*p).to(), v);
}
PtrSlice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Full,
}
}
pub unsafe fn from_glib_full_num(
ptr: *mut <T as GlibPtrDefault>::GlibType,
len: usize,
) -> Self {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
assert!(!ptr.is_null() || len == 0);
PtrSlice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Full,
}
}
pub unsafe fn from_glib_none_static(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
let mut len = 0;
if !ptr.is_null() {
while !(*ptr.add(len)).is_null() {
len += 1;
}
}
PtrSlice::from_glib_none_num_static(ptr, len)
}
pub unsafe fn from_glib_container_static(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
let mut len = 0;
if !ptr.is_null() {
while !(*ptr.add(len)).is_null() {
len += 1;
}
}
PtrSlice::from_glib_container_num_static(ptr, len)
}
pub unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
let mut len = 0;
if !ptr.is_null() {
while !(*ptr.add(len)).is_null() {
let p = ptr.add(len);
let v: T = from_glib_none(*p);
ptr::write((*p).to(), v);
len += 1;
}
}
PtrSlice::from_glib_full_num(ptr, len)
}
pub unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
let mut len = 0;
if !ptr.is_null() {
while !(*ptr.add(len)).is_null() {
len += 1;
}
}
PtrSlice::from_glib_full_num(ptr, len)
}
pub fn as_ptr(&self) -> *const <T as GlibPtrDefault>::GlibType {
if self.len == 0 {
ptr::null()
} else {
self.ptr.as_ptr()
}
}
pub fn as_slice(&self) -> &[T] {
self.as_ref()
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Drop for PtrSlice<T>
{
fn drop(&mut self) {
unsafe {
if self.transfer == ContainerTransfer::Full {
for i in 0..self.len {
let _: T = from_glib_full(*self.ptr.as_ptr().add(i));
}
}
if self.transfer != ContainerTransfer::None && self.ptr != ptr::NonNull::dangling() {
ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
}
}
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> AsRef<[T]> for PtrSlice<T>
{
fn as_ref(&self) -> &[T] {
unsafe {
if self.len == 0 {
&[]
} else {
std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len)
}
}
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> std::ops::Deref for PtrSlice<T>
{
type Target = [T];
fn deref(&self) -> &[T] {
self.as_ref()
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType>
for PtrSlice<T>
{
unsafe fn from_glib_none_num(_ptr: *mut <T as GlibPtrDefault>::GlibType, _num: usize) -> Self {
unimplemented!()
}
unsafe fn from_glib_container_num(
ptr: *mut <T as GlibPtrDefault>::GlibType,
num: usize,
) -> Self {
Self::from_glib_container_num(ptr, num)
}
unsafe fn from_glib_full_num(ptr: *mut <T as GlibPtrDefault>::GlibType, num: usize) -> Self {
Self::from_glib_full_num(ptr, num)
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut <T as GlibPtrDefault>::GlibType>
for PtrSlice<T>
{
unsafe fn from_glib_none(_ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
unimplemented!()
}
unsafe fn from_glib_container(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
Self::from_glib_container(ptr)
}
unsafe fn from_glib_full(ptr: *mut <T as GlibPtrDefault>::GlibType) -> Self {
Self::from_glib_full(ptr)
}
}
pub struct Slice<T: 'static> {
ptr: ptr::NonNull<T>,
len: usize,
transfer: ContainerTransfer,
}
unsafe impl<T: Send + 'static> Send for Slice<T> {}
unsafe impl<T: Sync + 'static> Sync for Slice<T> {}
impl<T: fmt::Debug + 'static> fmt::Debug for Slice<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_slice().fmt(f)
}
}
impl<T: PartialEq + 'static> PartialEq for Slice<T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: Eq + 'static> Eq for Slice<T> {}
impl<T: PartialOrd + 'static> PartialOrd for Slice<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.as_slice().partial_cmp(other.as_slice())
}
}
impl<T: Ord + 'static> Ord for Slice<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_slice().cmp(other.as_slice())
}
}
impl<T: std::hash::Hash + 'static> std::hash::Hash for Slice<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_slice().hash(state)
}
}
impl<T: PartialEq + 'static> PartialEq<[T]> for Slice<T> {
fn eq(&self, other: &[T]) -> bool {
self.as_slice() == other
}
}
impl<T: PartialEq + 'static> PartialEq<Slice<T>> for [T] {
fn eq(&self, other: &Slice<T>) -> bool {
self == other.as_slice()
}
}
impl<T: 'static> Slice<T> {
#[inline]
pub unsafe fn from_glib_borrow_num<'a>(ptr: *const T, len: usize) -> &'a [T] {
assert!(!ptr.is_null() || len == 0);
if len == 0 {
&[]
} else {
std::slice::from_raw_parts(ptr, len)
}
}
#[inline]
pub unsafe fn from_glib_borrow_num_mut<'a>(ptr: *mut T, len: usize) -> &'a mut [T] {
assert!(!ptr.is_null() || len == 0);
if len == 0 {
&mut []
} else {
std::slice::from_raw_parts_mut(ptr, len)
}
}
pub unsafe fn from_glib_none_num_static(ptr: *const T, len: usize) -> Self {
assert!(!ptr.is_null() || len == 0);
Slice {
ptr: if len == 0 {
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr as *mut _)
},
len,
transfer: ContainerTransfer::None,
}
}
pub unsafe fn from_glib_container_num_static(ptr: *mut T, len: usize) -> Self {
assert!(!ptr.is_null() || len == 0);
Slice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Container,
}
}
pub unsafe fn from_glib_container_num_copy(ptr: *mut T, len: usize) -> Self
where
T: Copy,
{
assert!(!ptr.is_null() || len == 0);
Slice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Container,
}
}
pub unsafe fn from_glib_container_num<P: Ptr>(ptr: *mut T, len: usize) -> Self
where
T: FromGlibPtrNone<P>,
{
assert!(!ptr.is_null() || len == 0);
for i in 0..len {
let p = ptr.add(i);
let v = from_glib_none(Ptr::from(p));
ptr::write(p, v);
}
Slice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Full,
}
}
pub unsafe fn from_glib_full_num_copy(ptr: *mut T, len: usize) -> Self
where
T: Copy,
{
assert!(!ptr.is_null() || len == 0);
Slice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Container,
}
}
pub unsafe fn from_glib_full_num(ptr: *mut T, len: usize) -> Self {
assert!(!ptr.is_null() || len == 0);
Slice {
ptr: if len == 0 {
ffi::g_free(ptr as ffi::gpointer);
ptr::NonNull::dangling()
} else {
ptr::NonNull::new_unchecked(ptr)
},
len,
transfer: ContainerTransfer::Full,
}
}
pub fn as_slice(&self) -> &[T] {
self.as_ref()
}
}
impl<T: 'static> Drop for Slice<T> {
fn drop(&mut self) {
unsafe {
if self.transfer == ContainerTransfer::Full {
for i in 0..self.len {
let _ = ptr::read(self.ptr.as_ptr().add(i));
}
}
if self.transfer != ContainerTransfer::None && self.ptr != ptr::NonNull::dangling() {
ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
}
}
}
}
impl<T: 'static> AsRef<[T]> for Slice<T> {
fn as_ref(&self) -> &[T] {
unsafe {
if self.len == 0 {
&[]
} else {
std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len)
}
}
}
}
impl<T: 'static> std::ops::Deref for Slice<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_ref()
}
}
impl<T: FromGlibPtrNone<*mut T> + 'static> FromGlibContainer<T, *mut T> for Slice<T> {
unsafe fn from_glib_none_num(_ptr: *mut T, _num: usize) -> Self {
unimplemented!()
}
unsafe fn from_glib_container_num(ptr: *mut T, num: usize) -> Self {
Self::from_glib_container_num(ptr, num)
}
unsafe fn from_glib_full_num(ptr: *mut T, num: usize) -> Self {
Self::from_glib_full_num(ptr, num)
}
}
pub struct List<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> {
ptr: Option<ptr::NonNull<ffi::GList>>,
transfer: ContainerTransfer,
phantom: PhantomData<T>,
}
unsafe impl<
T: Send
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Send for List<T>
{
}
unsafe impl<
T: Sync
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Sync for List<T>
{
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> List<T>
{
pub unsafe fn from_glib_none_static(list: *mut ffi::GList) -> List<T> {
List {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::None,
phantom: PhantomData,
}
}
pub unsafe fn from_glib_container(list: *mut ffi::GList) -> List<T> {
let mut l = list;
while !l.is_null() {
let item: T = from_glib_none(Ptr::from((*l).data));
ptr::write((*l).data as *mut T, item);
l = (*l).next;
}
List {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::Full,
phantom: PhantomData,
}
}
pub unsafe fn from_glib_container_static(list: *mut ffi::GList) -> List<T> {
List {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::Container,
phantom: PhantomData,
}
}
pub unsafe fn from_glib_full(list: *mut ffi::GList) -> List<T> {
List {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::Full,
phantom: PhantomData,
}
}
pub fn iter(&self) -> ListIter<T> {
ListIter::new(self)
}
pub fn is_empty(&self) -> bool {
self.ptr.is_none()
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Drop for List<T>
{
fn drop(&mut self) {
for item in self {
drop(item);
}
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Iterator for List<T>
{
type Item = T;
fn next(&mut self) -> Option<T> {
match self.ptr {
None => None,
Some(cur) => unsafe {
self.ptr = ptr::NonNull::new(cur.as_ref().next);
if let Some(mut next) = self.ptr {
next.as_mut().prev = ptr::null_mut();
}
let item = if self.transfer == ContainerTransfer::Full {
from_glib_full(Ptr::from(cur.as_ref().data))
} else {
from_glib_none(Ptr::from(cur.as_ref().data))
};
if self.transfer != ContainerTransfer::None {
ffi::g_list_free_1(cur.as_ptr());
}
Some(item)
},
}
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FusedIterator for List<T>
{
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut ffi::GList> for List<T>
{
unsafe fn from_glib_none_num(_ptr: *mut ffi::GList, _num: usize) -> Self {
unimplemented!()
}
unsafe fn from_glib_container_num(ptr: *mut ffi::GList, _num: usize) -> Self {
Self::from_glib_container(ptr)
}
unsafe fn from_glib_full_num(ptr: *mut ffi::GList, _num: usize) -> Self {
Self::from_glib_full(ptr)
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut ffi::GList> for List<T>
{
unsafe fn from_glib_none(_ptr: *mut ffi::GList) -> Self {
unimplemented!()
}
unsafe fn from_glib_container(ptr: *mut ffi::GList) -> Self {
Self::from_glib_container(ptr)
}
unsafe fn from_glib_full(ptr: *mut ffi::GList) -> Self {
Self::from_glib_full(ptr)
}
}
pub struct ListIter<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> {
ptr: Option<ptr::NonNull<ffi::GList>>,
phantom: PhantomData<&'a T>,
}
impl<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> ListIter<'a, T>
{
fn new(list: &'a List<T>) -> ListIter<'a, T> {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
ListIter {
ptr: list.ptr,
phantom: PhantomData,
}
}
}
impl<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Iterator for ListIter<'a, T>
{
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
match self.ptr {
None => None,
Some(cur) => unsafe {
self.ptr = ptr::NonNull::new(cur.as_ref().next);
let item = &*(&cur.as_ref().data as *const ffi::gpointer as *const T);
Some(item)
},
}
}
}
impl<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FusedIterator for ListIter<'a, T>
{
}
pub struct SList<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> {
ptr: Option<ptr::NonNull<ffi::GSList>>,
transfer: ContainerTransfer,
phantom: PhantomData<T>,
}
unsafe impl<
T: Send
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Send for SList<T>
{
}
unsafe impl<
T: Sync
+ GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Sync for SList<T>
{
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> SList<T>
{
pub unsafe fn from_glib_none_static(list: *mut ffi::GSList) -> SList<T> {
SList {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::None,
phantom: PhantomData,
}
}
pub unsafe fn from_glib_container(list: *mut ffi::GSList) -> SList<T> {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
let mut l = list;
while !l.is_null() {
let item: T = from_glib_none(Ptr::from((*l).data));
ptr::write((*l).data as *mut T, item);
l = (*l).next;
}
SList {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::Full,
phantom: PhantomData,
}
}
pub unsafe fn from_glib_container_static(list: *mut ffi::GSList) -> SList<T> {
SList {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::Container,
phantom: PhantomData,
}
}
pub unsafe fn from_glib_full(list: *mut ffi::GSList) -> SList<T> {
SList {
ptr: ptr::NonNull::new(list),
transfer: ContainerTransfer::Full,
phantom: PhantomData,
}
}
pub fn iter(&self) -> SListIter<T> {
SListIter::new(self)
}
pub fn is_empty(&self) -> bool {
self.ptr.is_none()
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Drop for SList<T>
{
fn drop(&mut self) {
for item in self {
drop(item);
}
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Iterator for SList<T>
{
type Item = T;
fn next(&mut self) -> Option<T> {
match self.ptr {
None => None,
Some(cur) => unsafe {
self.ptr = ptr::NonNull::new(cur.as_ref().next);
let item = if self.transfer == ContainerTransfer::Full {
from_glib_full(Ptr::from(cur.as_ref().data))
} else {
from_glib_none(Ptr::from(cur.as_ref().data))
};
if self.transfer != ContainerTransfer::None {
ffi::g_slist_free_1(cur.as_ptr());
}
Some(item)
},
}
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FusedIterator for SList<T>
{
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FromGlibContainer<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList> for SList<T>
{
unsafe fn from_glib_none_num(_ptr: *mut ffi::GSList, _num: usize) -> Self {
unimplemented!()
}
unsafe fn from_glib_container_num(ptr: *mut ffi::GSList, _num: usize) -> Self {
Self::from_glib_container(ptr)
}
unsafe fn from_glib_full_num(ptr: *mut ffi::GSList, _num: usize) -> Self {
Self::from_glib_full(ptr)
}
}
impl<
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FromGlibPtrContainer<<T as GlibPtrDefault>::GlibType, *mut ffi::GSList> for SList<T>
{
unsafe fn from_glib_none(_ptr: *mut ffi::GSList) -> Self {
unimplemented!()
}
unsafe fn from_glib_container(ptr: *mut ffi::GSList) -> Self {
Self::from_glib_container(ptr)
}
unsafe fn from_glib_full(ptr: *mut ffi::GSList) -> Self {
Self::from_glib_full(ptr)
}
}
pub struct SListIter<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> {
ptr: Option<ptr::NonNull<ffi::GSList>>,
phantom: PhantomData<&'a T>,
}
impl<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> SListIter<'a, T>
{
fn new(list: &'a SList<T>) -> SListIter<'a, T> {
assert_eq!(
mem::size_of::<T>(),
mem::size_of::<<T as GlibPtrDefault>::GlibType>()
);
SListIter {
ptr: list.ptr,
phantom: PhantomData,
}
}
}
impl<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> Iterator for SListIter<'a, T>
{
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
match self.ptr {
None => None,
Some(cur) => unsafe {
self.ptr = ptr::NonNull::new(cur.as_ref().next);
let item = &*(&cur.as_ref().data as *const ffi::gpointer as *const T);
Some(item)
},
}
}
}
impl<
'a,
T: GlibPtrDefault
+ FromGlibPtrFull<<T as GlibPtrDefault>::GlibType>
+ FromGlibPtrNone<<T as GlibPtrDefault>::GlibType>,
> FusedIterator for SListIter<'a, T>
{
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn slice() {
let items = [
crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap(),
];
let slice = unsafe {
let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut ffi::GDate;
ptr::write(ptr.add(0), *items[0].to_glib_none().0);
ptr::write(ptr.add(1), *items[1].to_glib_none().0);
ptr::write(ptr.add(2), *items[2].to_glib_none().0);
ptr::write(ptr.add(3), *items[3].to_glib_none().0);
Slice::<crate::Date>::from_glib_full_num(ptr as *mut crate::Date, 4)
};
assert_eq!(&items[..], &*slice);
}
#[test]
fn ptr_slice() {
let items = [
crate::Error::new(crate::FileError::Failed, "Failed 1"),
crate::Error::new(crate::FileError::Noent, "Failed 2"),
crate::Error::new(crate::FileError::Io, "Failed 3"),
crate::Error::new(crate::FileError::Perm, "Failed 4"),
];
let slice = unsafe {
let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut *mut ffi::GError;
ptr::write(ptr.add(0), items[0].to_glib_full() as *mut _);
ptr::write(ptr.add(1), items[1].to_glib_full() as *mut _);
ptr::write(ptr.add(2), items[2].to_glib_full() as *mut _);
ptr::write(ptr.add(3), items[3].to_glib_full() as *mut _);
PtrSlice::<crate::Error>::from_glib_full_num(ptr, 4)
};
for (a, b) in Iterator::zip(items.iter(), slice.iter()) {
assert_eq!(a.message(), b.message());
assert_eq!(
a.kind::<crate::FileError>().unwrap(),
b.kind::<crate::FileError>().unwrap()
);
}
}
#[test]
fn list() {
let items = [
crate::DateTime::from_utc(2021, 11, 20, 23, 41, 12.0).unwrap(),
crate::DateTime::from_utc(2021, 11, 20, 23, 41, 13.0).unwrap(),
crate::DateTime::from_utc(2021, 11, 20, 23, 41, 14.0).unwrap(),
crate::DateTime::from_utc(2021, 11, 20, 23, 41, 15.0).unwrap(),
];
let list = unsafe {
let mut list = ffi::g_list_append(
ptr::null_mut(),
ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[0]) as ffi::gpointer,
);
list = ffi::g_list_append(
list,
ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[1]) as ffi::gpointer,
);
list = ffi::g_list_append(
list,
ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[2]) as ffi::gpointer,
);
list = ffi::g_list_append(
list,
ToGlibPtr::<*mut ffi::GDateTime>::to_glib_full(&items[3]) as ffi::gpointer,
);
List::<crate::DateTime>::from_glib_full(list)
};
assert!(!list.is_empty());
let list_items = list.iter().cloned().collect::<Vec<_>>();
assert_eq!(&items[..], &list_items);
let list_items = list.collect::<Vec<_>>();
assert_eq!(&items[..], &list_items);
let list = unsafe { List::<crate::DateTime>::from_glib_full(ptr::null_mut()) };
assert!(list.is_empty());
}
#[test]
fn slist() {
let items = [
crate::Object::with_type(crate::Type::OBJECT, &[]),
crate::Object::with_type(crate::Type::OBJECT, &[]),
crate::Object::with_type(crate::Type::OBJECT, &[]),
crate::Object::with_type(crate::Type::OBJECT, &[]),
];
let list = unsafe {
let mut list = ffi::g_slist_append(
ptr::null_mut(),
<crate::Object as ToGlibPtr<*mut gobject_ffi::GObject>>::to_glib_full(&items[0])
as ffi::gpointer,
);
list = ffi::g_slist_append(
list,
<crate::Object as ToGlibPtr<*mut gobject_ffi::GObject>>::to_glib_full(&items[1])
as ffi::gpointer,
);
list = ffi::g_slist_append(
list,
<crate::Object as ToGlibPtr<*mut gobject_ffi::GObject>>::to_glib_full(&items[2])
as ffi::gpointer,
);
list = ffi::g_slist_append(
list,
<crate::Object as ToGlibPtr<*mut gobject_ffi::GObject>>::to_glib_full(&items[3])
as ffi::gpointer,
);
SList::<crate::Object>::from_glib_full(list)
};
assert!(!list.is_empty());
let list_items = list.iter().cloned().collect::<Vec<_>>();
assert_eq!(&items[..], &list_items);
let list_items = list.collect::<Vec<_>>();
assert_eq!(&items[..], &list_items);
let list = unsafe { SList::<crate::Object>::from_glib_full(ptr::null_mut()) };
assert!(list.is_empty());
}
}