从Rust中WebAssembly中的窗口对象获取查询字符串

从Rust中WebAssembly中的窗口对象获取查询字符串,rust,wasm-bindgen,rust-wasm,Rust,Wasm Bindgen,Rust Wasm,背景:我正在学习Rust&WebAssembly,作为一个实践练习,我有一个项目,用Rust代码在HTML画布上绘制东西。我想从web请求中获取查询字符串,然后代码可以从中决定调用哪个绘图函数 我编写此函数只是为了返回前导?已删除的查询字符串: fn解码请求(窗口:web\u系统::窗口)->std::string::string{ 让document=window.document().expect(“不存在全局窗口”); 让location=document.location().expec

背景:我正在学习Rust&WebAssembly,作为一个实践练习,我有一个项目,用Rust代码在HTML画布上绘制东西。我想从web请求中获取查询字符串,然后代码可以从中决定调用哪个绘图函数

我编写此函数只是为了返回前导
已删除的查询字符串:

fn解码请求(窗口:web\u系统::窗口)->std::string::string{
让document=window.document().expect(“不存在全局窗口”);
让location=document.location().expect(“不存在位置”);
让raw_search=location.search().expect(“不存在搜索”);
让search\u str=raw\u search.trim\u start\u匹配(“?”);
格式!(“{}”,搜索)
}
它确实能工作,但考虑到在我使用过的其他一些语言中它会变得简单得多,它似乎令人惊讶地冗长

有没有更简单的方法?还是说这种冗长只是你为生锈的安全付出的代价,我应该习惯它

从@IInspectable编辑每个答案: 我尝试了链接方法,得到一个错误:

temporary value dropped while borrowed

creates a temporary which is freed while still in use

note: consider using a `let` binding to create a longer lived value rustc(E0716)
最好能更好地理解这一点;我仍在通过头脑了解所有权的细节。现在是:

fn解码请求(窗口:窗口)->std::string::string{
让location=window.location();
让search_str=location.search().expect(“不存在搜索”);
让search_str=search_str.trim_start_匹配(“?”);
搜索街到所有的()
}

这当然是一个改进。

这个问题实际上是关于API设计,而不是它对实现的影响。实现结果相当冗长,主要是因为选择了契约:要么产生价值,要么死亡。这份合同本身没有什么问题。调用此函数的客户端永远不会观察到无效数据,因此这是完全安全的

不过,这可能不是库代码的最佳选择。库代码通常缺少上下文,并且不能很好地调用任何给定的错误条件是否是致命的。这是一个客户机代码更好回答的问题

在继续探索替代方案之前,让我们以更紧凑的方式重写原始代码,将调用链接在一起,而不显式地将每个结果分配给变量:

fn解码请求(窗口:web\u系统::窗口)->std::string::string{
窗口
.地点()
.search().expect(“不存在搜索”)
.trim_start_匹配(“?”)
.to_拥有()
}
我不熟悉
web\u sys
板条箱,因此有一些猜测。也就是说,假设
window.location()
返回的值与
document()
location()的值相同。除了链接调用之外,本文介绍的代码还进行了两项更改:

  • trim\u start\u matches()
    被传递一个字符文本来代替字符串文本。这将生成最佳代码,而无需依赖编译器的优化器来确定长度为1的字符串正在尝试搜索单个字符
  • 返回值是通过调用
    到_owned()
    来构造的。
    格式宏增加了开销,最终调用
    到\u string()
    。虽然在本例中也会表现出相同的行为,但使用语义更准确的
    to_owned()
    函数可以帮助您在编译时捕获错误(例如,如果您意外地将
    42.to_string()
选择 实现此函数更自然的方法是让它返回表示查询字符串的值,或者根本不返回任何值。Rust提供了方便建模的类型:

fn解码请求(窗口:web\u系统::窗口)->选项{
匹配窗口
.地点()
.search(){
Ok(s)=>一些(s.trim_start_匹配(“?”)。到_owned()),
_=>没有,
}
}
这允许函数的客户端根据函数返回的是
Some(s)
还是
None
做出决定。这将所有错误条件映射为
None

如果需要将故障原因反馈给调用者,则
解码请求
函数可以选择返回一个值,例如
结果
。在这样做时,实现可以利用
操作符,以紧凑的方式将错误传播给调用方:

fn解码请求(窗口:web\u sys::window)->结果{
好的(窗口
.地点()
.search()?
.trim_start_匹配(“?”)
.to_owned())
}

谢谢,反馈很好。当我尝试纯链接方法时出现的附加错误。如果你想到了这一点,那就太好了,但不管怎样,你的回答已经很有帮助了
search().unwrap()
返回一个从未分配给变量的
字符串;它的生存期在语句末尾结束,但是
trim\u start\u matches
返回一个切片引用,该切片引用比临时引用更有效。我将更新答案以解决此问题。在更新的代码中,
trim\u start\u matches
仍将切片引用返回到临时
字符串中。改变的是切片引用本身现在是临时的。它的生命结束与它的引用对象,即临时
字符串
值的生命结束一致。现在再也没有机会创建一个悬空的引用,借阅检查器也高兴了。谢谢。Rust处理大多数语言数据的作用域/生存期的方式不同,这肯定是我仍在努力解决的问题。@mat life仅限于封闭的作用域。这是一个相当传统的选择,与许多编程语言共享。事实上,如果你有机会,你也会遇到同样的人生问题。Rust的独特之处在于它在c