如何在 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 项目设为公开,但在其外部设为私有?的主要内容,如果未能解决你的问题,请参考以下文章

在 Rust 库中仅公开泛型私有类型的具体变体

Rust: Cargo 使用本地 crate

如何在 CouchDB 中将用户创建设为公开但读取权限设为私有?

如何让Rust的openssl crate解密来自对称加密gem的数据而没有Node Crypto自动删除的乱码?

如何找到 Rust 库的当前版本?

rust 模块组织结构