private ReaderClassDef GetClassDef(short classId) { if (classId < classDefs.Count) { return(classDefs[classId]); } if (classId > classDefs.Count) { throw Error("Bad classId: {0}", classId); } var typeName = Reader.ReadString(); var classType = Meta.GetTypeByReadAlias(typeName, Options) ?? TypeSerializer.Deserialize(typeName); if (classType == null) { return(GetClassDefUnknown(typeName)); } var result = new ReaderClassDef { Meta = Meta.Get(classType, Options) }; PrepareReaders(result); if (BinaryOptions.Unordered) { InitClassDefUnordered(result, typeName); } else { InitClassDef(result, typeName); } classDefs.Add(result); return(result); }
private ReaderClassDef GetClassDefUnknown(string typeName) { var result = new ReaderClassDef { Meta = Meta.Unknown, Make = (bd, def) => { var obj = new YuzuUnknownBinary { ClassTag = typeName, Def = def }; ReadFields(bd, def, obj); return(obj); }, }; var theirCount = Reader.ReadInt16(); for (int theirIndex = 0; theirIndex < theirCount; ++theirIndex) { var theirName = Reader.ReadString(); var t = ReadType(); var rf = ReadValueFunc(t); result.Fields.Add(new ReaderClassDef.FieldDef { Name = theirName, Type = t, OurIndex = -1, ReadFunc = obj => ((YuzuUnknown)obj).Fields[theirName] = rf() }); } classDefs.Add(result); return(result); }
protected override void PrepareReaders(ReaderClassDef def) { base.PrepareReaders(def); if (readCache.TryGetValue(def.Meta.Type, out ReadCacheAction r)) { def.ReadFields = r; } if (makeCache.TryGetValue(def.Meta.Type, out MakeCacheAction m)) { def.Make = m; } }
protected override void PrepareReaders(ReaderClassDef def) { base.PrepareReaders(def); Action <BinaryDeserializer, ReaderClassDef, object> r; if (readCache.TryGetValue(def.Meta.Type, out r)) { def.ReadFields = r; } Func <BinaryDeserializer, ReaderClassDef, object> m; if (makeCache.TryGetValue(def.Meta.Type, out m)) { def.Make = m; } }
private static void ReadFields(BinaryDeserializer d, ReaderClassDef def, object obj) { def.Meta.BeforeDeserialization.Run(obj); d.objStack.Push(obj); try { if (def.Meta.IsCompact) { for (int i = 1; i < def.Fields.Count; ++i) { def.Fields[i].ReadFunc(obj); } } else { if (def.Meta.GetUnknownStorage != null) { var storage = def.Meta.GetUnknownStorage(obj); storage.Clear(); storage.Internal = def; } var actualIndex = d.Reader.ReadInt16(); for (int i = 1; i < def.Fields.Count; ++i) { var fd = def.Fields[i]; if (i < actualIndex || actualIndex == 0) { if (fd.OurIndex < 0 || def.Meta.Items[fd.OurIndex - 1].IsOptional) { continue; } throw d.Error("Expected field '{0}' ({1}), but found '{2}'", i, fd.Name, actualIndex); } fd.ReadFunc(obj); actualIndex = d.Reader.ReadInt16(); } if (actualIndex != 0) { throw d.Error("Unfinished object, expected zero, but got {0}", actualIndex); } } } finally { d.objStack.Pop(); } def.Meta.AfterDeserialization.Run(obj); }
private object MakeAndCheckAssignable <T>(ReaderClassDef def) { var srcType = def.Meta.Type; var dstType = typeof(T); if (srcType != typeof(YuzuUnknown) && !dstType.IsAssignableFrom(srcType)) { throw Error("Unable to assign type \"{0}\" to \"{1}\"", srcType.ToString(), dstType); } var result = def.Make?.Invoke(this, def); if (srcType == typeof(YuzuUnknown) && !dstType.IsInstanceOfType(result)) { throw Error("Unable to assign type \"{0}\" to \"{1}\"", ((YuzuUnknownBinary)result).ClassTag, dstType); } return(result); }
private void AddUnknownFieldDef(ReaderClassDef def, string fieldName, string typeName) { if (!Options.AllowUnknownFields) { throw Error("New field {0} for class {1}", fieldName, typeName); } var fd = new ReaderClassDef.FieldDef { Name = fieldName, OurIndex = -1, Type = ReadType() }; var rf = ReadValueFunc(fd.Type); if (def.Meta.GetUnknownStorage == null) { fd.ReadFunc = obj => rf(); } else { fd.ReadFunc = obj => def.Meta.GetUnknownStorage(obj).Add(fieldName, rf()); } def.Fields.Add(fd); }
private void InitClassDefUnordered(ReaderClassDef def, string typeName) { var theirCount = Reader.ReadInt16(); int ourIndex = 0, requiredCountActiual = 0; for (int theirIndex = 0; theirIndex < theirCount; ++theirIndex) { var theirName = Reader.ReadString(); Meta.Item yi = null; if (def.Meta.TagToItem.TryGetValue(theirName, out yi)) { if (!ReadCompatibleType(yi.Type)) { throw Error( "Incompatible type for field {0}, expected {1}", theirName, yi.Type); } def.Fields.Add(new ReaderClassDef.FieldDef { Name = theirName, OurIndex = def.Meta.Items.IndexOf(yi) + 1, Type = yi.Type, ReadFunc = MakeReadOrMergeFunc(yi), }); ourIndex += 1; if (!yi.IsOptional) { requiredCountActiual += 1; } } else { AddUnknownFieldDef(def, theirName, typeName); } } if (requiredCountActiual != def.Meta.RequiredCount) { throw Error( "Expected {0} required field(s), but found {1} for class {2}", def.Meta.RequiredCount, requiredCountActiual, typeName); } }
private void InitClassDef(ReaderClassDef def, string typeName) { var ourCount = def.Meta.Items.Count; var theirCount = Reader.ReadInt16(); int ourIndex = 0, theirIndex = 0; var theirName = ""; while (ourIndex < ourCount && theirIndex < theirCount) { var yi = def.Meta.Items[ourIndex]; var ourName = yi.Tag(Options); if (theirName == "") { theirName = Reader.ReadString(); } var cmp = String.CompareOrdinal(ourName, theirName); if (cmp < 0) { if (!yi.IsOptional) { throw Error("Missing required field {0} for class {1}", ourName, typeName); } ourIndex += 1; } else if (cmp > 0) { AddUnknownFieldDef(def, theirName, typeName); theirIndex += 1; theirName = ""; } else { if (!ReadCompatibleType(yi.Type)) { throw Error( "Incompatible type for field {0}, expected {1}", ourName, yi.Type); } def.Fields.Add(new ReaderClassDef.FieldDef { Name = theirName, OurIndex = ourIndex + 1, Type = yi.Type, ReadFunc = MakeReadOrMergeFunc(yi), }); ourIndex += 1; theirIndex += 1; theirName = ""; } } for (; ourIndex < ourCount; ++ourIndex) { var yi = def.Meta.Items[ourIndex]; var ourName = yi.Tag(Options); if (!yi.IsOptional) { throw Error("Missing required field {0} for class {1}", ourName, typeName); } } for (; theirIndex < theirCount; ++theirIndex) { if (theirName == "") { theirName = Reader.ReadString(); } AddUnknownFieldDef(def, theirName, typeName); theirName = ""; } }
protected virtual void PrepareReaders(ReaderClassDef def) => def.ReadFields = ReadFields;
private ReaderClassDef GetClassDef(short classId) { if (classId < classDefs.Count) { return(classDefs[classId]); } if (classId > classDefs.Count) { throw Error("Bad classId: {0}", classId); } var typeName = Reader.ReadString(); var classType = Meta.GetTypeByReadAlias(typeName, Options) ?? TypeSerializer.Deserialize(typeName); if (classType == null) { return(GetClassDefUnknown(typeName)); } var result = new ReaderClassDef { Meta = Meta.Get(classType, Options) }; PrepareReaders(result); var ourCount = result.Meta.Items.Count; var theirCount = Reader.ReadInt16(); int ourIndex = 0, theirIndex = 0; var theirName = ""; while (ourIndex < ourCount && theirIndex < theirCount) { var yi = result.Meta.Items[ourIndex]; var ourName = yi.Tag(Options); if (theirName == "") { theirName = Reader.ReadString(); } var cmp = String.CompareOrdinal(ourName, theirName); if (cmp < 0) { if (!yi.IsOptional) { throw Error("Missing required field {0} for class {1}", ourName, typeName); } ourIndex += 1; } else if (cmp > 0) { AddUnknownFieldDef(result, theirName, typeName); theirIndex += 1; theirName = ""; } else { if (!ReadCompatibleType(yi.Type)) { throw Error( "Incompatible type for field {0}, expected {1}", ourName, yi.Type.Name); } var fieldDef = new ReaderClassDef.FieldDef { Name = theirName, OurIndex = ourIndex + 1, Type = yi.Type }; if (yi.SetValue != null) { var rf = ReadValueFunc(yi.Type); fieldDef.ReadFunc = obj => yi.SetValue(obj, rf()); } else { var mf = MergeValueFunc(yi.Type); fieldDef.ReadFunc = obj => mf(yi.GetValue(obj)); } result.Fields.Add(fieldDef); ourIndex += 1; theirIndex += 1; theirName = ""; } } for (; ourIndex < ourCount; ++ourIndex) { var yi = result.Meta.Items[ourIndex]; var ourName = yi.Tag(Options); if (!yi.IsOptional) { throw Error("Missing required field {0} for class {1}", ourName, typeName); } } for (; theirIndex < theirCount; ++theirIndex) { if (theirName == "") { theirName = Reader.ReadString(); } AddUnknownFieldDef(result, theirName, typeName); theirName = ""; } classDefs.Add(result); return(result); }