Serializer: полная реализация
Возвращаясь к исходному желаемому потоку:
Теперь это напрямую отражено в типах нашего сериализатора:
Код полной реализации 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 вместе с обобщениями, чтобы провести пользователя через безопасные и корректные шаги настройки.