1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::io;
use std::sync::Arc;
use std::marker::PhantomData;
use error::ErrCode;
use super::{IoObject, IoService, Callback};

pub trait Handler<R> : Sized + Send + 'static {
    type Output;

    fn callback(self, io: &IoService, res: io::Result<R>);

    #[doc(hidden)]
    fn wrap<G>(self, callback: G) -> Callback
        where G: FnOnce(&IoService, ErrCode, Self) + Send + 'static;

    #[doc(hidden)]
    type AsyncResult : AsyncResult<Self::Output>;

    #[doc(hidden)]
    fn async_result(&self) -> Self::AsyncResult;
}

pub trait AsyncResult<R> {
    fn get(self, io: &IoService) -> R;
}

pub struct NoAsyncResult;

impl AsyncResult<()> for NoAsyncResult {
    fn get(self, _io: &IoService) {
    }
}

/// The binding Arc handler.
pub struct ArcHandler<T, F, R> {
    data: Arc<T>,
    handler: F,
    _marker: PhantomData<R>,
}

impl<T, F, R> Handler<R> for ArcHandler<T, F, R>
    where T: IoObject + Send + Sync + 'static,
          F: FnOnce(Arc<T>, io::Result<R>) + Send + 'static,
          R: Send + 'static,
{
    type Output = ();

    fn callback(self, _: &IoService, res: io::Result<R>) {
        let ArcHandler { data, handler, _marker } = self;
        handler(data, res)
    }

    fn wrap<G>(self, callback: G) -> Callback
        where G: FnOnce(&IoService, ErrCode, Self) + Send + 'static
    {
        Box::new(move |io: *const IoService, ec| {
            callback(unsafe { &*io }, ec, self)
        })
        }

    type AsyncResult = NoAsyncResult;

    fn async_result(&self) -> Self::AsyncResult {
        NoAsyncResult
    }
}

/// Provides a `Arc` handler to asynchronous operation.
///
/// The ArcHandler has trait the `Handler`, that type of `Handler::Output` is `()`.
///
/// # Examples
///
/// ```
/// use std::io;
/// use std::sync::Arc;
/// use asyncio::{IoService, wrap};
/// use asyncio::ip::{Tcp, TcpSocket, TcpEndpoint, TcpListener};
///
/// fn on_accept(soc: Arc<TcpListener>, res: io::Result<(TcpSocket, TcpEndpoint)>) {
///   if let Ok((acc, ep)) = res {
///     println!("accepted {}", ep)
///   }
/// }
///
/// let io = &IoService::new();
/// let soc = Arc::new(TcpListener::new(io, Tcp::v4()).unwrap());
/// soc.async_accept(wrap(on_accept, &soc));
/// ```
pub fn wrap<T, F, R>(handler: F, data: &Arc<T>) -> ArcHandler<T, F, R>
    where T: IoObject,
{
    ArcHandler {
        data: data.clone(),
        handler: handler,
        _marker: PhantomData,
    }
}