#native #prost #protobuf #macro-derive

prost-convert-derive

Prost-convert中的进程宏

1 个不稳定版本

0.3.0 2024年8月19日

55#prost

Download history 135/week @ 2024-08-16

每月135 次下载
用于 prost-convert

MIT/Apache

26KB
483 代码行

Prost convert derive

此crate提供了用于TryFromProtoFromNative特质的derive宏。

使用它所需的内容。

  • Proto结构/枚举和本地结构应具有相同的名称。
  • Proto结构/枚举和本地结构应具有相同的字段名称。

用例:移除不需要的选项

Prost将用户定义的消息包装为可选的,如proto3规范所述。

宏的一个想法是,如果proto结构中的字段是可选的,而本地结构中没有,则提供一个转换函数以尝试进行转换。

遗憾的是,在derive宏中我们无法知道proto结构字段是否为可选的。我们只知道结构路径,我们无法简单地解析它

因此,如果我们使用TryFrom<Option<T>> for T,则无法自定义行为,因为我们不知道它是否为可选的。

一种解决方案是提供#[required]属性在本地结构上的字段,但这很冗长,并增加了样板。

除了TryFrom<Option<T>> for T之外,由于孤儿规则,这不是可实现的。

例如,这将不起作用

let option = Some(String::from("foo"));
let string: String = o.try_into()?;

因此,我们创建了自己的trait,以便在将Opion<T>转换为T时定义要执行的操作。

用例:移除不需要的包装器

我们真正需要的是将包装器转换为网络传输。通过网络接收后,再从包装器中创建。因此,我们必须指定包装器路径。但是,从包装器路径我们不能推导出包装路径,反之亦然。如果本地是枚举类型,我们能否假设提供的源是一个只有枚举类型字段的struct?-> 不能。目前我们需要为每个嵌套struct实现ProstConvert。所以我们可以有不在包装器struct内部的枚举。如果包装器只是递归调用,也许可以不提供包装器?

枚举的语法

#[derive(ProstConvert)]
#[prost_convert(src = "proto::Foo", wrapper = "proto::FooWrapper")]
enum Foo {
    Foo1,
    Foo2,
}

这将生成2个TryFromProto实现: "src" 属性与struct的用法相同,它会生成

impl TryFromProto<proto::Foo> for Foo
impl FromNative<Foo> for proto::Foo

但是,"wrapper" 属性还会生成2个额外的转换函数,与包装器struct一起

impl TryFromProto<proto::FooWrapper> for Foo
impl FromNative<Foo> for proto::FooWrapper

如果你使用了包装器关键字,不需要为包装器本身派生 ProstConvert。换句话说,我们不需要

impl TryFromProto<proto::FooWrapper> for FooWrapper
impl FromNative<FooWrapper> for proto::FooWrapper

目前

  • 包装器只能用于枚举(容易为struct实现,但是有没有用例?)
  • 包装器假设包装器是一个包含一个枚举的单字段struct。

潜在改进

  • 目前这个宏同时实现了 TryFromProtoFromNative,但有时我们可能只需要其中一个。
  • 只需使用darling解析宏参数(检查它是否与syn::Error集成良好)。
  • 当字段未实现prost derive时,编译错误应在字段上,而不是在struct上(例如缺少Debug、Clone等)。
  • [prost_convert(src = "..."]出现在struct注释顶部时,将出现编译错误 => 不应该是这种情况。
  • 我们是否使用了所有的错误变体?
  • 确认Style::TupleStyle::Tuple不能从protobuf创建。
  • 如果需要,提供自定义实现?例如,从std::string创建std::net::IpAddress
  • 处理新类型struct Id(Uuid)
  • 处理元组struct Foo(i32, i32)
  • 为这个添加UT pub struct Message {}
  • 处理"struct"枚举变体或在文档中标记它。另外,如果我们不支持它,我们可以在宏上添加编译错误。

许可证

根据以下任一许可证授权:

由您选择。

贡献

除非您明确声明,否则根据Apache-2.0许可证定义的任何有意提交以包含在作品中的贡献,将如上双重许可,不附加任何额外条款或条件。

依赖项

~1.5MB
~35K SLoC