如何在 crate 中将 Rust 项目设为公开,但在其外部设为私有?
Posted
技术标签:
【中文标题】如何在 crate 中将 Rust 项目设为公开,但在其外部设为私有?【英文标题】:How do I make an Rust item public within a crate, but private outside it? 【发布时间】:2017-05-30 16:36:46 【问题描述】:我有一个包含大量代码的板条箱,因此我将其拆分为多个文件/模块。但是,某些模块具有内部不安全的东西(例如原始指针),我需要将其公开给不同的模块,但我不想暴露给我的 crate 的用户。我该怎么做?
我能想到的唯一方法是实际上让我的 crate 只是一个大模块,但是没有办法将它分成不同的文件,除了 this solution 这似乎有点哈克。
通常,当我遇到一个真实世界的问题时,Rust 文档中的简单示例无法充分解释我只是复制一个流行的真实世界 crate,例如git2-rs,但这似乎只是有效地公开了所有内容,包括原始指针。
【问题讨论】:
【参考方案1】:为了从库 crate 中导出 item,必须至少有一个路径通向它,其中 每个 组件都是公共的。这意味着您需要在您的 crate 中公开一个项目但不从 crate 中导出(我从现在开始将其称为“内部”,以模仿 C# 术语)是将它放在 crate 根目录下的私有模块中.
但是,该解决方案具有很大的限制性。如果您想要一个具有导出函数和内部函数的模块怎么办?为了导出某些功能,我们需要将模块设为公共,这意味着该模块中的所有公共项也会被导出。
自从Rust 1.18,就有了适应这种场景的解决方案:pub(restricted)
。此功能可让您指定项目的“公开程度”。语法非常灵活(您可以使项目对特定模块树而不是整个 crate 可见),但如果您想保持简单,pub(crate)
将使项目在 crate 中的任何位置都可以访问,但不能被其他人访问crates(相当于 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,有一个解决方法,但它有点笨拙。它涉及在私有模块中定义您的所有项目,并仅在仅包含重新导出的公共模块中重新导出您想要公开的项目(使用pub use
)。上面的示例如下所示:
pub mod util
pub use util_impl::foo;
mod util_impl
pub fn foo()
unimplemented!()
pub fn bar()
unimplemented!()
fn baz()
unimplemented!()
这不仅不容易阅读和理解,而且没有涵盖所有可以使用pub
的情况。例如,如何使导出结构的某些字段在同一个 crate 中的其他模块中可访问,而不导出它们?唯一的选择是公开一个带有单个私有字段的包装器,其类型是具有公共字段的结构;如果您想从其他 crate 中隐藏所有字段,则效果很好,但如果您想公开某些字段并在同一结构中创建一些其他字段,则不行。
【讨论】:
以上是关于如何在 crate 中将 Rust 项目设为公开,但在其外部设为私有?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 CouchDB 中将用户创建设为公开但读取权限设为私有?