1#[cfg(feature = "futures")]
6use futures::future;
7use gio_sys;
8use glib;
9use glib::object::Cast;
10use glib::object::IsA;
11use glib::signal::connect_raw;
12use glib::signal::SignalHandlerId;
13use glib::translate::*;
14use glib::StaticType;
15use glib::Value;
16use glib_sys;
17use gobject_sys;
18use std::boxed::Box as Box_;
19use std::fmt;
20use std::mem::transmute;
21use std::ptr;
22use Cancellable;
23use Error;
24use InputStream;
25use OutputStream;
26
27glib_wrapper! {
28 pub struct IOStream(Object<gio_sys::GIOStream, gio_sys::GIOStreamClass, IOStreamClass>);
29
30 match fn {
31 get_type => || gio_sys::g_io_stream_get_type(),
32 }
33}
34
35impl IOStream {}
36
37pub const NONE_IO_STREAM: Option<&IOStream> = None;
38
39pub trait IOStreamExt: 'static {
40 fn clear_pending(&self);
41
42 fn close<P: IsA<Cancellable>>(&self, cancellable: Option<&P>) -> Result<(), Error>;
43
44 fn close_async<P: IsA<Cancellable>, Q: FnOnce(Result<(), Error>) + Send + 'static>(
45 &self,
46 io_priority: glib::Priority,
47 cancellable: Option<&P>,
48 callback: Q,
49 );
50
51 #[cfg(feature = "futures")]
52 fn close_async_future(
53 &self,
54 io_priority: glib::Priority,
55 ) -> Box_<dyn future::Future<Output = Result<(), Error>> + std::marker::Unpin>;
56
57 fn get_input_stream(&self) -> Option<InputStream>;
58
59 fn get_output_stream(&self) -> Option<OutputStream>;
60
61 fn has_pending(&self) -> bool;
62
63 fn is_closed(&self) -> bool;
64
65 fn set_pending(&self) -> Result<(), Error>;
66
67 fn get_property_closed(&self) -> bool;
68
69 fn connect_property_closed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
70}
71
72impl<O: IsA<IOStream>> IOStreamExt for O {
73 fn clear_pending(&self) {
74 unsafe {
75 gio_sys::g_io_stream_clear_pending(self.as_ref().to_glib_none().0);
76 }
77 }
78
79 fn close<P: IsA<Cancellable>>(&self, cancellable: Option<&P>) -> Result<(), Error> {
80 unsafe {
81 let mut error = ptr::null_mut();
82 let _ = gio_sys::g_io_stream_close(
83 self.as_ref().to_glib_none().0,
84 cancellable.map(|p| p.as_ref()).to_glib_none().0,
85 &mut error,
86 );
87 if error.is_null() {
88 Ok(())
89 } else {
90 Err(from_glib_full(error))
91 }
92 }
93 }
94
95 fn close_async<P: IsA<Cancellable>, Q: FnOnce(Result<(), Error>) + Send + 'static>(
96 &self,
97 io_priority: glib::Priority,
98 cancellable: Option<&P>,
99 callback: Q,
100 ) {
101 let user_data: Box<Q> = Box::new(callback);
102 unsafe extern "C" fn close_async_trampoline<
103 Q: FnOnce(Result<(), Error>) + Send + 'static,
104 >(
105 _source_object: *mut gobject_sys::GObject,
106 res: *mut gio_sys::GAsyncResult,
107 user_data: glib_sys::gpointer,
108 ) {
109 let mut error = ptr::null_mut();
110 let _ = gio_sys::g_io_stream_close_finish(_source_object as *mut _, res, &mut error);
111 let result = if error.is_null() {
112 Ok(())
113 } else {
114 Err(from_glib_full(error))
115 };
116 let callback: Box<Q> = Box::from_raw(user_data as *mut _);
117 callback(result);
118 }
119 let callback = close_async_trampoline::<Q>;
120 unsafe {
121 gio_sys::g_io_stream_close_async(
122 self.as_ref().to_glib_none().0,
123 io_priority.to_glib(),
124 cancellable.map(|p| p.as_ref()).to_glib_none().0,
125 Some(callback),
126 Box::into_raw(user_data) as *mut _,
127 );
128 }
129 }
130
131 #[cfg(feature = "futures")]
132 fn close_async_future(
133 &self,
134 io_priority: glib::Priority,
135 ) -> Box_<dyn future::Future<Output = Result<(), Error>> + std::marker::Unpin> {
136 use fragile::Fragile;
137 use GioFuture;
138
139 GioFuture::new(self, move |obj, send| {
140 let cancellable = Cancellable::new();
141 let send = Fragile::new(send);
142 obj.close_async(io_priority, Some(&cancellable), move |res| {
143 let _ = send.into_inner().send(res);
144 });
145
146 cancellable
147 })
148 }
149
150 fn get_input_stream(&self) -> Option<InputStream> {
151 unsafe {
152 from_glib_none(gio_sys::g_io_stream_get_input_stream(
153 self.as_ref().to_glib_none().0,
154 ))
155 }
156 }
157
158 fn get_output_stream(&self) -> Option<OutputStream> {
159 unsafe {
160 from_glib_none(gio_sys::g_io_stream_get_output_stream(
161 self.as_ref().to_glib_none().0,
162 ))
163 }
164 }
165
166 fn has_pending(&self) -> bool {
167 unsafe {
168 from_glib(gio_sys::g_io_stream_has_pending(
169 self.as_ref().to_glib_none().0,
170 ))
171 }
172 }
173
174 fn is_closed(&self) -> bool {
175 unsafe {
176 from_glib(gio_sys::g_io_stream_is_closed(
177 self.as_ref().to_glib_none().0,
178 ))
179 }
180 }
181
182 fn set_pending(&self) -> Result<(), Error> {
183 unsafe {
184 let mut error = ptr::null_mut();
185 let _ = gio_sys::g_io_stream_set_pending(self.as_ref().to_glib_none().0, &mut error);
186 if error.is_null() {
187 Ok(())
188 } else {
189 Err(from_glib_full(error))
190 }
191 }
192 }
193
194 fn get_property_closed(&self) -> bool {
195 unsafe {
196 let mut value = Value::from_type(<bool as StaticType>::static_type());
197 gobject_sys::g_object_get_property(
198 self.to_glib_none().0 as *mut gobject_sys::GObject,
199 b"closed\0".as_ptr() as *const _,
200 value.to_glib_none_mut().0,
201 );
202 value.get().unwrap()
203 }
204 }
205
206 fn connect_property_closed_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
207 unsafe extern "C" fn notify_closed_trampoline<P, F: Fn(&P) + 'static>(
208 this: *mut gio_sys::GIOStream,
209 _param_spec: glib_sys::gpointer,
210 f: glib_sys::gpointer,
211 ) where
212 P: IsA<IOStream>,
213 {
214 let f: &F = &*(f as *const F);
215 f(&IOStream::from_glib_borrow(this).unsafe_cast())
216 }
217 unsafe {
218 let f: Box_<F> = Box_::new(f);
219 connect_raw(
220 self.as_ptr() as *mut _,
221 b"notify::closed\0".as_ptr() as *const _,
222 Some(transmute(notify_closed_trampoline::<Self, F> as usize)),
223 Box_::into_raw(f),
224 )
225 }
226 }
227}
228
229impl fmt::Display for IOStream {
230 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231 write!(f, "IOStream")
232 }
233}