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> {
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 debug_assert!(count <= isize::MAX as usize);
144
145 let instance = &*(ptr as *mut T::Instance);
146 let imp = instance.imp();
147
148 match imp.read(
149 if count == 0 {
150 &mut []
151 } else {
152 std::slice::from_raw_parts_mut(buffer as *mut u8, count)
153 },
154 Option::<Cancellable>::from_glib_borrow(cancellable)
155 .as_ref()
156 .as_ref(),
157 ) {
158 Ok(res) => {
159 assert!(res <= isize::MAX as usize);
160 assert!(res <= count);
161 res as isize
162 }
163 Err(e) => {
164 if !err.is_null() {
165 *err = e.into_glib_ptr();
166 }
167 -1
168 }
169 }
170}
171
172unsafe extern "C" fn stream_close<T: InputStreamImpl>(
173 ptr: *mut ffi::GInputStream,
174 cancellable: *mut ffi::GCancellable,
175 err: *mut *mut glib::ffi::GError,
176) -> glib::ffi::gboolean {
177 let instance = &*(ptr as *mut T::Instance);
178 let imp = instance.imp();
179
180 match imp.close(
181 Option::<Cancellable>::from_glib_borrow(cancellable)
182 .as_ref()
183 .as_ref(),
184 ) {
185 Ok(_) => glib::ffi::GTRUE,
186 Err(e) => {
187 if !err.is_null() {
188 *err = e.into_glib_ptr();
189 }
190 glib::ffi::GFALSE
191 }
192 }
193}
194
195unsafe extern "C" fn stream_skip<T: InputStreamImpl>(
196 ptr: *mut ffi::GInputStream,
197 count: usize,
198 cancellable: *mut ffi::GCancellable,
199 err: *mut *mut glib::ffi::GError,
200) -> isize {
201 debug_assert!(count <= isize::MAX as usize);
202
203 let instance = &*(ptr as *mut T::Instance);
204 let imp = instance.imp();
205
206 match imp.skip(
207 count,
208 Option::<Cancellable>::from_glib_borrow(cancellable)
209 .as_ref()
210 .as_ref(),
211 ) {
212 Ok(res) => {
213 assert!(res <= isize::MAX as usize);
214 assert!(res <= count);
215 res as isize
216 }
217 Err(e) => {
218 if !err.is_null() {
219 *err = e.into_glib_ptr();
220 }
221 -1
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use std::cell::RefCell;
229
230 use super::*;
231 use crate::{prelude::*, subclass::prelude::*};
232
233 mod imp {
234 use super::*;
235
236 #[derive(Default)]
237 pub struct SimpleInputStream {
238 pub pos: RefCell<usize>,
239 }
240
241 #[glib::object_subclass]
242 impl ObjectSubclass for SimpleInputStream {
243 const NAME: &'static str = "SimpleInputStream";
244 type Type = super::SimpleInputStream;
245 type ParentType = InputStream;
246 type Interfaces = (crate::Seekable,);
247 }
248
249 impl ObjectImpl for SimpleInputStream {}
250
251 impl InputStreamImpl for SimpleInputStream {
252 fn read(
253 &self,
254 buffer: &mut [u8],
255 _cancellable: Option<&Cancellable>,
256 ) -> Result<usize, Error> {
257 let mut pos = self.pos.borrow_mut();
258 for b in buffer.iter_mut() {
259 *b = ((*pos) % 255) as u8;
260 *pos += 1;
261 }
262 Ok(buffer.len())
263 }
264 }
265
266 impl SeekableImpl for SimpleInputStream {
267 fn tell(&self) -> i64 {
268 *self.pos.borrow() as i64
269 }
270
271 fn can_seek(&self) -> bool {
272 true
273 }
274
275 fn seek(
276 &self,
277 offset: i64,
278 type_: glib::SeekType,
279 _cancellable: Option<&Cancellable>,
280 ) -> Result<(), glib::Error> {
281 let mut pos = self.pos.borrow_mut();
282 match type_ {
283 glib::SeekType::Set => {
284 *pos = offset as usize;
285 Ok(())
286 }
287 glib::SeekType::Cur => {
288 if offset < 0 {
289 *pos -= (-offset) as usize;
290 } else {
291 *pos += offset as usize;
292 }
293
294 Ok(())
295 }
296 glib::SeekType::End => Err(glib::Error::new(
297 crate::IOErrorEnum::NotSupported,
298 "Can't seek relative to end",
299 )),
300 _ => unreachable!(),
301 }
302 }
303
304 fn can_truncate(&self) -> bool {
305 false
306 }
307 fn truncate(
308 &self,
309 _offset: i64,
310 _cancellable: Option<&Cancellable>,
311 ) -> Result<(), Error> {
312 unimplemented!()
313 }
314 }
315 }
316
317 glib::wrapper! {
318 pub struct SimpleInputStream(ObjectSubclass<imp::SimpleInputStream>)
319 @extends InputStream,
320 @implements crate::Seekable;
321 }
322
323 #[test]
324 fn test_simple_stream() {
325 let stream = glib::Object::new::<SimpleInputStream>();
326
327 let mut buf = [0; 16];
328 assert_eq!(stream.read(&mut buf, crate::Cancellable::NONE), Ok(16));
329 assert_eq!(
330 &buf,
331 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
332 );
333
334 assert_eq!(stream.skip(2, crate::Cancellable::NONE), Ok(2));
335
336 assert_eq!(stream.read(&mut buf, crate::Cancellable::NONE), Ok(16));
337 assert_eq!(
338 &buf,
339 &[18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33]
340 );
341
342 let seekable = stream.dynamic_cast_ref::<crate::Seekable>().unwrap();
343 assert_eq!(seekable.tell(), 34);
344 assert!(seekable.can_seek());
345
346 assert_eq!(
347 seekable.seek(0, glib::SeekType::Set, crate::Cancellable::NONE),
348 Ok(())
349 );
350
351 assert_eq!(seekable.tell(), 0);
352 assert_eq!(stream.read(&mut buf, crate::Cancellable::NONE), Ok(16));
353 assert_eq!(
354 &buf,
355 &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
356 );
357
358 assert_eq!(stream.close(crate::Cancellable::NONE), Ok(()));
359 }
360}