1 // Copyright 2019, The Gtk-rs Project Developers.
2 // See the COPYRIGHT file at the top-level directory of this distribution.
3 // Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5 use gio_sys;
6 use glib_sys;
7
8 use glib::subclass::prelude::*;
9 use glib::translate::*;
10
11 use glib::Error;
12
13 use Cancellable;
14 use InputStream;
15 use OutputStream;
16 use OutputStreamClass;
17 use OutputStreamSpliceFlags;
18
19 use std::mem;
20 use std::ptr;
21
22 pub trait OutputStreamImpl: OutputStreamImplExt + Send + 'static {
write( &self, stream: &OutputStream, buffer: &[u8], cancellable: Option<&Cancellable>, ) -> Result<usize, Error>23 fn write(
24 &self,
25 stream: &OutputStream,
26 buffer: &[u8],
27 cancellable: Option<&Cancellable>,
28 ) -> Result<usize, Error> {
29 self.parent_write(stream, buffer, cancellable)
30 }
31
close(&self, stream: &OutputStream, cancellable: Option<&Cancellable>) -> Result<(), Error>32 fn close(&self, stream: &OutputStream, cancellable: Option<&Cancellable>) -> Result<(), Error> {
33 self.parent_close(stream, cancellable)
34 }
35
flush(&self, stream: &OutputStream, cancellable: Option<&Cancellable>) -> Result<(), Error>36 fn flush(&self, stream: &OutputStream, cancellable: Option<&Cancellable>) -> Result<(), Error> {
37 self.parent_flush(stream, cancellable)
38 }
39
splice( &self, stream: &OutputStream, input_stream: &InputStream, flags: OutputStreamSpliceFlags, cancellable: Option<&Cancellable>, ) -> Result<usize, Error>40 fn splice(
41 &self,
42 stream: &OutputStream,
43 input_stream: &InputStream,
44 flags: OutputStreamSpliceFlags,
45 cancellable: Option<&Cancellable>,
46 ) -> Result<usize, Error> {
47 self.parent_splice(stream, input_stream, flags, cancellable)
48 }
49 }
50
51 pub trait OutputStreamImplExt {
parent_write( &self, stream: &OutputStream, buffer: &[u8], cancellable: Option<&Cancellable>, ) -> Result<usize, Error>52 fn parent_write(
53 &self,
54 stream: &OutputStream,
55 buffer: &[u8],
56 cancellable: Option<&Cancellable>,
57 ) -> Result<usize, Error>;
58
parent_close( &self, stream: &OutputStream, cancellable: Option<&Cancellable>, ) -> Result<(), Error>59 fn parent_close(
60 &self,
61 stream: &OutputStream,
62 cancellable: Option<&Cancellable>,
63 ) -> Result<(), Error>;
64
parent_flush( &self, stream: &OutputStream, cancellable: Option<&Cancellable>, ) -> Result<(), Error>65 fn parent_flush(
66 &self,
67 stream: &OutputStream,
68 cancellable: Option<&Cancellable>,
69 ) -> Result<(), Error>;
70
parent_splice( &self, stream: &OutputStream, input_stream: &InputStream, flags: OutputStreamSpliceFlags, cancellable: Option<&Cancellable>, ) -> Result<usize, Error>71 fn parent_splice(
72 &self,
73 stream: &OutputStream,
74 input_stream: &InputStream,
75 flags: OutputStreamSpliceFlags,
76 cancellable: Option<&Cancellable>,
77 ) -> Result<usize, Error>;
78 }
79
80 impl<T: OutputStreamImpl + ObjectImpl> OutputStreamImplExt for T {
parent_write( &self, stream: &OutputStream, buffer: &[u8], cancellable: Option<&Cancellable>, ) -> Result<usize, Error>81 fn parent_write(
82 &self,
83 stream: &OutputStream,
84 buffer: &[u8],
85 cancellable: Option<&Cancellable>,
86 ) -> Result<usize, Error> {
87 unsafe {
88 let data = self.get_type_data();
89 let parent_class = data.as_ref().get_parent_class() as *mut gio_sys::GOutputStreamClass;
90 let f = (*parent_class)
91 .write_fn
92 .expect("No parent class implementation for \"write\"");
93 let mut err = ptr::null_mut();
94 let res = f(
95 stream.to_glib_none().0,
96 mut_override(buffer.as_ptr()),
97 buffer.len(),
98 cancellable.to_glib_none().0,
99 &mut err,
100 );
101 if res == -1 {
102 Err(from_glib_full(err))
103 } else {
104 assert!(res >= 0);
105 let res = res as usize;
106 assert!(res <= buffer.len());
107 Ok(res)
108 }
109 }
110 }
111
parent_close( &self, stream: &OutputStream, cancellable: Option<&Cancellable>, ) -> Result<(), Error>112 fn parent_close(
113 &self,
114 stream: &OutputStream,
115 cancellable: Option<&Cancellable>,
116 ) -> Result<(), Error> {
117 unsafe {
118 let data = self.get_type_data();
119 let parent_class = data.as_ref().get_parent_class() as *mut gio_sys::GOutputStreamClass;
120 let mut err = ptr::null_mut();
121 if let Some(f) = (*parent_class).close_fn {
122 if from_glib(f(
123 stream.to_glib_none().0,
124 cancellable.to_glib_none().0,
125 &mut err,
126 )) {
127 Ok(())
128 } else {
129 Err(from_glib_full(err))
130 }
131 } else {
132 Ok(())
133 }
134 }
135 }
136
parent_flush( &self, stream: &OutputStream, cancellable: Option<&Cancellable>, ) -> Result<(), Error>137 fn parent_flush(
138 &self,
139 stream: &OutputStream,
140 cancellable: Option<&Cancellable>,
141 ) -> Result<(), Error> {
142 unsafe {
143 let data = self.get_type_data();
144 let parent_class = data.as_ref().get_parent_class() as *mut gio_sys::GOutputStreamClass;
145 let mut err = ptr::null_mut();
146 if let Some(f) = (*parent_class).flush {
147 if from_glib(f(
148 stream.to_glib_none().0,
149 cancellable.to_glib_none().0,
150 &mut err,
151 )) {
152 Ok(())
153 } else {
154 Err(from_glib_full(err))
155 }
156 } else {
157 Ok(())
158 }
159 }
160 }
161
parent_splice( &self, stream: &OutputStream, input_stream: &InputStream, flags: OutputStreamSpliceFlags, cancellable: Option<&Cancellable>, ) -> Result<usize, Error>162 fn parent_splice(
163 &self,
164 stream: &OutputStream,
165 input_stream: &InputStream,
166 flags: OutputStreamSpliceFlags,
167 cancellable: Option<&Cancellable>,
168 ) -> Result<usize, Error> {
169 unsafe {
170 let data = self.get_type_data();
171 let parent_class = data.as_ref().get_parent_class() as *mut gio_sys::GOutputStreamClass;
172 let mut err = ptr::null_mut();
173 let f = (*parent_class)
174 .splice
175 .expect("No parent class implementation for \"splice\"");
176 let res = f(
177 stream.to_glib_none().0,
178 input_stream.to_glib_none().0,
179 flags.to_glib(),
180 cancellable.to_glib_none().0,
181 &mut err,
182 );
183 if res == -1 {
184 Err(from_glib_full(err))
185 } else {
186 assert!(res >= 0);
187 let res = res as usize;
188 Ok(res)
189 }
190 }
191 }
192 }
193
194 unsafe impl<T: ObjectSubclass + OutputStreamImpl> IsSubclassable<T> for OutputStreamClass {
override_vfuncs(&mut self)195 fn override_vfuncs(&mut self) {
196 <glib::ObjectClass as IsSubclassable<T>>::override_vfuncs(self);
197 unsafe {
198 let klass = &mut *(self as *mut Self as *mut gio_sys::GOutputStreamClass);
199 klass.write_fn = Some(stream_write::<T>);
200 klass.close_fn = Some(stream_close::<T>);
201 klass.flush = Some(stream_flush::<T>);
202 klass.splice = Some(stream_splice::<T>);
203 }
204 }
205 }
206
stream_write<T: ObjectSubclass>( ptr: *mut gio_sys::GOutputStream, buffer: *mut u8, count: usize, cancellable: *mut gio_sys::GCancellable, err: *mut *mut glib_sys::GError, ) -> isize where T: OutputStreamImpl,207 unsafe extern "C" fn stream_write<T: ObjectSubclass>(
208 ptr: *mut gio_sys::GOutputStream,
209 buffer: *mut u8,
210 count: usize,
211 cancellable: *mut gio_sys::GCancellable,
212 err: *mut *mut glib_sys::GError,
213 ) -> isize
214 where
215 T: OutputStreamImpl,
216 {
217 use std::isize;
218 use std::slice;
219
220 assert!(count <= isize::MAX as usize);
221
222 let instance = &*(ptr as *mut T::Instance);
223 let imp = instance.get_impl();
224 let wrap: OutputStream = from_glib_borrow(ptr);
225
226 match imp.write(
227 &wrap,
228 slice::from_raw_parts(buffer as *const u8, count),
229 Option::<Cancellable>::from_glib_borrow(cancellable).as_ref(),
230 ) {
231 Ok(res) => {
232 assert!(res <= isize::MAX as usize);
233 assert!(res <= count);
234 res as isize
235 }
236 Err(mut e) => {
237 *err = e.to_glib_none_mut().0;
238 mem::forget(e);
239 -1
240 }
241 }
242 }
243
stream_close<T: ObjectSubclass>( ptr: *mut gio_sys::GOutputStream, cancellable: *mut gio_sys::GCancellable, err: *mut *mut glib_sys::GError, ) -> glib_sys::gboolean where T: OutputStreamImpl,244 unsafe extern "C" fn stream_close<T: ObjectSubclass>(
245 ptr: *mut gio_sys::GOutputStream,
246 cancellable: *mut gio_sys::GCancellable,
247 err: *mut *mut glib_sys::GError,
248 ) -> glib_sys::gboolean
249 where
250 T: OutputStreamImpl,
251 {
252 let instance = &*(ptr as *mut T::Instance);
253 let imp = instance.get_impl();
254 let wrap: OutputStream = from_glib_borrow(ptr);
255
256 match imp.close(
257 &wrap,
258 Option::<Cancellable>::from_glib_borrow(cancellable).as_ref(),
259 ) {
260 Ok(_) => glib_sys::GTRUE,
261 Err(mut e) => {
262 *err = e.to_glib_none_mut().0;
263 mem::forget(e);
264 glib_sys::GFALSE
265 }
266 }
267 }
268
stream_flush<T: ObjectSubclass>( ptr: *mut gio_sys::GOutputStream, cancellable: *mut gio_sys::GCancellable, err: *mut *mut glib_sys::GError, ) -> glib_sys::gboolean where T: OutputStreamImpl,269 unsafe extern "C" fn stream_flush<T: ObjectSubclass>(
270 ptr: *mut gio_sys::GOutputStream,
271 cancellable: *mut gio_sys::GCancellable,
272 err: *mut *mut glib_sys::GError,
273 ) -> glib_sys::gboolean
274 where
275 T: OutputStreamImpl,
276 {
277 let instance = &*(ptr as *mut T::Instance);
278 let imp = instance.get_impl();
279 let wrap: OutputStream = from_glib_borrow(ptr);
280
281 match imp.flush(
282 &wrap,
283 Option::<Cancellable>::from_glib_borrow(cancellable).as_ref(),
284 ) {
285 Ok(_) => glib_sys::GTRUE,
286 Err(mut e) => {
287 *err = e.to_glib_none_mut().0;
288 mem::forget(e);
289 glib_sys::GFALSE
290 }
291 }
292 }
293
stream_splice<T: ObjectSubclass>( ptr: *mut gio_sys::GOutputStream, input_stream: *mut gio_sys::GInputStream, flags: gio_sys::GOutputStreamSpliceFlags, cancellable: *mut gio_sys::GCancellable, err: *mut *mut glib_sys::GError, ) -> isize where T: OutputStreamImpl,294 unsafe extern "C" fn stream_splice<T: ObjectSubclass>(
295 ptr: *mut gio_sys::GOutputStream,
296 input_stream: *mut gio_sys::GInputStream,
297 flags: gio_sys::GOutputStreamSpliceFlags,
298 cancellable: *mut gio_sys::GCancellable,
299 err: *mut *mut glib_sys::GError,
300 ) -> isize
301 where
302 T: OutputStreamImpl,
303 {
304 let instance = &*(ptr as *mut T::Instance);
305 let imp = instance.get_impl();
306 let wrap: OutputStream = from_glib_borrow(ptr);
307
308 match imp.splice(
309 &wrap,
310 &from_glib_borrow(input_stream),
311 from_glib(flags),
312 Option::<Cancellable>::from_glib_borrow(cancellable).as_ref(),
313 ) {
314 Ok(res) => {
315 use std::isize;
316 assert!(res <= isize::MAX as usize);
317 res as isize
318 }
319 Err(mut e) => {
320 *err = e.to_glib_none_mut().0;
321 mem::forget(e);
322 -1
323 }
324 }
325 }
326
327 #[cfg(test)]
328 mod tests {
329 use super::*;
330 use crate::prelude::*;
331 use glib;
332 use glib::subclass;
333 use std::cell::RefCell;
334
335 struct SimpleOutputStream {
336 sum: RefCell<usize>,
337 }
338
339 impl ObjectSubclass for SimpleOutputStream {
340 const NAME: &'static str = "SimpleOutputStream";
341 type ParentType = OutputStream;
342 type Instance = subclass::simple::InstanceStruct<Self>;
343 type Class = subclass::simple::ClassStruct<Self>;
344
345 glib_object_subclass!();
346
new() -> Self347 fn new() -> Self {
348 Self {
349 sum: RefCell::new(0),
350 }
351 }
352 }
353
354 impl ObjectImpl for SimpleOutputStream {
355 glib_object_impl!();
356 }
357
358 impl OutputStreamImpl for SimpleOutputStream {
write( &self, _stream: &OutputStream, buffer: &[u8], _cancellable: Option<&Cancellable>, ) -> Result<usize, Error>359 fn write(
360 &self,
361 _stream: &OutputStream,
362 buffer: &[u8],
363 _cancellable: Option<&Cancellable>,
364 ) -> Result<usize, Error> {
365 let mut sum = self.sum.borrow_mut();
366 for b in buffer {
367 *sum += *b as usize;
368 }
369
370 Ok(buffer.len())
371 }
372 }
373
374 #[test]
test_simple_stream()375 fn test_simple_stream() {
376 let stream = glib::Object::new(SimpleOutputStream::get_type(), &[])
377 .unwrap()
378 .downcast::<::OutputStream>()
379 .unwrap();
380
381 assert_eq!(*SimpleOutputStream::from_instance(&stream).sum.borrow(), 0);
382 assert_eq!(
383 stream.write(&[1, 2, 3, 4, 5], crate::NONE_CANCELLABLE),
384 Ok(5)
385 );
386 assert_eq!(*SimpleOutputStream::from_instance(&stream).sum.borrow(), 15);
387 }
388 }
389