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