0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rust】同名フィールドを持つ異なる型に変換する

Posted at

はじめに

以下のようなことをやりたいです。

mod A {
    #[derive(Default)]
    pub struct Foo {
        pub id: i64,
        pub name: String,
    }
}

mod B {
    pub struct Foo {
        pub id: i64,
        pub name: String,
    }
}

let a = A::Foo::default();
let b = B::Foo { id: 1, ..a };
assert_eq!(a, b);

上記の例でいうと、fooとbarが同じ型であれば問題なくコンパイルが通ります。
しかしジェネリクスが使用されていたり、名前空間が異なると異なる型とみなされて実現できません。

調べてみるとRFCがありましたがFurther generalizationとして提示されています。
(ジェネリクスについては1.58あたりで入りそうです)

環境

❯ rustc -V
rustc 1.55.0 (c8dfcfe04 2021-09-06)

成果

use type_change::From;

# [derive(Clone)]
struct Foo {
    id: i64,
    name: String,
}

# [derive(From)]
# [from(Foo)]
struct Bar {
    id: i64,
    name: String,
}

let foo = Foo { id: 1, name: "foo".to_string() };
let bar = Bar { name: "bar".to_string(), ..foo.clone().into() };
assert_eq!(foo.id, bar.id);

リポジトリはこちらです

タプル構造体や構造体のフィールドでも変換できます。

現状はすべてのフィールド名と型が一致しないと変換できないのですが、attributeを付けてフィールドごとに制御できたらもっと使いやすいと思います。

終わりに

マクロは初めて書いたのですがsynquoteのおかげで直感的にかなり書きやすいと思いました。

手続きマクロは別クレートを用意しなければならないのであまり気軽に書くことはなさそうですが、何でもできるので覚えておくと困ったときに役立つと思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?