首先,我是Rust的新手:-)
问题:
我想创建一个名为RestServer的模块,其中包含添加路由并启动服务器的方法(actix-web)。
struct Route
{
url: String,
request: String,
handler: Box<dyn Fn(HttpRequest) -> HttpResponse>
}
impl PartialEq for Route {
fn eq(&self, other: &Self) -> bool {
self.url == other.url
}
}
impl Eq for Route {}
impl Hash for Route {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.url.hash(hasher);
}
}
这是路由结构,此结构包含路由URL,请求类型(GET,POST等),而hanlder是必须捕获请求并返回HTTPResponse的函数
pub struct RestServer
{
scopes: HashMap<String, Rc<HashSet<Route>>>,
routes: HashSet<Route>,
host: String,
}
impl RestServer {
pub fn add_route(self, req: &str, funct: impl Fn(HttpRequest) -> HttpResponse + 'static,
route: &str, scope: Option<&str>) -> RestServer
{
let mut routes_end = self.routes;
let mut scopes_end = self.scopes;
let url = self.host;
let route = Route {
url: String::from(route),
request: String::from(req),
handler: Box::new(funct)
};
if let Some(x) = scope {
if let Some(y) = scopes_end.get(x) {
let mut cloned_y = Rc::clone(y);
cloned_y.insert(route);
scopes_end.insert(String::from(x), cloned_y);
}else {
let mut hash_scopes = HashSet::new();
hash_scopes.insert(route);
scopes_end.insert(String::from(x), Rc::new(hash_scopes));
}
} else {
routes_end.insert(route);
}
RestServer {
scopes: scopes_end,
routes: routes_end,
host: String::from(url)
}
}
最新的代码是RestServer的实现。
最重要的部分是 add_route 函数,该函数作为参数接收作为字符串的路由,函数处理程序,请求字符串和作用域。
首先,我创建路线对象。
我检查范围是否存在于HashMap中,如果是,则必须采用实际范围并更新HashSet。
当我构建代码时,出现以下错误
error[E0596]: cannot borrow data in an `Rc` as mutable
--> interface/src/rest/mod.rs:60:17
|
60 | cloned_y.insert(route);
| ^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not
implemented for `std::rc::Rc<std::collections::HashSet<rest::Route>>`
我知道编译器会给我一些帮助,但老实说,我不知道该怎么做,或者我是否可以使用一些简单的解决方案。
在Google中进行大量搜索后,我在RefCell中找到了解决方案,但还不是很清楚
在此先感谢您的帮助
最佳答案
您不能借用引用计数指针作为可变指针。这是因为它提供的保证之一只有在结构为只读的情况下才有可能。
但是,您可以绕开它,但需要进行一些签名更改。
输入内部可变性
内部可变性是您可能从互斥体,原子和同步原语的形式从其他编程语言中了解的一个概念。实际上,这些结构允许您暂时保证您是给定变量的唯一访问者。
在Rust中,这特别好,因为它允许我们从仅需要对其自身进行不可变引用的结构中提取对内部构件的可变引用。完美适合Rc
。
根据您需要的内容,您会发现 Cell
和 RefCell
结构正是您所需要的。这些不是线程安全的,但是Rc
也不是,因此这并不是一个破坏交易的行为。
实际上,它的工作原理非常简单:
let data = Rc::new(RefCell::new(true));
{
let mut reference = data.borrow_mut();
*reference = false;
}
println!("{:?}", data);
playground
(如果您想要线程版本,
Arc
替换Rc
和Mutex
或RwLock
替换Cell
/RefCell
)关于rust - 不能借用可变的Rc,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58599539/