Я пытаюсь решить проблему сериализации и десериализации Box<SomeTrait>
. Я знаю, что в случае иерархии закрытого типа рекомендуемым способом является использование перечисления, и нет никаких проблем с их сериализацией, но в моем случае использование перечислений является неприемлемым решением.
Сначала я попытался использовать Serde, поскольку он является механизмом сериализации де-факто Rust. Serde способен сериализовать Box<X>
, но не в том случае, когда X
является признаком. Функция Serialize
может быть реализована для объектов-признаков, поскольку она имеет общие методы. Эта конкретная проблема может быть решена с помощью erased-serde, поэтому сериализация Box<SomeTrait>
может работать.
Основная проблема - десериализация. Чтобы десериализовать полиморфный тип, вам необходимо иметь маркер определенного типа в сериализованных данных. Сначала этот маркер следует десериализовать, а затем использовать для динамического получения функции, которая вернет Box<SomeTrait>
.
std::any::TypeId
может использоваться как тип маркера, но главная проблема заключается в том, как динамически получить функцию десериализации. Я не рассматриваю возможность регистрации функции для каждого полиморфного типа, который должен быть вызван вручную во время инициализации приложения.
Я знаю два возможных способа сделать это:
- Языки, которые имеют отражение во время выполнения, например С#, могут использовать его для получения десериализации.
- В С++ библиотека зерновых использует магию статических объектов для регистрации десериализатора в статической карте во время инициализации библиотеки.
Но ни один из этих вариантов не доступен в Rust. Как можно десериализовать полиморфные объекты в Rust, если вообще?