rust - 如何安全地使用由唯一 ID 表示的外部数据?

标签 rust

我可能希望在 Rust 中与之交互的许多外部系统(网络 API、FFI 到遗留 C 库等)使用数字 ID 来表示远程资源。这些 ID 通常具有隐含的上下文,在该上下文中它们是有效的,并且可以在程序持有它们时过期。

我习惯用其他编程语言处理这个问题,但在阅读 Rust 书(特别是 this chapter ,其中讨论了字符串索引)之后,我觉得避免直接暴露这些 ID 会更清晰、更安全在我的程序中,因为它们依赖于上下文并且不能保证它们在将来有效。 Rust 中是否有任何模式允许我安全地与由 ID 表示的远程资源交互?

考虑一个我尝试使用的特定 ABI 的简化示例来演示该问题:

// Windows are represented as a unique ID per connection.
type WindowId = u64;

/// Fetches a list of Windows from the display server.
fn get_windows() -> Vec<WindowId> {
    // Makes an external call to display server to get a list of Window IDs.
    ...
}

/// Wait for the next event sent by the display server.
fn get_event() -> Event {
    // Blocks until we receive an event, one of which can indicate that a
    // Window has been destroyed and is no longer valid.
    ...
}

/// Example of a function that uses a Window to fetch data.
fn get_window_dimensions(window: WindowId) -> (u32, u32) {
    // Makes an extermal call to display server to ask for the dimensions of
    // the window referenced by the provided WindowId.
   ...
}

/// Example of a function that uses a Window to modify data.
fn set_window_dimensions(window: WindowId, x: u32, y:u32) {
    // Makes an extermal call to display server to set the dimensions for
    // the window referenced by the provided WindowId.
   ...
}

此代码要求我们使用 WindowId 引用 Window 资源,但值得注意的是,如果出现以下情况,这些 ID 可能会变得无效:

  1. Window 被我们的程序调用例如destroy_window() 函数。
  2. Window 被拥有它的远程进程/客户端销毁。
  3. 我们的客户端失去连接,使所有可能仍存储的 WindowId 失效

在我的案例中,这些场景中的每一个都被认为是正常行为,并且应该由客户处理。这使得 WindowId 在没有明确编码范围的情况下直接使用时感觉很脆弱。例如,存储 WindowId 的程序的其他部分可能会突然发现引用的关联 Window 无效,并且需要以某种方式检测和处理这种情况。

这感觉很快就会变得非常困惑!在这些约束下,有什么方法可以让我在 Rust 中安全地与 Windows 交互,还是我需要直接处理 WindowId

最佳答案

根据您的描述,似乎是一个 new type idiom struct 在这里可能是合适的,因为用户似乎永远不需要 id 的实际数值。

struct WindowId(u64);

这并不能解决 ID 失效的问题。 要解决第 1 点,您可以使导致 Id 无效的函数使用 Id(按值获取),假设上面提到的新类型结构不派生 Copy 并且如果合理的话不实现 Clone。

impl WindowId {
    fn destroy(self){
        /* .. snip .. */
    }
}

这仍然留下第 2 点和第 3 点,最好的选择可能是所有通过其 ID 访问窗口的操作都是可失败的,例如通过返回 Result .

impl WindowId {
    fn size(&self) -> Result<(u32, u32), WindowError> {
        /* .. snip .. */
    }
}

关于rust - 如何安全地使用由唯一 ID 表示的外部数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65544739/

相关文章:

rust - 错误消息不清楚: returns a value referencing data owned by the current function

rust - 如何检查我的内存分配是否正确?

rust - 遍历对 Chars 的引用

rust - 如何将 float 四舍五入到指定位数?

rust - 实现 ParseIntError 的 From 特征

generics - 如何在 Rust 中提供通用结构的实现?

rust - 对于数组长度,类似于 C 预处理器的 #define 是什么?

get - 在 Rust HashMap 中返回精确值

rust - 将键插入 HashMap 后如何保留对键的引用?

c++ - 静态链接启用了PIC的内置库时,链接器PIC错误