1use std::ptr;
4
5use glib::{prelude::*, subclass::prelude::*, translate::*, Error};
6
7use crate::{ffi, Cancellable, InputStream};
8
9pub trait InputStreamImpl: Send + ObjectImpl + ObjectSubclass<Type: IsA<InputStream>> {
10 fn read(&self, buffer: &mut [u8], cancellable: Option<&Cancellable>) -> Result<usize, Error> {
11 self.parent_read(buffer, cancellable)
12 }
13
14 fn close(&self, cancellable: Option<&Cancellable>) -> Result<(), Error> {
15 self.parent_close(cancellable)
16 }
17
18 fn skip(&self, count: usize, cancellable: Option<&Cancellable>) -> Result<usize, Error> {
19 self.parent_skip(count, cancellable)
20 }
21}
22
23pub trait InputStreamImplExt: InputStreamImpl {
24 fn parent_read(
25 &self,
26 buffer: &mut [u8],
27 cancellable: Option<&Cancellable>,
28 ) -> Result<usize, Error> {
29 unsafe {
30 let data = Self::type_data();
31 let parent_class = data.as_ref().parent_class() as *mut ffi::GInputStreamClass;
32 let f = (*parent_class)
33 .read_fn
34 .expect("No parent class implementation for \"read\"");
35 let mut err = ptr::null_mut();
36 let res = f(
37 self.obj().unsafe_cast_ref::<InputStream>().to_glib_none().0,
38 buffer.as_mut_ptr() as glib::ffi::gpointer,
39 buffer.len(),
40 cancellable.to_glib_none().0,
41 &mut err,
42 );
43 if res == -1 {
44 Err(from_glib_full(err))
45 } else {
46 debug_assert!(res >= 0);
47 let res = res as usize;
48 debug_assert!(res <= buffer.len());
49 Ok(res)
50 }
51 }
52 }
53
54 fn parent_close(&self, cancellable: Option<&Cancellable>) -> Result<(), Error> {
55 unsafe {
56 let data = Self::type_data();
57 let parent_class = data.as_ref().parent_class() as *mut ffi::GInputStreamClass;
58 let mut err = ptr::null_mut();
59 if let Some(f) = (*parent_class).close_fn {
60 if from_glib(f(
61 self.obj().unsafe_cast_ref::<InputStream>().to_glib_none().0,
62 cancellable.to_glib_none().0,
63 &mut err,
64 )) {
65 Ok(())
66 } else {
67 Err(from_glib_full(err))
68 }
69 } else {
70 Ok(())
71 }
72 }
73 }
74
75 fn parent_skip(&self, count: usize, cancellable: Option<&Cancellable>) -> Result<usize, Error> {
76 unsafe {
77 let data = Self::type_data();
78 let parent_class = data.as_ref().parent_class() as *mut ffi::GInputStreamClass;
79 let mut err = ptr::null_mut();
80 let f = (*parent_class)
81 .skip
82 .expect("No parent class implementation for \"skip\"");
83 let res = f(
84 self.obj().unsafe_cast_ref::<InputStream>().to_glib_none().0,
85 count,
86 cancellable.to_glib_none().0,
87 &mut err,
88 );
89 if res == -1 {
90 Err(from_glib_full(err))
91 } else {
92 debug_assert!(res >= 0);
93 let res = res as usize;
94 debug_assert!(res <= count);
95 Ok(res)
96 }
97 }
98 }
99}
100
101impl<T: InputStreamImpl> InputStreamImplExt for T {}
102
103unsafe impl<T: InputStreamImpl> IsSubclassable<T> for InputStream {
104 fn class_init(class: &mut ::glib::Class<Self>) {
105 Self::parent_class_init::<T>(class);
106
107 let klass = class.as_mut();
108 klass.read_fn = Some(stream_read::<T>);
109 klass.close_fn = Some(stream_close::<T>);
110 klass.skip = Some(stream_skip::<T>);
111 }
112}
113
114unsafe extern "C" fn stream_read<T: InputStreamImpl>(
115 ptr: *mut ffi::GInputStream,
116 buffer: glib::ffi::gpointer,
117 count: usize,
118 cancellable: *mut ffi::GCancellable,
119 err: *mut *mut glib::ffi::GError,
120) -> isize {
121 debug_assert!(count <= isize::MAX as usize);
122
123 let instance = &*(ptr as *mut T::Instance);
124 let imp = instance.imp();
125
126 match imp.read(
127 if count == 0 {
128 &mut []
129 } else {
130 std::slice::from_raw_parts_mut(buffer as *mut u8, count)
131 },
132 Option::<Cancellable>::from_glib_borrow(cancellable)
133 .as_ref()
134 .as_ref(),
135 ) {
136 Ok(res) => {
137 assert!(res <= isize::MAX as usize);
138 assert!(res <= count);
139 res as isize
140 }
141 Err(e) => {
142 if !err.is_null() {
143 *err = e.into_glib_ptr();
144 }
145 -1
146 }
147 }
148}
149
150unsafe extern "C" fn stream_close<T: InputStreamImpl>(
151 ptr: *mut ffi::GInputStream,
152 cancellable: *mut ffi::GCancellable,
153 err: *mut *mut glib::ffi::GError,
154) -> glib::ffi::gboolean {
155 let instance = &*(ptr as *mut T::Instance);
156 let imp = instance.imp();
157
158 match imp.close(
159 Option::<Cancellable>::from_glib_borrow(cancellable)
160 .as_ref()
161 .as_ref(),
162 ) {
163 Ok(_) => glib::ffi::GTRUE,
164 Err(e) => {
165 if !err.is_null() {
166 *err = e.into_glib_ptr();
167 }
168 glib::ffi::GFALSE
169 }
170 }
171}
172
173unsafe extern "C" fn stream_skip<T: InputStreamImpl>(
174 ptr: *mut ffi::GInputStream,
175 count: usize,
176 cancellable: *mut ffi::GCancellable,
177 err: *mut *mut glib::ffi::GError,
178) -> isize {
179 debug_assert!(count <= isize::MAX as usize);
180
181 let instance = &*(ptr as *mut T::Instance);
182 let imp = instance.imp();
183
184 match imp.skip(
185 count,
186 Option::<Cancellable>::from_glib_borrow(cancellable)
187 .as_ref()
188 .as_ref(),
189 ) {
190 Ok(res) => {
191 assert!(res <= isize::MAX as usize);
192 assert!(res <= count);
193 res as isize
194 }
195 Err(e) => {
196 if !err.is_null() {
197 *err = e.into_glib_ptr();
198 }
199 -1
200 }
201 }
202}
203
204#[cfg(test)]
205mod tests {
206 use std::cell::RefCell;
207
208 use super::*;
209 use crate::{prelude::*, subclass::prelude::*};
210
211 mod imp {
212 use super::*;
213
214 #[derive(Default)]
215 pub struct SimpleInputStream {
216 pub pos: RefCell<usize>,
217 }
218
219 #[glib::object_subclass]
220 impl ObjectSubclass for SimpleInputStream {
221 const NAME: &'static str = "SimpleInputStream";
222 type Type = super::SimpleInputStream;
223 type ParentType = InputStream;
224 type Interfaces = (crate::Seekable,);
225 }
226
227 impl ObjectImpl for SimpleInputStream {}
228
229 impl InputStreamImpl for SimpleInputStream {
230 fn read(
231 &self,
232 buffer: &mut [u8],
233 _cancellable: Option<&Cancellable>,
234 ) -> Result<usize, Error> {
235 let mut pos = self.pos.borrow_mut();
236 for b in buffer.iter_mut() {
237 *b = ((*pos) % 255) as u8;
238 *pos += 1;
239 }
240 Ok(buffer.len())
241 }
242 }
243
244 impl SeekableImpl for SimpleInputStream {
245 fn tell(&self) -> i64 {
246 *self.pos.borrow() as i64
247 }
248
249 fn can_seek(&self) -> bool {
250 true
251 }
252
253 fn seek(
254 &self,
255 offset: i64,
256 type_: glib::SeekType,
257 _cancellable: Option<&Cancellable>,
258 ) -> Result<(), glib::Error> {
259 let mut pos = self.pos.borrow_mut();
260 match type_ {
261 glib::SeekType::Set => {
262 *pos = offset as usize;
263 Ok(())
264 }
265 glib::SeekType::Cur => {
266 if offset < 0 {
267 *pos -= (-offset) as usize;
268 } else {
269 *pos += offset as usize;
270 }
271
272 Ok(())
273 }
274 glib::SeekType::End => Err(glib::Error::new(
275 crate::IOErrorEnum::NotSupported,
276 "Can't seek relative to end",
277 )),
278 _ => unreachable!(),
279 }
280 }
281
282 fn can_truncate(&self) -> bool {
283 false
284 }
285 fn truncate(
286 &self,
287 _offset: i64,
288 _cancellable: Option<&Cancellable>,
289 ) -> Result<(), Error> {
290 unimplemented!()
291 }
292 }
293 }
294
295 glib::wrapper! {
296 pub struct SimpleInputStream(ObjectSubclass<imp::SimpleInputStream>)
297 @extends InputStream,
298 @implements crate::Seekable;
299 }
300
301 #[test]
302 fn test_simple_stream() {
303 let stream = glib::Object::new::<SimpleInputStream>();
304
305 let mut buf = [0; 16];
306 assert_eq!(stream.read(&mut buf, crate::Cancellable::NONE), Ok(16));
307 assert_eq!(
308 &buf,
309 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
310 );
311
312 assert_eq!(stream.skip(2, crate::Cancellable::NONE), Ok(2));
313
314 assert_eq!(stream.read(&mut buf, crate::Cancellable::NONE), Ok(16));
315 assert_eq!(
316 &buf,
317 &[18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33]
318 );
319
320 let seekable = stream.dynamic_cast_ref::<crate::Seekable>().unwrap();
321 assert_eq!(seekable.tell(), 34);
322 assert!(seekable.can_seek());
323
324 assert_eq!(
325 seekable.seek(0, glib::SeekType::Set, crate::Cancellable::NONE),
326 Ok(())
327 );
328
329 assert_eq!(seekable.tell(), 0);
330 assert_eq!(stream.read(&mut buf, crate::Cancellable::NONE), Ok(16));
331 assert_eq!(
332 &buf,
333 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
334 );
335
336 assert_eq!(stream.close(crate::Cancellable::NONE), Ok(()));
337 }
338}