Serde ist eine erstaunliche Serialisierungsbibliothek für Rust und war ein großer Grund dafür, dass ich jahrelang mit ihr produktiv war. Allerdings wurde ich schon bei Sentry recht frustriert über einige der Beschränkungen, mit denen sie sich kennt, aber Serde tatsächlich zu ersetzen ist schwierig, aufgrund der Einflusskraft, die sie in der Ökosystem hat. Außerdem ist es ziemlich schwer, wirklich besser zu werden, ohne auch einige potenziell schmerzhafte Kompromisse zu machen.
Hier sind drei Beispiele für Serde-Grenzfälle, die schlechte Wechselwirkungen zwischen Serde-Funktionen oder unerwartete Beschränkungen zeigen: Eine Zahl, die eine Karte ist. Eine intern markierte Enumeration, mit der serde_json arbitrary_precision-Funktion aktiviert. Das Zusammenfalten beschädigt Integer-Schlüssel.
Adapter lassen sich nicht zusammensetzen. Keiner dieser Fehler ist leicht in Serde zu beheben. Sie gehen aus seinem Design hervor, und dieses Design ist durch Serde-Stabilitätsgarantien geschützt. 2022 begann ich ein Experiment namens Deser.
Es ist eine Serialisierungsbibliothek für Rust, die die Benutzererfahrung von Serde auf einer völlig anderen, von miniserde inspirierten Architektur unterbringt. Ich habe sie sie niemals wirklich abgeschlossen und sie lag einige Jahre ungenutzt. Ich nahm sie wieder auf und sie hat jetzt einen Punkt erreicht, den ich für blickwürdig halte.
Selbst nur, um andere zu inspirieren, zu sehen, ob sie möchten, den Raum zu erkunden. Name und Idee Der Name ist Serde mit seinen beiden Hälften vertauscht. Deser ist Serde auf die andere Weise.
In Serde treibt ein Typ den Deserialisierungsprozess an: Eine Deserialize-Implementierung fragt den Deserialisierer nach dem Typ des erwarteten Werts, das Format ruft einen Besucher zurück. Jeder verschachtelte Wert wird durch Rekursion verarbeitet, was Serde-Deserialisierung auf natürliche Weise den Stapel mit jedem Verschachtelungsgrad wachsen lässt. Deser dagegen kehrt dies um und das Format sagt dem Typ des nächsten Werts und drückt Ereignisse in einen Sink.
Wenn ein Sink am Anfang eines verschachtelten Werts ankommt, ruft er nicht darauf zu, sondern übergibt einen neuen Sink an einen Treiber, der alle Zustände auf dem Heap behält (tatsächlich in einer Arena). Auf dem Weg nach außen geben Emitter ihre verschachtelten Werte zurück statt sie rekursiv hinein zu gehen.