DEV Community

x1957
x1957

Posted on • Edited on

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

Top comments (0)