gio/subclass/
seekable.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::ptr;
4
5use glib::{prelude::*, subclass::prelude::*, translate::*, Error, SeekType};
6
7use crate::{ffi, Cancellable, Seekable};
8
9pub trait SeekableImpl: ObjectImpl + Send {
10    fn tell(&self) -> i64;
11    fn can_seek(&self) -> bool;
12    fn seek(
13        &self,
14        offset: i64,
15        type_: SeekType,
16        cancellable: Option<&Cancellable>,
17    ) -> Result<(), Error>;
18    fn can_truncate(&self) -> bool;
19    fn truncate(&self, offset: i64, cancellable: Option<&Cancellable>) -> Result<(), Error>;
20}
21
22mod sealed {
23    pub trait Sealed {}
24    impl<T: super::SeekableImplExt> Sealed for T {}
25}
26
27pub trait SeekableImplExt: sealed::Sealed + ObjectSubclass {
28    fn parent_tell(&self) -> i64 {
29        unsafe {
30            let type_data = Self::type_data();
31            let parent_iface =
32                type_data.as_ref().parent_interface::<Seekable>() as *const ffi::GSeekableIface;
33
34            let func = (*parent_iface)
35                .tell
36                .expect("no parent \"tell\" implementation");
37            func(self.obj().unsafe_cast_ref::<Seekable>().to_glib_none().0)
38        }
39    }
40
41    fn parent_can_seek(&self) -> bool {
42        unsafe {
43            let type_data = Self::type_data();
44            let parent_iface =
45                type_data.as_ref().parent_interface::<Seekable>() as *const ffi::GSeekableIface;
46
47            let func = (*parent_iface)
48                .can_seek
49                .expect("no parent \"can_seek\" implementation");
50            let ret = func(self.obj().unsafe_cast_ref::<Seekable>().to_glib_none().0);
51            from_glib(ret)
52        }
53    }
54
55    fn parent_seek(
56        &self,
57        offset: i64,
58        type_: SeekType,
59        cancellable: Option<&Cancellable>,
60    ) -> Result<(), Error> {
61        unsafe {
62            let type_data = Self::type_data();
63            let parent_iface =
64                type_data.as_ref().parent_interface::<Seekable>() as *const ffi::GSeekableIface;
65
66            let func = (*parent_iface)
67                .seek
68                .expect("no parent \"seek\" implementation");
69
70            let mut err = ptr::null_mut();
71            func(
72                self.obj().unsafe_cast_ref::<Seekable>().to_glib_none().0,
73                offset,
74                type_.into_glib(),
75                cancellable.to_glib_none().0,
76                &mut err,
77            );
78
79            if err.is_null() {
80                Ok(())
81            } else {
82                Err(from_glib_full(err))
83            }
84        }
85    }
86
87    fn parent_can_truncate(&self) -> bool {
88        unsafe {
89            let type_data = Self::type_data();
90            let parent_iface =
91                type_data.as_ref().parent_interface::<Seekable>() as *const ffi::GSeekableIface;
92
93            let func = (*parent_iface)
94                .can_truncate
95                .expect("no parent \"can_truncate\" implementation");
96            let ret = func(self.obj().unsafe_cast_ref::<Seekable>().to_glib_none().0);
97            from_glib(ret)
98        }
99    }
100
101    fn parent_truncate(&self, offset: i64, cancellable: Option<&Cancellable>) -> Result<(), Error> {
102        unsafe {
103            let type_data = Self::type_data();
104            let parent_iface =
105                type_data.as_ref().parent_interface::<Seekable>() as *const ffi::GSeekableIface;
106
107            let func = (*parent_iface)
108                .truncate_fn
109                .expect("no parent \"truncate\" implementation");
110
111            let mut err = ptr::null_mut();
112            func(
113                self.obj().unsafe_cast_ref::<Seekable>().to_glib_none().0,
114                offset,
115                cancellable.to_glib_none().0,
116                &mut err,
117            );
118
119            if err.is_null() {
120                Ok(())
121            } else {
122                Err(from_glib_full(err))
123            }
124        }
125    }
126}
127
128impl<T: SeekableImpl> SeekableImplExt for T {}
129
130unsafe impl<T: SeekableImpl> IsImplementable<T> for Seekable {
131    fn interface_init(iface: &mut glib::Interface<Self>) {
132        let iface = iface.as_mut();
133
134        iface.tell = Some(seekable_tell::<T>);
135        iface.can_seek = Some(seekable_can_seek::<T>);
136        iface.seek = Some(seekable_seek::<T>);
137        iface.can_truncate = Some(seekable_can_truncate::<T>);
138        iface.truncate_fn = Some(seekable_truncate::<T>);
139    }
140}
141
142unsafe extern "C" fn seekable_tell<T: SeekableImpl>(seekable: *mut ffi::GSeekable) -> i64 {
143    let instance = &*(seekable as *mut T::Instance);
144    let imp = instance.imp();
145
146    imp.tell()
147}
148
149unsafe extern "C" fn seekable_can_seek<T: SeekableImpl>(
150    seekable: *mut ffi::GSeekable,
151) -> glib::ffi::gboolean {
152    let instance = &*(seekable as *mut T::Instance);
153    let imp = instance.imp();
154
155    imp.can_seek().into_glib()
156}
157
158unsafe extern "C" fn seekable_seek<T: SeekableImpl>(
159    seekable: *mut ffi::GSeekable,
160    offset: i64,
161    type_: glib::ffi::GSeekType,
162    cancellable: *mut ffi::GCancellable,
163    err: *mut *mut glib::ffi::GError,
164) -> glib::ffi::gboolean {
165    let instance = &*(seekable as *mut T::Instance);
166    let imp = instance.imp();
167
168    match imp.seek(
169        offset,
170        from_glib(type_),
171        Option::<Cancellable>::from_glib_borrow(cancellable)
172            .as_ref()
173            .as_ref(),
174    ) {
175        Ok(()) => glib::ffi::GTRUE,
176        Err(e) => {
177            if !err.is_null() {
178                *err = e.into_glib_ptr();
179            }
180            glib::ffi::GFALSE
181        }
182    }
183}
184
185unsafe extern "C" fn seekable_can_truncate<T: SeekableImpl>(
186    seekable: *mut ffi::GSeekable,
187) -> glib::ffi::gboolean {
188    let instance = &*(seekable as *mut T::Instance);
189    let imp = instance.imp();
190
191    imp.can_truncate().into_glib()
192}
193
194unsafe extern "C" fn seekable_truncate<T: SeekableImpl>(
195    seekable: *mut ffi::GSeekable,
196    offset: i64,
197    cancellable: *mut ffi::GCancellable,
198    err: *mut *mut glib::ffi::GError,
199) -> glib::ffi::gboolean {
200    let instance = &*(seekable as *mut T::Instance);
201    let imp = instance.imp();
202
203    match imp.truncate(
204        offset,
205        Option::<Cancellable>::from_glib_borrow(cancellable)
206            .as_ref()
207            .as_ref(),
208    ) {
209        Ok(()) => glib::ffi::GTRUE,
210        Err(e) => {
211            if !err.is_null() {
212                *err = e.into_glib_ptr();
213            }
214            glib::ffi::GFALSE
215        }
216    }
217}