/// <summary> /// Writes the specified <see cref="Duality.Serialization.MetaFormat.StructNode"/>, including possible child nodes. /// </summary> /// <param name="node"></param> protected void WriteStruct(StructNode node) { // Write the structs data type this.writer.Write(node.TypeString); this.writer.Write(node.ObjId); this.writer.Write(node.CustomSerialization); this.writer.Write(node.SurrogateSerialization); if (node.SurrogateSerialization) { CustomSerialIO customIO = new CustomSerialIO(); DummyNode surrogateConstructor = node.SubNodes.FirstOrDefault() as DummyNode; if (surrogateConstructor != null) { var enumerator = surrogateConstructor.SubNodes.GetEnumerator(); while (enumerator.MoveNext()) { StringNode key = enumerator.Current as StringNode; if (enumerator.MoveNext() && key != null) { DataNode value = enumerator.Current; customIO.WriteValue(key.StringValue, value); } } } customIO.Serialize(this); } if (node.CustomSerialization || node.SurrogateSerialization) { CustomSerialIO customIO = new CustomSerialIO(); var enumerator = node.SubNodes.GetEnumerator(); while (enumerator.MoveNext()) { StringNode key = enumerator.Current as StringNode; if (key != null && enumerator.MoveNext()) { DataNode value = enumerator.Current; customIO.WriteValue(key.StringValue, value); } } customIO.Serialize(this); } else { bool skipLayout = false; TypeDataLayout layout = null; if (node.SubNodes.FirstOrDefault() is TypeDataLayoutNode) { TypeDataLayoutNode typeDataLayout = node.SubNodes.FirstOrDefault() as TypeDataLayoutNode; this.WriteTypeDataLayout(typeDataLayout.Layout, node.TypeString); layout = typeDataLayout.Layout; skipLayout = true; } else { this.WriteTypeDataLayout(node.TypeString); layout = this.GetCachedTypeDataLayout(node.TypeString); } // Write the structs omitted mask bool[] fieldOmitted = new bool[layout.Fields.Length]; for (int i = 0; i < layout.Fields.Length; i++) { fieldOmitted[i] = !node.SubNodes.Any(n => !(n is DummyNode) && n.Name == layout.Fields[i].name); } this.WriteArrayData(fieldOmitted); // Write the structs fields foreach (DataNode subNode in node.SubNodes) { if (skipLayout) { skipLayout = false; continue; } if (subNode is DummyNode) { continue; } this.WriteObject(subNode); } } }
/// <summary> /// Reads a <see cref="Duality.Serialization.MetaFormat.StructNode"/>, including possible child nodes. /// </summary> /// <param name="node"></param> protected StructNode ReadStruct(bool classType) { // Read struct type string objTypeString = this.reader.ReadString(); uint objId = this.reader.ReadUInt32(); bool custom = this.reader.ReadBoolean(); bool surrogate = this.reader.ReadBoolean(); StructNode result = new StructNode(classType, objTypeString, objId, custom, surrogate); // Read surrogate constructor data if (surrogate) { custom = true; // Set fake object reference for surrogate constructor: No self-references allowed here. this.idManager.Inject(null, objId); CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); if (customIO.Data.Any()) { DummyNode surrogateConstructor = new DummyNode(); surrogateConstructor.Parent = result; foreach (var pair in customIO.Data) { StringNode key = new StringNode(pair.Key); DataNode value = pair.Value as DataNode; key.Parent = surrogateConstructor; value.Parent = surrogateConstructor; } } } // Prepare object reference this.idManager.Inject(result, objId); if (custom) { CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); foreach (var pair in customIO.Data) { StringNode key = new StringNode(pair.Key); DataNode value = pair.Value as DataNode; key.Parent = result; value.Parent = result; } } else { // Determine data layout bool wasThereBefore = this.GetCachedTypeDataLayout(objTypeString) != null; TypeDataLayout layout = this.ReadTypeDataLayout(objTypeString); if (!wasThereBefore) { TypeDataLayoutNode layoutNode = new TypeDataLayoutNode(new TypeDataLayout(layout)); layoutNode.Parent = result; } // Read fields if (this.dataVersion <= 2) { for (int i = 0; i < layout.Fields.Length; i++) { DataNode fieldValue = this.ReadObject() as DataNode; fieldValue.Parent = result; fieldValue.Name = layout.Fields[i].name; } } else if (this.dataVersion >= 3) { bool[] fieldOmitted = new bool[layout.Fields.Length]; this.ReadArrayData(fieldOmitted); for (int i = 0; i < layout.Fields.Length; i++) { if (fieldOmitted[i]) { continue; } DataNode fieldValue = this.ReadObject() as DataNode; fieldValue.Parent = result; fieldValue.Name = layout.Fields[i].name; } } } return(result); }
/// <summary> /// Reads a <see cref="Duality.Serialization.MetaFormat.StructNode"/>, including possible child nodes. /// </summary> /// <param name="node"></param> protected StructNode ReadStruct(bool classType) { // Read struct type string objTypeString = this.reader.ReadString(); uint objId = this.reader.ReadUInt32(); bool custom = this.reader.ReadBoolean(); bool surrogate = this.reader.ReadBoolean(); StructNode result = new StructNode(classType, objTypeString, objId, custom, surrogate); // Read surrogate constructor data if (surrogate) { custom = true; // Set fake object reference for surrogate constructor: No self-references allowed here. this.idManager.Inject(null, objId); CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); if (customIO.Data.Any()) { DummyNode surrogateConstructor = new DummyNode(); surrogateConstructor.Parent = result; foreach (var pair in customIO.Data) { StringNode key = new StringNode(pair.Key); DataNode value = pair.Value as DataNode; key.Parent = surrogateConstructor; value.Parent = surrogateConstructor; } } } // Prepare object reference this.idManager.Inject(result, objId); if (custom) { CustomSerialIO customIO = new CustomSerialIO(); customIO.Deserialize(this); foreach (var pair in customIO.Data) { StringNode key = new StringNode(pair.Key); DataNode value = pair.Value as DataNode; key.Parent = result; value.Parent = result; } } else { // Determine data layout bool wasThereBefore = this.GetCachedTypeDataLayout(objTypeString) != null; TypeDataLayout layout = this.ReadTypeDataLayout(objTypeString); if (!wasThereBefore) { TypeDataLayoutNode layoutNode = new TypeDataLayoutNode(new TypeDataLayout(layout)); layoutNode.Parent = result; } // Read fields if (this.dataVersion <= 2) { for (int i = 0; i < layout.Fields.Length; i++) { DataNode fieldValue = this.ReadObject() as DataNode; fieldValue.Parent = result; fieldValue.Name = layout.Fields[i].name; } } else if (this.dataVersion >= 3) { bool[] fieldOmitted = new bool[layout.Fields.Length]; this.ReadArrayData(fieldOmitted); for (int i = 0; i < layout.Fields.Length; i++) { if (fieldOmitted[i]) continue; DataNode fieldValue = this.ReadObject() as DataNode; fieldValue.Parent = result; fieldValue.Name = layout.Fields[i].name; } } } return result; }