- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我刚刚开始学习 Rust,我正在努力处理生命周期。
我想要一个包含 String
的结构,用于缓冲来自标准输入的行。然后我想在结构上有一个方法,它返回缓冲区中的下一个字符,或者如果该行中的所有字符都已被消耗,它将从标准输入读取下一行。
文档说 Rust 字符串不能按字符索引,因为 UTF-8 效率低下。当我按顺序访问字符时,使用迭代器应该没问题。然而,据我所知,Rust 中的迭代器与它们正在迭代的事物的生命周期相关联,我不知道如何将此迭代器与 String
一起存储在结构中。
这是我想要实现的伪 Rust。显然它无法编译。
struct CharGetter {
/* Buffer containing one line of input at a time */
input_buf: String,
/* The position within input_buf of the next character to
* return. This needs a lifetime parameter. */
input_pos: std::str::Chars
}
impl CharGetter {
fn next(&mut self) -> Result<char, io::Error> {
loop {
match self.input_pos.next() {
/* If there is still a character left in the input
* buffer then we can just return it immediately. */
Some(n) => return Ok(n),
/* Otherwise get the next line */
None => {
io::stdin().read_line(&mut self.input_buf)?;
/* Reset the iterator to the beginning of the
* line. Obviously this doesn’t work because it’s
* not obeying the lifetime of input_buf */
self.input_pos = self.input_buf.chars();
}
}
}
}
}
我正在尝试执行 Synacor challenge .这涉及实现一个虚拟机,其中一个操作码从标准输入读取一个字符并将其存储在寄存器中。我这部分工作正常。文档指出,每当 VM 内的程序读取一个字符时,它会一直读取,直到读取整行。我想利用这一点为我的实现添加一个“保存”命令。这意味着无论何时程序要求输入一个字符,我都会从输入中读取一行。如果该行是“保存”,我将保存 VM 的状态,然后继续获取另一行以提供给 VM。每次 VM 执行输入操作码时,我都需要能够从缓冲行中一次给它一个字符,直到缓冲区耗尽。
我当前的实现是 here .我的计划是将 input_buf
和 input_pos
添加到表示 VM 状态的 Machine
结构。
最佳答案
详见 Why can't I store a value and a reference to that value in the same struct? ,通常您不能这样做,因为它确实不安全。移动内存时,会使引用无效。这就是为什么很多人使用 Rust 的原因 - 没有导致程序崩溃的无效引用!
让我们看看您的代码:
io::stdin().read_line(&mut self.input_buf)?;
self.input_pos = self.input_buf.chars();
在这两行之间,您离开了 self.input_pos
状态不佳。如果发生 panic ,那么对象的析构函数就有机会访问无效内存! Rust 正在保护您免受大多数人从未想过的问题的影响。
正如该答案中也所述:
There is a special case where the lifetime tracking is overzealous:when you have something placed on the heap. This occurs when you use a
Box<T>
, for example. In this case, the structure that is movedcontains a pointer into the heap. The pointed-at value will remainstable, but the address of the pointer itself will move. In practice,this doesn't matter, as you always follow the pointer.Some crates provide ways of representing this case, but they requirethat the base address never move. This rules out mutating vectors,which may cause a reallocation and a move of the heap-allocatedvalues.
记住 String
只是添加了额外前提条件的字节向量。
除了使用其中一个 crate 之外,我们还可以推出自己的解决方案,这意味着我们(阅读您)可以承担所有责任,确保我们没有做错任何事情。
这里的技巧是确保 String
中的数据永远不会移动,也不会意外引用。
use std::{mem, str::Chars};
/// I believe this struct to be safe because the String is
/// heap-allocated (stable address) and will never be modified
/// (stable address). `chars` will not outlive the struct, so
/// lying about the lifetime should be fine.
///
/// TODO: What about during destruction?
/// `Chars` shouldn't have a destructor...
struct OwningChars {
_s: String,
chars: Chars<'static>,
}
impl OwningChars {
fn new(s: String) -> Self {
let chars = unsafe { mem::transmute(s.chars()) };
OwningChars { _s: s, chars }
}
}
impl Iterator for OwningChars {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
self.chars.next()
}
}
您甚至可以考虑将只是这段代码放入一个模块中,这样您就不会不小心弄乱内部结构。
这是使用 ouroboros 的相同代码crate 创建一个包含 String
的自引用结构和一个 Chars
迭代器:
use ouroboros::self_referencing; // 0.4.1
use std::str::Chars;
#[self_referencing]
pub struct IntoChars {
string: String,
#[borrows(string)]
chars: Chars<'this>,
}
// All these implementations are based on what `Chars` implements itself
impl Iterator for IntoChars {
type Item = char;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.with_mut(|me| me.chars.next())
}
#[inline]
fn count(mut self) -> usize {
self.with_mut(|me| me.chars.count())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.with(|me| me.chars.size_hint())
}
#[inline]
fn last(mut self) -> Option<Self::Item> {
self.with_mut(|me| me.chars.last())
}
}
impl DoubleEndedIterator for IntoChars {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.with_mut(|me| me.chars.next_back())
}
}
impl std::iter::FusedIterator for IntoChars {}
// And an extension trait for convenience
trait IntoCharsExt {
fn into_chars(self) -> IntoChars;
}
impl IntoCharsExt for String {
fn into_chars(self) -> IntoChars {
IntoCharsBuilder {
string: self,
chars_builder: |s| s.chars(),
}
.build()
}
}
这是使用 rental 的相同代码crate 创建一个包含 String
的自引用结构和一个 Chars
迭代器:
#[macro_use]
extern crate rental; // 0.5.5
rental! {
mod into_chars {
pub use std::str::Chars;
#[rental]
pub struct IntoChars {
string: String,
chars: Chars<'string>,
}
}
}
use into_chars::IntoChars;
// All these implementations are based on what `Chars` implements itself
impl Iterator for IntoChars {
type Item = char;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.rent_mut(|chars| chars.next())
}
#[inline]
fn count(mut self) -> usize {
self.rent_mut(|chars| chars.count())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.rent(|chars| chars.size_hint())
}
#[inline]
fn last(mut self) -> Option<Self::Item> {
self.rent_mut(|chars| chars.last())
}
}
impl DoubleEndedIterator for IntoChars {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.rent_mut(|chars| chars.next_back())
}
}
impl std::iter::FusedIterator for IntoChars {}
// And an extension trait for convenience
trait IntoCharsExt {
fn into_chars(self) -> IntoChars;
}
impl IntoCharsExt for String {
fn into_chars(self) -> IntoChars {
IntoChars::new(self, |s| s.chars())
}
}
关于rust - 如何将 Chars 迭代器存储在与其迭代的 String 相同的结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43952104/
我正在运行一个辅助角色,并检查 Azure 上托管的存储中是否存在数据。当我将连接字符串用于经典类型的存储时,我的代码可以正常工作,但是当我连接到 V2 Azure 存储时,它会抛出此异常。 “远程服
在我的应用程序的主页上,我正在进行 AJAX 调用以获取应用程序各个部分所需的大量数据。该调用如下所示: var url = "/Taxonomy/GetTaxonomyList/" $.getJSO
大家好,我正在尝试将我的商店导入我的 Vuex Route-Gard。 路由器/auth-guard.js import {store} from '../store' export default
我正在使用 C# 控制台应用程序 (.NET Core 3.1) 从 Azure Blob 存储读取大量图像文件并生成这些图像的缩略图。新图像将保存回 Azure,并将 Blob ID 存储在我们的数
我想将 Mlflow 设置为具有以下组件: 后端存储(本地):在本地使用 SQLite 数据库存储 Mlflow 实体(run_id、params、metrics...) 工件存储(远程):使用 Az
我正在使用 C# 控制台应用程序 (.NET Core 3.1) 从 Azure Blob 存储读取大量图像文件并生成这些图像的缩略图。新图像将保存回 Azure,并将 Blob ID 存储在我们的数
我想将 Mlflow 设置为具有以下组件: 后端存储(本地):在本地使用 SQLite 数据库存储 Mlflow 实体(run_id、params、metrics...) 工件存储(远程):使用 Az
我的 Windows 计算机上的本地文件夹中有一些图像。我想将所有图像上传到同一容器中的同一 blob。 我知道如何使用 Azure Storage SDKs 上传单个文件BlockBlobServi
我尝试发出 GET 请求来获取我的 Azure Blob 存储帐户的帐户详细信息,但每次都显示身份验证失败。谁能判断形成的 header 或签名字符串是否正确或是否存在其他问题? 代码如下: cons
这是用于编写 JSON 的 NeutralinoJS 存储 API。是否可以更新 JSON 文件(推送数据),而不仅仅是用新的 JS 对象覆盖数据。怎么做到的??? // Javascript
我有一个并行阶段设置,想知道是否可以在嵌套阶段之前运行脚本,所以像这样: stage('E2E-PR-CYPRESS') { when { allOf {
我想从命令行而不是从GUI列出VirtualBox VM的详细信息。我对存储细节特别感兴趣。 当我在GUI中单击VM时,可以看到包括存储部分在内的详细信息: 但是到目前为止,我还没有找到通过命令行执行
我有大约 3500 个防洪设施,我想将它们表示为一个网络来确定流动路径(本质上是一个有向图)。我目前正在使用 SqlServer 和 CTE 来递归检查所有节点及其上游组件,只要上游路径没有 fork
谁能告诉我 jquery data() 在哪里存储数据以及何时删除以及如何删除? 如果我用它来存储ajax调用结果,会有性能问题吗? 例如: $("body").data("test", { myDa
有人可以建议如何为 Firebase 存储中的文件设置备份。我能够备份数据库,但不确定如何为 firebase 存储中的文件(我有图像)设置定期备份。 最佳答案 如何进行 Firebase 存储的本地
我最近开始使用 firebase 存储和 firebase 功能。现在我一直在开发从功能到存储的文件上传。 我已经让它工作了(上传完成并且文件出现在存储部分),但是,图像永远保持这样(永远在右侧加载)
我想只允许用户将文件上传到他们自己的存储桶中,最大文件大小为 1MB,仍然允许他们删除文件。我添加了以下内容: match /myusers/{userId}/{allPaths=**} { al
使用生命周期管理策略将容器的内容从冷访问层移动到存档。我正在尝试以下策略,希望它能在一天后将该容器中的所有文件移动到存档层,但事实并非如此在职的。我设置了选择标准“一天未使用后”。 这是 json 代
对于连接到 Azure 存储端点,有 http 和 https 两个选项。 第一。 https 会带来开销,可能是 5%-10%,但我不支付同一个数据中心的费用。 第二。 http 更快,但 Auth
有人可以帮我理解这一点吗?我创建了Virtual Machine in Azure running Windows Server 2012 。我注意到 Azure 自动创建了一个存储帐户。当我进入该存
我是一名优秀的程序员,十分优秀!