Serialize script fields in "array" + more forgiving deserialization

This commit is contained in:
Simon Lübeß
2023-07-17 04:04:01 +02:00
parent 88b393157a
commit 66d66d3308
2 changed files with 97 additions and 37 deletions
+15 -13
View File
@@ -60,33 +60,35 @@ extension ScriptFieldType
case .Long:
return typeof(int64);
case .Byte:
return typeof(uint8);
return typeof(uint8);
case .UShort:
return typeof(uint16);
return typeof(uint16);
case .UInt:
return typeof(uint32);
return typeof(uint32);
case .ULong:
return typeof(uint64);
return typeof(uint64);
case .Float:
return typeof(float);
return typeof(float);
case .float2:
return typeof(float2);
return typeof(float2);
case .float3:
return typeof(float3);
return typeof(float3);
case .float4:
return typeof(float4);
return typeof(float4);
case .Double:
return typeof(double);
return typeof(double);
case .Double2:
return typeof(double2);
return typeof(double2);
case .Double3:
return typeof(double3);
return typeof(double3);
case .Double4:
return typeof(double4);
return typeof(double4);
case .Entity:
return typeof(UUID);
default:
return null;
+80 -22
View File
@@ -195,15 +195,29 @@ class SceneSerializer
{
let fields = ScriptEngine.GetScriptFieldMap(entity);
for (var (fieldName, fieldInstance) in fields)
writer.Identifier("Fields");
using (writer.ArrayBlock())
{
switch (fieldInstance.Field.FieldType)
for (var (fieldName, fieldInstance) in fields)
{
case .Entity, .Enum, .Class, .Struct:
// TODO: implement
default:
writer.Identifier(fieldName);
Serialize.Value(writer, ValueView(fieldInstance.Field.FieldType.GetBeefType(), &fieldInstance.[Friend]_data), gBonEnv);
if (fieldInstance.Field.FieldType == .None)
continue;
switch (fieldInstance.Field.FieldType)
{
case .Enum, .Class, .Struct:
// TODO: implement
default:
writer.Identifier(fieldName);
String str = scope .();
fieldInstance.Field.FieldType.ToString(str);
writer.Type(str);
Serialize.Value(writer, ValueView(fieldInstance.Field.FieldType.GetBeefType(), &fieldInstance.[Friend]_data), gBonEnv);
}
}
}
}
@@ -567,28 +581,72 @@ class SceneSerializer
Try!(reader.EntryEnd());
bool first = true;
while (reader.ObjectHasMore())
if (Try!(reader.Identifier()) == "Fields")
{
if (first)
first = false;
else
Try!(reader.EntryEnd());
Try!(reader.ArrayBlock());
// TODO: We could think about doing the Try! a little smarter...
// However we always might just fail to deserialize, so it doesn't really matter.
bool dontRemoveComma = true;
StringView fieldName = Try!(reader.Identifier());
if (fields.ContainsKey(fieldName))
// Remove whitespace before the check
while (reader..ConsumeEmpty().ArrayHasMore())
{
var field = ref fields[fieldName];
if (dontRemoveComma)
dontRemoveComma = false;
else
{
if (reader.[Friend]Check(',', false))
reader.EntryEnd();
else
reader..FileEntrySkip(1).ConsumeEmpty();
}
void* data = &field.[Friend]_data;
// TODO: We could think about doing the Try! a little smarter...
// However we always might just fail to deserialize, so it doesn't really matter.
// It does matter... in case of an error we should try to skip to the next entry.
Try!(Deserialize.Value(reader, ValueView(field.Field.FieldType.GetBeefType(), data), gBonEnv));
StringView fieldName = Try!(reader.Identifier());
if (fields.ContainsKey(fieldName))
{
var field = ref fields[fieldName];
Result<StringView> fieldTypeName = reader.Type();
if (fieldTypeName case .Err)
{
Log.EngineLogger.Error($"Failed to read field type for field \"{fieldName}\" in script \"{component.ScriptClass.FullName}\" of entity {entity.UUID} (\"{entity.Name}\")");
reader.FileEntrySkip(1);
dontRemoveComma = true;
continue;
}
Result<ScriptFieldType> fieldType = Enum.Parse<ScriptFieldType>(fieldTypeName, true);
if ((fieldType case .Err) || (fieldType != field.Field.FieldType))
{
Log.EngineLogger.Error($"Unexpected field type (\"{fieldTypeName}\" instead of \"{field.Field.FieldType}\" for field: \"{fieldName}\" in script \"{component.ScriptClass.FullName}\" of entity {entity.UUID} (\"{entity.Name}\")");
reader.FileEntrySkip(1);
dontRemoveComma = true;
continue;
}
void* data = &field.[Friend]_data;
if (Deserialize.Value(reader, ValueView(field.Field.FieldType.GetBeefType(), data), gBonEnv) case .Err)
{
Log.EngineLogger.Error($"Failed to deserialize data for field: \"{fieldName}\" in script \"{component.ScriptClass.FullName}\" of entity {entity.UUID} (\"{entity.Name}\")");
reader.FileEntrySkip(1);
dontRemoveComma = true;
continue;
}
}
else
{
Log.EngineLogger.Error($"Script \"{component.ScriptClass.FullName}\" doesn't have a field with name \"{fieldName}\". (Entity {entity.UUID} (\"{entity.Name}\"))");
}
}
Try!(reader.ArrayBlockEnd());
}
}