Skip to content

Commit b3992f9

Browse files
committed
Add mapping-only structured serialization module
1 parent 4891a00 commit b3992f9

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

wurst/file/SerializableTests.wurst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ class OldPlayerState extends Serializable
9898
override function deserializeProperties()
9999
score = getIntProperty("score")
100100

101+
class TransitionalPlayerState extends Serializable implements FieldSerializable
102+
use SerializableFieldMapping
103+
104+
int score = 0
105+
string title = "default"
106+
107+
override function serializeProperties()
108+
addProperty("score", score)
109+
addProperty("title", title)
110+
111+
override function deserializeProperties()
112+
score = getIntProperty("score")
113+
title = getStringProperty("title")
114+
101115
@Test
102116
function reflectedFieldsRoundTripNestedClassesAndTuples()
103117
constructions = 0
@@ -128,6 +142,27 @@ function reflectedFieldsRoundTripNestedClassesAndTuples()
128142
destroy loaded
129143
destroy data
130144

145+
@Test
146+
function mappingOnlyModuleCoexistsWithLegacySerializable()
147+
let original = new TransitionalPlayerState()
148+
original.score = 81
149+
original.title = "transition"
150+
let writer = new FieldSerializationWriter(1)
151+
writer.write("profile", original)
152+
let data = writer.finish()
153+
let reader = new FieldSerializationReader(data)
154+
let loaded = new TransitionalPlayerState()
155+
156+
reader.readInto("profile", loaded).assertTrue()
157+
loaded.score.assertEquals(81)
158+
loaded.title.assertEquals("transition")
159+
160+
destroy loaded
161+
destroy reader
162+
destroy data
163+
destroy writer
164+
destroy original
165+
131166
@Test
132167
function customTupleCodecRoundTripsThroughSerializableFields()
133168
let original = new CustomTupleState()

wurst/file/StructuredSerialization.wurst

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,28 @@ public module FieldSerializableLifecycle
202202
deserialize(input)
203203
return this
204204

205+
/**
206+
Automatic field mapping without adding a second `serialize`/`deserialize` lifecycle.
207+
208+
Use this during a compatibility window when a data class still extends legacy `Serializable`, or
209+
when another base class already owns lifecycle methods. The class must implement `FieldSerializable`.
210+
All of its accessible mutable instance fields participate; keep runtime-only state in a separate
211+
class because persisted-field annotation filtering is not available.
212+
*/
213+
public module SerializableFieldMapping
214+
function writeSerializedFields(FieldSerializationWriter writer)
215+
wurstForFields((fieldName, value) -> writer.write(fieldName, value))
216+
217+
function readSerializedFields(FieldSerializationReader reader)
218+
wurstMapFields((fieldName, value) -> value.readSerializedField(reader, fieldName))
219+
220+
function readSerializedField(FieldSerializationReader reader, string name) returns thistype
221+
let child = reader.readObject(name)
222+
if child.isValid()
223+
readSerializedFields(child)
224+
destroy child
225+
return this
226+
205227
/**
206228
Modern automatic serialization for dedicated state/DAO classes using built-in codecs.
207229

@@ -210,7 +232,8 @@ iteration to direct accesses. The tagged format tolerates field reordering, adde
210232
and unknown future wire types. Missing fields retain constructor defaults. Use a schema version and
211233
`SerializationMigration` for semantic changes or `renameField` for renamed attributes. For custom
212234
tuple codecs declared in the consuming package, use `FieldSerializableLifecycle` as documented
213-
above so overload resolution occurs where those codecs are visible.
235+
above so overload resolution occurs where those codecs are visible. Classes that must also retain
236+
legacy `Serializable` should use `SerializableFieldMapping` to avoid conflicting lifecycle methods.
214237
*/
215238
public module SerializableFields
216239
use FieldSerializableLifecycle

0 commit comments

Comments
 (0)