public void Sync(SyncContext ctx) { if (ctx.is_read) { types = ((SymbolFactory)ctx.factory).types; } else if (string.IsNullOrEmpty(_name)) { throw new Exception("TypeProxy name is empty"); } Marshall.Sync(ctx, ref _name); IMarshallableGeneric mg = null; if (ctx.is_read) { Marshall.SyncGeneric(ctx, ref mg); type = (IType)mg; } else { var resolved = Get(); //TODO: make this check more robust bool defined_in_scope = resolved is Symbol symb && (symb.scope is ModuleScope || symb is BuiltInSymbol || symb is ClassSymbolNative || symb is InterfaceSymbolNative || symb is EnumSymbol || (symb is ArrayTypeSymbol && !(symb is GenericArrayTypeSymbol)) ); //NOTE: we want to marshall only those types which are not // defined elsewhere otherwise we just want to keep // string reference at them if (!defined_in_scope) { mg = resolved as IMarshallableGeneric; if (mg == null) { throw new Exception("Type is not marshallable: " + (resolved != null ? resolved.GetType().Name + " " : "<null> ") + _name); } } Marshall.SyncGeneric(ctx, ref mg); } }
//TODO: make it private and deduce by IMarshallableGeneric interface static public void SyncGeneric(SyncContext ctx, ref IMarshallableGeneric v) { if (ctx.is_read) { ctx.reader.BeginContainer(); uint clid = 0; ctx.reader.ReadU32(ref clid); //check for null if (clid != 0xFFFFFFFF) { v = ctx.factory.CreateById(clid); if (v == null) { throw new Error(ErrorCode.BAD_CLASS_ID, "Could not create object with class id: " + clid); } v.Sync(ctx); } else { v = null; } ctx.reader.EndContainer(); } else { int fields_num = v == null ? 0 : (v is IFixedStruct fs ? fs.GetFieldsNum() : -1); //class id if (fields_num != -1) { ++fields_num; } ctx.writer.BeginContainer(fields_num); ctx.writer.WriteU32(v == null ? 0xFFFFFFFF : v.ClassId()); if (v != null) { v.Sync(ctx); } ctx.writer.EndContainer(); } }