如何在哈希映射字段中保存对处理程序的引用
How to save reference to handler in hashmap field
我正在学习 Rust 并尝试编写一个 websocket 服务器。逻辑如下:WSConnectionFactory 创建 WSHandler 来处理传入的消息并根据任意规则将它们发送到其他客户端。
问题是我不知道如何实现这种行为。
限制:我无法更改工厂和处理程序特征的签名,因为它们由 ws-rs 库提供。
问题:如何使用RefCell/Cell实现这个?
extern crate rand;
extern crate rustc_serialize;
extern crate ws;
#[macro_use]
extern crate log;
#[macro_use]
extern crate env_logger;
use std::cell::RefCell;
use std::collections::HashMap;
use rand::random;
use ws::{Factory, Sender, Handler, Handshake, Message, CloseCode, WebSocket};
use ws::Result as WSResult;
use ws::util::Token;
struct WSConnectionFactory<'p> {
handlers: HashMap<&'p u32, RefCell<&'p WSHandler<'p>>>,
}
#[derive(Debug)]
struct WSHandler<'h> {
uid: &'h u32,
ws: RefCell<&'h Sender>,
}
impl<'p> Factory for WSConnectionFactory<'p> {
type Handler = WSHandler<'p>;
fn connection_made(&mut self, ws: Sender) -> Self::Handler {
println!("factory.connection_made token={:?}", &ws.token());
let uid = &random::<u32>();
let handler = WSHandler {
uid: uid,
ws: RefCell::new(&ws),
};
self.handlers.insert(uid, RefCell::new(&handler));
handler
}
}
impl<'h> Handler for WSHandler<'h> {
fn on_open(&mut self, _handshake: Handshake) -> WSResult<()> {
println!("handler.on_open");
Ok(())
}
fn on_message(&mut self, msg: Message) -> WSResult<()> {
println!("handler.on_message {:?}", msg);
Ok(())
}
fn on_timeout(&mut self, _token: Token) -> WSResult<()> {
println!("handler.on_timeout {:?}", _token);
Ok(())
}
fn on_close(&mut self, code: CloseCode, reason: &str) {
println!("handler.on_close code={:?}, reason={:?}", code, reason);
}
}
fn main() {
let factory = WSConnectionFactory { handlers: HashMap::new() };
let ws_socket = WebSocket::new(factory).expect("Can't create WebSocket");
ws_socket.listen("127.0.0.1:8080").expect("Can't bind to socket");
}
您正在尝试从 connection_made
return 一个 WSHandler
,同时还在 WSConnectionFactory
结构中存储对 WSHandler
的引用。这是不可能的(借用指针),因为通过 returning a WSHandler
,你无法控制它会发生什么(它可能被移动或丢弃,这会使你的指针无效)。当您应该直接存储值时,您也在存储借用的指针。
WSConnectionFactory
creates WSHandler
which handle incoming messages and send them to other clients according to arbitrary rules.
如果你想向其他客户端发送消息,你实际上需要一个Sender
,而不是WSHandler
。值得庆幸的是,Sender
实现了 Clone
,通过快速查看代码,克隆一个 Sender
应该会给你第二个 "handle" 到相同的端点。因此,您应该在 HashMap
中放置 Sender
,而不是 WSHandler
.
extern crate rand;
extern crate rustc_serialize;
extern crate ws;
#[macro_use]
extern crate log;
#[macro_use]
extern crate env_logger;
use std::collections::HashMap;
use rand::random;
use ws::{Factory, Sender, Handler, Handshake, Message, CloseCode, WebSocket};
use ws::Result as WSResult;
use ws::util::Token;
struct WSConnectionFactory {
handlers: HashMap<u32, Sender>,
}
#[derive(Debug)]
struct WSHandler {
uid: u32,
ws: Sender,
}
impl Factory for WSConnectionFactory {
type Handler = WSHandler;
fn connection_made(&mut self, ws: Sender) -> Self::Handler {
println!("factory.connection_made token={:?}", &ws.token());
let uid = random::<u32>();
let handler = WSHandler {
uid: uid,
ws: ws.clone(),
};
self.handlers.insert(uid, ws);
handler
}
}
impl Handler for WSHandler {
fn on_open(&mut self, _handshake: Handshake) -> WSResult<()> {
println!("handler.on_open");
Ok(())
}
fn on_message(&mut self, msg: Message) -> WSResult<()> {
println!("handler.on_message {:?}", msg);
Ok(())
}
fn on_timeout(&mut self, _token: Token) -> WSResult<()> {
println!("handler.on_timeout {:?}", _token);
Ok(())
}
fn on_close(&mut self, code: CloseCode, reason: &str) {
println!("handler.on_close code={:?}, reason={:?}", code, reason);
}
}
fn main() {
let factory = WSConnectionFactory { handlers: HashMap::new() };
let ws_socket = WebSocket::new(factory).expect("Can't create WebSocket");
ws_socket.listen("127.0.0.1:8080").expect("Can't bind to socket");
}
我正在学习 Rust 并尝试编写一个 websocket 服务器。逻辑如下:WSConnectionFactory 创建 WSHandler 来处理传入的消息并根据任意规则将它们发送到其他客户端。 问题是我不知道如何实现这种行为。
限制:我无法更改工厂和处理程序特征的签名,因为它们由 ws-rs 库提供。
问题:如何使用RefCell/Cell实现这个?
extern crate rand;
extern crate rustc_serialize;
extern crate ws;
#[macro_use]
extern crate log;
#[macro_use]
extern crate env_logger;
use std::cell::RefCell;
use std::collections::HashMap;
use rand::random;
use ws::{Factory, Sender, Handler, Handshake, Message, CloseCode, WebSocket};
use ws::Result as WSResult;
use ws::util::Token;
struct WSConnectionFactory<'p> {
handlers: HashMap<&'p u32, RefCell<&'p WSHandler<'p>>>,
}
#[derive(Debug)]
struct WSHandler<'h> {
uid: &'h u32,
ws: RefCell<&'h Sender>,
}
impl<'p> Factory for WSConnectionFactory<'p> {
type Handler = WSHandler<'p>;
fn connection_made(&mut self, ws: Sender) -> Self::Handler {
println!("factory.connection_made token={:?}", &ws.token());
let uid = &random::<u32>();
let handler = WSHandler {
uid: uid,
ws: RefCell::new(&ws),
};
self.handlers.insert(uid, RefCell::new(&handler));
handler
}
}
impl<'h> Handler for WSHandler<'h> {
fn on_open(&mut self, _handshake: Handshake) -> WSResult<()> {
println!("handler.on_open");
Ok(())
}
fn on_message(&mut self, msg: Message) -> WSResult<()> {
println!("handler.on_message {:?}", msg);
Ok(())
}
fn on_timeout(&mut self, _token: Token) -> WSResult<()> {
println!("handler.on_timeout {:?}", _token);
Ok(())
}
fn on_close(&mut self, code: CloseCode, reason: &str) {
println!("handler.on_close code={:?}, reason={:?}", code, reason);
}
}
fn main() {
let factory = WSConnectionFactory { handlers: HashMap::new() };
let ws_socket = WebSocket::new(factory).expect("Can't create WebSocket");
ws_socket.listen("127.0.0.1:8080").expect("Can't bind to socket");
}
您正在尝试从 connection_made
return 一个 WSHandler
,同时还在 WSConnectionFactory
结构中存储对 WSHandler
的引用。这是不可能的(借用指针),因为通过 returning a WSHandler
,你无法控制它会发生什么(它可能被移动或丢弃,这会使你的指针无效)。当您应该直接存储值时,您也在存储借用的指针。
WSConnectionFactory
createsWSHandler
which handle incoming messages and send them to other clients according to arbitrary rules.
如果你想向其他客户端发送消息,你实际上需要一个Sender
,而不是WSHandler
。值得庆幸的是,Sender
实现了 Clone
,通过快速查看代码,克隆一个 Sender
应该会给你第二个 "handle" 到相同的端点。因此,您应该在 HashMap
中放置 Sender
,而不是 WSHandler
.
extern crate rand;
extern crate rustc_serialize;
extern crate ws;
#[macro_use]
extern crate log;
#[macro_use]
extern crate env_logger;
use std::collections::HashMap;
use rand::random;
use ws::{Factory, Sender, Handler, Handshake, Message, CloseCode, WebSocket};
use ws::Result as WSResult;
use ws::util::Token;
struct WSConnectionFactory {
handlers: HashMap<u32, Sender>,
}
#[derive(Debug)]
struct WSHandler {
uid: u32,
ws: Sender,
}
impl Factory for WSConnectionFactory {
type Handler = WSHandler;
fn connection_made(&mut self, ws: Sender) -> Self::Handler {
println!("factory.connection_made token={:?}", &ws.token());
let uid = random::<u32>();
let handler = WSHandler {
uid: uid,
ws: ws.clone(),
};
self.handlers.insert(uid, ws);
handler
}
}
impl Handler for WSHandler {
fn on_open(&mut self, _handshake: Handshake) -> WSResult<()> {
println!("handler.on_open");
Ok(())
}
fn on_message(&mut self, msg: Message) -> WSResult<()> {
println!("handler.on_message {:?}", msg);
Ok(())
}
fn on_timeout(&mut self, _token: Token) -> WSResult<()> {
println!("handler.on_timeout {:?}", _token);
Ok(())
}
fn on_close(&mut self, code: CloseCode, reason: &str) {
println!("handler.on_close code={:?}, reason={:?}", code, reason);
}
}
fn main() {
let factory = WSConnectionFactory { handlers: HashMap::new() };
let ws_socket = WebSocket::new(factory).expect("Can't create WebSocket");
ws_socket.listen("127.0.0.1:8080").expect("Can't bind to socket");
}