Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Serializer: полная реализация

Возвращаясь к исходному желаемому потоку:

structureserializerpropertylistString

Теперь это напрямую отражено в типах нашего сериализатора:

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

Код полной реализации Serializer и всех его состояний можно найти в этой песочнице Rust.

  • Этот паттерн не является серебряной пулей. Он всё равно допускает такие проблемы, как:

    • Пустые или некорректные имена свойств (что можно исправить с помощью паттерна 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 для обеспечения критически важных инвариантов.

  • Один отличный пример из практики — rustls::ClientConfig, который использует typestate вместе с обобщениями, чтобы провести пользователя через безопасные и корректные шаги настройки.