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::{Error, SeekType, prelude::*, subclass::prelude::*, translate::*};
6
7use crate::{Cancellable, Seekable, ffi};
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    unsafe {
139        let instance = &*(seekable as *mut T::Instance);
140        let imp = instance.imp();
141
142        imp.tell()
143    }
144}
145
146unsafe extern "C" fn seekable_can_seek<T: SeekableImpl>(
147    seekable: *mut ffi::GSeekable,
148) -> glib::ffi::gboolean {
149    unsafe {
150        let instance = &*(seekable as *mut T::Instance);
151        let imp = instance.imp();
152
153        imp.can_seek().into_glib()
154    }
155}
156
157unsafe extern "C" fn seekable_seek<T: SeekableImpl>(
158    seekable: *mut ffi::GSeekable,
159    offset: i64,
160    type_: glib::ffi::GSeekType,
161    cancellable: *mut ffi::GCancellable,
162    err: *mut *mut glib::ffi::GError,
163) -> glib::ffi::gboolean {
164    unsafe {
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}
185
186unsafe extern "C" fn seekable_can_truncate<T: SeekableImpl>(
187    seekable: *mut ffi::GSeekable,
188) -> glib::ffi::gboolean {
189    unsafe {
190        let instance = &*(seekable as *mut T::Instance);
191        let imp = instance.imp();
192
193        imp.can_truncate().into_glib()
194    }
195}
196
197unsafe extern "C" fn seekable_truncate<T: SeekableImpl>(
198    seekable: *mut ffi::GSeekable,
199    offset: i64,
200    cancellable: *mut ffi::GCancellable,
201    err: *mut *mut glib::ffi::GError,
202) -> glib::ffi::gboolean {
203    unsafe {
204        let instance = &*(seekable as *mut T::Instance);
205        let imp = instance.imp();
206
207        match imp.truncate(
208            offset,
209            Option::<Cancellable>::from_glib_borrow(cancellable)
210                .as_ref()
211                .as_ref(),
212        ) {
213            Ok(()) => glib::ffi::GTRUE,
214            Err(e) => {
215                if !err.is_null() {
216                    *err = e.into_glib_ptr();
217                }
218                glib::ffi::GFALSE
219            }
220        }
221    }
222}