DEV Community

x1957
x1957

Posted on • Edited on

3 1

impl Trait for Fn

用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)
        }

Reinvent your career. Join DEV.

It takes one minute and is worth it for your career.

Get started

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more