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