Skip to content

Commit 450c249

Browse files
committed
glib: Make glib::Slice API more complete and similar to Vec
1 parent 040ed32 commit 450c249

File tree

7 files changed

+992
-288
lines changed

7 files changed

+992
-288
lines changed

glib/src/collections/mod.rs

Lines changed: 4 additions & 279 deletions
Original file line numberDiff line numberDiff line change
@@ -1,274 +1,21 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

3-
use std::{fmt, iter::FusedIterator, marker::PhantomData, mem, ptr};
3+
use std::{iter::FusedIterator, marker::PhantomData, mem, ptr};
44

55
use crate::translate::*;
66

77
pub mod ptr_slice;
88
pub use ptr_slice::PtrSlice;
99

10+
pub mod slice;
11+
pub use slice::Slice;
12+
1013
#[derive(Debug, PartialEq, Eq)]
1114
enum ContainerTransfer {
1215
Full,
1316
Container,
1417
}
1518

16-
// rustdoc-stripper-ignore-next
17-
/// Slice of elements of type `T` allocated by the GLib allocator.
18-
///
19-
/// This can be used like a `&[T]`.
20-
pub struct Slice<T: 'static> {
21-
ptr: ptr::NonNull<T>,
22-
len: usize,
23-
transfer: ContainerTransfer,
24-
}
25-
26-
unsafe impl<T: Send + 'static> Send for Slice<T> {}
27-
28-
unsafe impl<T: Sync + 'static> Sync for Slice<T> {}
29-
30-
impl<T: fmt::Debug + 'static> fmt::Debug for Slice<T> {
31-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32-
self.as_slice().fmt(f)
33-
}
34-
}
35-
36-
impl<T: PartialEq + 'static> PartialEq for Slice<T> {
37-
fn eq(&self, other: &Self) -> bool {
38-
self.as_slice() == other.as_slice()
39-
}
40-
}
41-
42-
impl<T: Eq + 'static> Eq for Slice<T> {}
43-
44-
impl<T: PartialOrd + 'static> PartialOrd for Slice<T> {
45-
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
46-
self.as_slice().partial_cmp(other.as_slice())
47-
}
48-
}
49-
50-
impl<T: Ord + 'static> Ord for Slice<T> {
51-
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
52-
self.as_slice().cmp(other.as_slice())
53-
}
54-
}
55-
56-
impl<T: std::hash::Hash + 'static> std::hash::Hash for Slice<T> {
57-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
58-
self.as_slice().hash(state)
59-
}
60-
}
61-
62-
impl<T: PartialEq + 'static> PartialEq<[T]> for Slice<T> {
63-
fn eq(&self, other: &[T]) -> bool {
64-
self.as_slice() == other
65-
}
66-
}
67-
68-
impl<T: PartialEq + 'static> PartialEq<Slice<T>> for [T] {
69-
fn eq(&self, other: &Slice<T>) -> bool {
70-
self == other.as_slice()
71-
}
72-
}
73-
74-
impl<T: 'static> Slice<T> {
75-
// rustdoc-stripper-ignore-next
76-
/// Borrows a static C array.
77-
#[inline]
78-
pub unsafe fn from_glib_borrow_num<'a>(ptr: *const T, len: usize) -> &'a [T] {
79-
debug_assert!(!ptr.is_null() || len == 0);
80-
81-
if len == 0 {
82-
&[]
83-
} else {
84-
std::slice::from_raw_parts(ptr, len)
85-
}
86-
}
87-
88-
// rustdoc-stripper-ignore-next
89-
/// Borrows a static mutable C array.
90-
#[inline]
91-
pub unsafe fn from_glib_borrow_num_mut<'a>(ptr: *mut T, len: usize) -> &'a mut [T] {
92-
debug_assert!(!ptr.is_null() || len == 0);
93-
94-
if len == 0 {
95-
&mut []
96-
} else {
97-
std::slice::from_raw_parts_mut(ptr, len)
98-
}
99-
}
100-
101-
// rustdoc-stripper-ignore-next
102-
/// Create a new `Slice` around a C array of which the items are static.
103-
///
104-
/// Must only be called for static items that are never invalidated.
105-
#[inline]
106-
pub unsafe fn from_glib_container_num_static(ptr: *mut T, len: usize) -> Self {
107-
debug_assert!(!ptr.is_null() || len == 0);
108-
109-
Slice {
110-
ptr: if len == 0 {
111-
ffi::g_free(ptr as ffi::gpointer);
112-
ptr::NonNull::dangling()
113-
} else {
114-
ptr::NonNull::new_unchecked(ptr)
115-
},
116-
len,
117-
transfer: ContainerTransfer::Container,
118-
}
119-
}
120-
121-
// rustdoc-stripper-ignore-next
122-
/// Create a new `Slice` around a C array where the items are `Copy`.
123-
#[inline]
124-
pub unsafe fn from_glib_container_num_copy(ptr: *mut T, len: usize) -> Self
125-
where
126-
T: Copy,
127-
{
128-
debug_assert!(!ptr.is_null() || len == 0);
129-
130-
Slice {
131-
ptr: if len == 0 {
132-
ffi::g_free(ptr as ffi::gpointer);
133-
ptr::NonNull::dangling()
134-
} else {
135-
ptr::NonNull::new_unchecked(ptr)
136-
},
137-
len,
138-
transfer: ContainerTransfer::Container,
139-
}
140-
}
141-
142-
// rustdoc-stripper-ignore-next
143-
/// Create a new `Slice` around a C array where the items are borrowed.
144-
#[inline]
145-
pub unsafe fn from_glib_container_num<P: Ptr>(ptr: *mut T, len: usize) -> Self
146-
where
147-
T: FromGlibPtrNone<P>,
148-
{
149-
debug_assert!(!ptr.is_null() || len == 0);
150-
151-
for i in 0..len {
152-
let p = ptr.add(i);
153-
let v = from_glib_none(Ptr::from(p));
154-
ptr::write(p, v);
155-
}
156-
157-
Slice {
158-
ptr: if len == 0 {
159-
ffi::g_free(ptr as ffi::gpointer);
160-
ptr::NonNull::dangling()
161-
} else {
162-
ptr::NonNull::new_unchecked(ptr)
163-
},
164-
len,
165-
transfer: ContainerTransfer::Full,
166-
}
167-
}
168-
169-
// rustdoc-stripper-ignore-next
170-
/// Create a new `Slice` around a C array where the items are `Copy`.
171-
#[inline]
172-
pub unsafe fn from_glib_full_num_copy(ptr: *mut T, len: usize) -> Self
173-
where
174-
T: Copy,
175-
{
176-
debug_assert!(!ptr.is_null() || len == 0);
177-
178-
Slice {
179-
ptr: if len == 0 {
180-
ffi::g_free(ptr as ffi::gpointer);
181-
ptr::NonNull::dangling()
182-
} else {
183-
ptr::NonNull::new_unchecked(ptr)
184-
},
185-
len,
186-
transfer: ContainerTransfer::Container,
187-
}
188-
}
189-
190-
// rustdoc-stripper-ignore-next
191-
/// Create a new `Slice` around a C array.
192-
#[inline]
193-
pub unsafe fn from_glib_full_num(ptr: *mut T, len: usize) -> Self {
194-
debug_assert!(!ptr.is_null() || len == 0);
195-
196-
Slice {
197-
ptr: if len == 0 {
198-
ffi::g_free(ptr as ffi::gpointer);
199-
ptr::NonNull::dangling()
200-
} else {
201-
ptr::NonNull::new_unchecked(ptr)
202-
},
203-
len,
204-
transfer: ContainerTransfer::Full,
205-
}
206-
}
207-
208-
// rustdoc-stripper-ignore-next
209-
/// Borrows this slice as a `&[T]`.
210-
#[inline]
211-
pub fn as_slice(&self) -> &[T] {
212-
self.as_ref()
213-
}
214-
}
215-
216-
impl<T: 'static> Drop for Slice<T> {
217-
#[inline]
218-
fn drop(&mut self) {
219-
unsafe {
220-
if self.transfer == ContainerTransfer::Full && mem::needs_drop::<T>() {
221-
for i in 0..self.len {
222-
ptr::drop_in_place::<T>(self.ptr.as_ptr().add(i));
223-
}
224-
}
225-
226-
if self.len != 0 {
227-
ffi::g_free(self.ptr.as_ptr() as ffi::gpointer);
228-
}
229-
}
230-
}
231-
}
232-
233-
impl<T: 'static> AsRef<[T]> for Slice<T> {
234-
#[inline]
235-
fn as_ref(&self) -> &[T] {
236-
unsafe {
237-
if self.len == 0 {
238-
&[]
239-
} else {
240-
std::slice::from_raw_parts(self.ptr.as_ptr() as *const T, self.len)
241-
}
242-
}
243-
}
244-
}
245-
246-
impl<T: 'static> std::ops::Deref for Slice<T> {
247-
type Target = [T];
248-
249-
#[inline]
250-
fn deref(&self) -> &[T] {
251-
self.as_ref()
252-
}
253-
}
254-
255-
// FIXME: Ideally FromGlibPtrNone would not be needed for from_glib_full()
256-
impl<T: FromGlibPtrNone<*mut T> + 'static> FromGlibContainer<T, *mut T> for Slice<T> {
257-
unsafe fn from_glib_none_num(_ptr: *mut T, _num: usize) -> Self {
258-
unimplemented!()
259-
}
260-
261-
#[inline]
262-
unsafe fn from_glib_container_num(ptr: *mut T, num: usize) -> Self {
263-
Self::from_glib_container_num(ptr, num)
264-
}
265-
266-
#[inline]
267-
unsafe fn from_glib_full_num(ptr: *mut T, num: usize) -> Self {
268-
Self::from_glib_full_num(ptr, num)
269-
}
270-
}
271-
27219
// rustdoc-stripper-ignore-next
27320
/// A list of items of type `T`.
27421
///
@@ -793,28 +540,6 @@ impl<
793540
mod test {
794541
use super::*;
795542

796-
#[test]
797-
fn slice() {
798-
let items = [
799-
crate::Date::from_dmy(20, crate::DateMonth::November, 2021).unwrap(),
800-
crate::Date::from_dmy(21, crate::DateMonth::November, 2021).unwrap(),
801-
crate::Date::from_dmy(22, crate::DateMonth::November, 2021).unwrap(),
802-
crate::Date::from_dmy(23, crate::DateMonth::November, 2021).unwrap(),
803-
];
804-
805-
let slice = unsafe {
806-
let ptr = ffi::g_malloc(mem::size_of::<ffi::GDate>() * 4) as *mut ffi::GDate;
807-
ptr::write(ptr.add(0), *items[0].to_glib_none().0);
808-
ptr::write(ptr.add(1), *items[1].to_glib_none().0);
809-
ptr::write(ptr.add(2), *items[2].to_glib_none().0);
810-
ptr::write(ptr.add(3), *items[3].to_glib_none().0);
811-
812-
Slice::<crate::Date>::from_glib_full_num(ptr as *mut crate::Date, 4)
813-
};
814-
815-
assert_eq!(&items[..], &*slice);
816-
}
817-
818543
#[test]
819544
// checker-ignore-item
820545
fn list() {

0 commit comments

Comments
 (0)