Serializer: 完全な実装

最初に目指していたフローを振り返ると、次のようになります。

structureserializerpropertylistString

これが、シリアライザーの型に直接反映されていることがわかります。

Serializer<Root>Serializer<Struct<S>>Serializer<Property<S>>StringSerializer<List<S>>finishstructserializestructfinishlistfinishstructserializestringorstructserializepropertyfinishfinishstructserializelistserializelistorstringorfinishlist

Serializer とそのすべての状態の完全な実装コードは、この Rust playground で確認できます。

  • このパターンは銀の弾丸ではありません。次のような問題は依然として許してしまいます。

    • 空または無効なプロパティ名(これは newtype パターン を使って修正できます)
    • 重複したプロパティ名(これは Struct<S> で追跡し、Result で処理できます)
  • 検証の失敗が発生する場合は、メソッドシグネチャを変更して Result を返すようにし、回復を可能にすることもできます。

    #![allow(unused)]
    fn main() {
    // Copyright 2025 Google LLC
    // SPDX-License-Identifier: Apache-2.0
    
    struct PropertySerializeError<S> {
        kind: PropertyError,
        serializer: Serializer<Struct<S>>,
    }
    
    impl<S> Serializer<Struct<S>> {
        fn serialize_property(
            self,
            name: &str,
        ) -> Result<Serializer<Property<Struct<S>>>, PropertySerializeError<S>> {
            /* ... */
        }
    }
    }
  • この API は強力ですが、常に使いやすいとは限りません。本番環境のシリアライザーでは、通常はよりシンプルな API が好まれ、typestate パターンは重要な不変条件を強制するためにのみ使われます。

  • 現実の優れた例の 1 つが rustls::ClientConfig で、これはジェネリクスと typestate を使って、ユーザーを安全で正しい設定手順へ導きます。