DEV Community

loading...

impl Trait for Fn

x1957
Updated on ・1 min read

用ws-rs的时候,看demo:

connect(HUOBI, |out| {
        out.send(r#"{"event":"addChannel","channel":"ltcbtc_depth"}"#);

        move |msg| {
            println!("Client got message '{}'. ", msg);
            out.close(CloseCode::Normal)
        }
    });

后面返回个 closure,开始以为是啥奇怪的语法呢,msg就拿到了服务端发送的东西,好神奇!

看connect代码:

pub fn connect<U, F, H>(url: U, factory: F) -> Result<()>
where
    U: Borrow<str>,
    F: FnMut(Sender) -> H,
    H: Handler,
{
    let mut ws = WebSocket::new(factory)?;
    let parsed = url::Url::parse(url.borrow()).map_err(|err| {
        Error::new(
            ErrorKind::Internal,
            format!("Unable to parse {} as url due to {:?}", url.borrow(), err),
        )
    })?;
    ws.connect(parsed)?;
    ws.run()?;
    Ok(())
}

我们输入的应该是个 factory,然后通过factory创建了ws。
我们再看看factory定义

/// A trait for creating new WebSocket handlers.
pub trait Factory {
    type Handler: Handler;

    fn connection_made(&mut self, _: Sender) -> Self::Handler;

    #[inline]
    fn on_shutdown(&mut self) {
        debug!("Factory received WebSocket shutdown request.");
    }

    #[inline]
    fn client_connected(&mut self, ws: Sender) -> Self::Handler {
        self.connection_made(ws)
    }

    #[inline]
    fn server_connected(&mut self, ws: Sender) -> Self::Handler {
        self.connection_made(ws)
    }

    #[inline]
    fn connection_lost(&mut self, _: Self::Handler) {}
}

但是我们输入的是个closure啊???

再看看我们输入函数在where的限定

F: FnMut(Sender) -> H
H: Handler

输入是个Sender,返回是个Handler,所以我们demo里面的out是个Sender,返回的

move |msg| {
            println!("Client got message '{}'. ", msg);
            out.close(CloseCode::Normal)
        }

是个Handler.

继续疑问:我输入是个函数呀,怎么就符合Factory这个呢

看看Factory trait里面

impl<F, H> Factory for F
where
    H: Handler,
    F: FnMut(Sender) -> H,
{
    type Handler = H;

    fn connection_made(&mut self, out: Sender) -> H {
        self(out)
    }
}

他给 FnMut(Sender) -> H实现了Factory trait,connection_made也是Factory trait里面唯一没有默认实现的,所以当connection创建之后,就调用我们的这个函数,把out给他,并返回一个Handler。

OK到这儿就只有一个问题了,我们返回的是个closuzre啊,同理。。。也是给这个closuzre实现了Handler trait,看看代码

impl<F> Handler for F
where
    F: Fn(Message) -> Result<()>,
{
    fn on_message(&mut self, msg: Message) -> Result<()> {
        self(msg)
    }
}

同上,on_message也是Handler唯一没有默认实现的了,所以这里这个等于

        move |msg| {
            println!("Client got message '{}'. ", msg);
            out.close(CloseCode::Normal)
        }

Discussion (0)