如何在板条箱内制作 Rust 项目 public,但在板条箱外是私有的?

How do I make an Rust item public within a crate, but private outside it?

我有一个包含大量代码的箱子,所以我将它分成多个 files/modules。然而,一些模块有内部不安全的东西(例如原始指针),我需要对不同的模块进行 public ,但我不想暴露给我的板条箱的用户。我该怎么做?

我能想到的唯一方法就是让我的 crate 实际上只是一个大模块,但是没有办法将它拆分成不同的文件,除了 this solution 似乎 有点老套。

通常当我遇到一个现实世界的问题时,Rust 文档中的简单示例不能充分解释我只是复制一个流行的现实世界的板条箱,例如git2-rs,但这似乎有效地使所有内容 public,包括原始指针。

为了从库箱导出 item,必须至少有一条路径通向它,其中 每个 组件是 public.这意味着你需要做的就是在你的板条箱中制作一个项目 public 但不从板条箱导出(从现在开始我将称之为 "internal" ,以模仿 C# 术语)是把它放在一个crate root 下的私有模块。

但是,该解决方案限制性很强。如果您想要一个带有导出函数 内部函数的模块怎么办?为了导出一些功能,我们需要制作模块 public,这意味着该模块中的所有 public 项也将被导出。

Rust 1.18, there's a solution adapted to this kind of scenario: pub(restricted)。此功能允许您指定 "how public" 项目应该是。语法非常灵活(你可以让一个项目对特定的模块树而不是整个箱子可见),但如果你想保持简单,pub(crate) 将使箱子内的任何地方都可以访问一个项目,但不是到其他板条箱(相当于 C# 中的 internal)。

例如,假设我们想要一个模块 util,其中 foo 是导出的(如 mycrate::util::foo),bar 是内部的并且 baz 是模块私有的。代码可能如下所示:

pub mod util {
    pub fn foo() {
        unimplemented!()
    }

    pub(crate) fn bar() {
        unimplemented!()
    }

    fn baz() {
        unimplemented!()
    }
}

如果您还在使用 1.18 之前的 Rust,有一个解决方法,但它有点笨拙。它涉及在私有模块中定义所有项目,并仅在 public 模块 包含再出口。上面的示例如下所示:

pub mod util {
    pub use util_impl::foo;
}

mod util_impl {
    pub fn foo() {
        unimplemented!()
    }

    pub fn bar() {
        unimplemented!()
    }

    fn baz() {
        unimplemented!()
    }
}

这不仅不容易阅读和理解,而且也没有涵盖所有可以使用 pub 的情况。例如,如何在不导出它们的情况下使同一个 crate 中的其他模块可以访问导出结构的某些字段?唯一的选择是公开一个带有单个私有字段的包装器,其类型是具有 public 字段的结构;如果你想隐藏其他板条箱的所有字段,这很好用,但如果你想公开一些字段,则效果不佳 在同一结构中创建一些其他字段。