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