private void SerializeCore(ProtoWriter writer, object value) { if (value == null) { throw new ArgumentNullException("value"); } Type type = value.GetType(); int key = this.GetKey(ref type); if (key >= 0) { this.Serialize(key, value, writer); return; } if (!this.TrySerializeAuxiliaryType(writer, type, DataFormat.Default, 1, value, false)) { TypeModel.ThrowUnexpectedType(type); } }
internal bool TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, int tag, Type type, ref object value, bool skipOtherFields, bool asListItem, bool autoCreate, bool insideList) { if (type == null) { throw new ArgumentNullException("type"); } ProtoTypeCode typecode = Helpers.GetTypeCode(type); int modelKey; WireType wiretype = this.GetWireType(typecode, format, ref type, out modelKey); bool found = false; if (wiretype == WireType.None) { Type itemType = TypeModel.GetListItemType(this, type); if (itemType == null && type.IsArray && type.GetArrayRank() == 1 && type != typeof(byte[])) { itemType = type.GetElementType(); } if (itemType != null) { if (insideList) { throw TypeModel.CreateNestedListsNotSupported(); } found = this.TryDeserializeList(this, reader, format, tag, type, itemType, ref value); if (!found && autoCreate) { value = TypeModel.CreateListInstance(type, itemType); } return(found); } else { TypeModel.ThrowUnexpectedType(type); } } while (!found || !asListItem) { int fieldNumber = reader.ReadFieldHeader(); if (fieldNumber <= 0) { break; } if (fieldNumber != tag) { if (!skipOtherFields) { throw ProtoReader.AddErrorData(new InvalidOperationException("Expected field " + tag.ToString() + ", but found " + fieldNumber.ToString()), reader); } reader.SkipField(); } else { found = true; reader.Hint(wiretype); if (modelKey >= 0) { switch (wiretype) { case WireType.String: case WireType.StartGroup: { SubItemToken token = ProtoReader.StartSubItem(reader); value = this.Deserialize(modelKey, value, reader); ProtoReader.EndSubItem(token, reader); break; } default: value = this.Deserialize(modelKey, value, reader); break; } } else { ProtoTypeCode protoTypeCode = typecode; switch (protoTypeCode) { case ProtoTypeCode.Boolean: value = reader.ReadBoolean(); break; case ProtoTypeCode.Char: value = (char)reader.ReadUInt16(); break; case ProtoTypeCode.SByte: value = reader.ReadSByte(); break; case ProtoTypeCode.Byte: value = reader.ReadByte(); break; case ProtoTypeCode.Int16: value = reader.ReadInt16(); break; case ProtoTypeCode.UInt16: value = reader.ReadUInt16(); break; case ProtoTypeCode.Int32: value = reader.ReadInt32(); break; case ProtoTypeCode.UInt32: value = reader.ReadUInt32(); break; case ProtoTypeCode.Int64: value = reader.ReadInt64(); break; case ProtoTypeCode.UInt64: value = reader.ReadUInt64(); break; case ProtoTypeCode.Single: value = reader.ReadSingle(); break; case ProtoTypeCode.Double: value = reader.ReadDouble(); break; case ProtoTypeCode.Decimal: value = BclHelpers.ReadDecimal(reader); break; case ProtoTypeCode.DateTime: value = BclHelpers.ReadDateTime(reader); break; case (ProtoTypeCode)17: break; case ProtoTypeCode.String: value = reader.ReadString(); break; default: switch (protoTypeCode) { case ProtoTypeCode.TimeSpan: value = BclHelpers.ReadTimeSpan(reader); break; case ProtoTypeCode.ByteArray: value = ProtoReader.AppendBytes((byte[])value, reader); break; case ProtoTypeCode.Guid: value = BclHelpers.ReadGuid(reader); break; case ProtoTypeCode.Uri: value = new Uri(reader.ReadString()); break; } break; } } } } if (!found && !asListItem && autoCreate && type != typeof(string)) { value = Activator.CreateInstance(type); } return(found); }
private object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out int bytesRead, out bool haveObject, SerializationContext context) { haveObject = false; bytesRead = 0; if (type == null && (style != PrefixStyle.Base128 || resolver == null)) { throw new InvalidOperationException("A type must be provided unless base-128 prefixing is being used in combination with a resolver"); } while (true) { bool expectPrefix = expectedField > 0 || resolver != null; int actualField; int tmpBytesRead; int len = ProtoReader.ReadLengthPrefix(source, expectPrefix, style, out actualField, out tmpBytesRead); if (tmpBytesRead == 0) { break; } bytesRead += tmpBytesRead; if (len < 0) { return(value); } bool skip; if (style == PrefixStyle.Base128) { if (expectPrefix && expectedField == 0 && type == null && resolver != null) { type = resolver(actualField); skip = (type == null); } else { skip = (expectedField != actualField); } } else { skip = false; } if (skip) { if (len == 2147483647) { goto Block_12; } ProtoReader.Seek(source, len, null); bytesRead += len; } if (!skip) { goto Block_13; } } return(value); Block_12: throw new InvalidOperationException(); Block_13: ProtoReader reader = null; object result; try { int len; reader = ProtoReader.Create(source, this, context, len); int key = this.GetKey(ref type); if (key >= 0 && !Helpers.IsEnum(type)) { value = this.Deserialize(key, value, reader); } else { if (!this.TryDeserializeAuxiliaryType(reader, DataFormat.Default, 1, type, ref value, true, false, true, false) && len != 0) { TypeModel.ThrowUnexpectedType(type); } } bytesRead += reader.Position; haveObject = true; result = value; } finally { ProtoReader.Recycle(reader); } return(result); }
internal bool TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, int tag, object value, bool isInsideList) { if (type == null) { type = value.GetType(); } ProtoTypeCode typecode = Helpers.GetTypeCode(type); int modelKey; WireType wireType = this.GetWireType(typecode, format, ref type, out modelKey); if (modelKey >= 0) { if (Helpers.IsEnum(type)) { this.Serialize(modelKey, value, writer); return(true); } ProtoWriter.WriteFieldHeader(tag, wireType, writer); switch (wireType) { case WireType.None: throw ProtoWriter.CreateException(writer); case WireType.String: case WireType.StartGroup: { SubItemToken token = ProtoWriter.StartSubItem(value, writer); this.Serialize(modelKey, value, writer); ProtoWriter.EndSubItem(token, writer); return(true); } } this.Serialize(modelKey, value, writer); return(true); } else { if (wireType != WireType.None) { ProtoWriter.WriteFieldHeader(tag, wireType, writer); } ProtoTypeCode protoTypeCode = typecode; switch (protoTypeCode) { case ProtoTypeCode.Boolean: ProtoWriter.WriteBoolean((bool)value, writer); return(true); case ProtoTypeCode.Char: ProtoWriter.WriteUInt16((ushort)((char)value), writer); return(true); case ProtoTypeCode.SByte: ProtoWriter.WriteSByte((sbyte)value, writer); return(true); case ProtoTypeCode.Byte: ProtoWriter.WriteByte((byte)value, writer); return(true); case ProtoTypeCode.Int16: ProtoWriter.WriteInt16((short)value, writer); return(true); case ProtoTypeCode.UInt16: ProtoWriter.WriteUInt16((ushort)value, writer); return(true); case ProtoTypeCode.Int32: ProtoWriter.WriteInt32((int)value, writer); return(true); case ProtoTypeCode.UInt32: ProtoWriter.WriteUInt32((uint)value, writer); return(true); case ProtoTypeCode.Int64: ProtoWriter.WriteInt64((long)value, writer); return(true); case ProtoTypeCode.UInt64: ProtoWriter.WriteUInt64((ulong)value, writer); return(true); case ProtoTypeCode.Single: ProtoWriter.WriteSingle((float)value, writer); return(true); case ProtoTypeCode.Double: ProtoWriter.WriteDouble((double)value, writer); return(true); case ProtoTypeCode.Decimal: BclHelpers.WriteDecimal((decimal)value, writer); return(true); case ProtoTypeCode.DateTime: BclHelpers.WriteDateTime((DateTime)value, writer); return(true); case (ProtoTypeCode)17: break; case ProtoTypeCode.String: ProtoWriter.WriteString((string)value, writer); return(true); default: switch (protoTypeCode) { case ProtoTypeCode.TimeSpan: BclHelpers.WriteTimeSpan((TimeSpan)value, writer); return(true); case ProtoTypeCode.ByteArray: ProtoWriter.WriteBytes((byte[])value, writer); return(true); case ProtoTypeCode.Guid: BclHelpers.WriteGuid((Guid)value, writer); return(true); case ProtoTypeCode.Uri: ProtoWriter.WriteString(((Uri)value).AbsoluteUri, writer); return(true); } break; } IEnumerable sequence = value as IEnumerable; if (sequence == null) { return(false); } if (isInsideList) { throw TypeModel.CreateNestedListsNotSupported(); } foreach (object item in sequence) { if (item == null) { throw new NullReferenceException(); } if (!this.TrySerializeAuxiliaryType(writer, null, format, tag, item, true)) { TypeModel.ThrowUnexpectedType(item.GetType()); } } return(true); } }
public object DeepClone(object value) { if (value == null) { return(null); } Type type = value.GetType(); int key = this.GetKey(ref type); object result; if (key >= 0 && !Helpers.IsEnum(type)) { using (MemoryStream ms = new MemoryStream()) { using (ProtoWriter writer = new ProtoWriter(ms, this, null)) { writer.SetRootObject(value); this.Serialize(key, value, writer); writer.Close(); } ms.Position = 0L; ProtoReader reader = null; try { reader = ProtoReader.Create(ms, this, null, -1); result = this.Deserialize(key, null, reader); return(result); } finally { ProtoReader.Recycle(reader); } } } if (type == typeof(byte[])) { byte[] orig = (byte[])value; byte[] clone = new byte[orig.Length]; Helpers.BlockCopy(orig, 0, clone, 0, orig.Length); return(clone); } int modelKey; if (this.GetWireType(Helpers.GetTypeCode(type), DataFormat.Default, ref type, out modelKey) != WireType.None && modelKey < 0) { return(value); } using (MemoryStream ms2 = new MemoryStream()) { using (ProtoWriter writer2 = new ProtoWriter(ms2, this, null)) { if (!this.TrySerializeAuxiliaryType(writer2, type, DataFormat.Default, 1, value, false)) { TypeModel.ThrowUnexpectedType(type); } writer2.Close(); } ms2.Position = 0L; ProtoReader reader2 = null; try { reader2 = ProtoReader.Create(ms2, this, null, -1); value = null; this.TryDeserializeAuxiliaryType(reader2, DataFormat.Default, 1, type, ref value, true, false, true, false); result = value; } finally { ProtoReader.Recycle(reader2); } } return(result); }
internal int FindOrAddAuto(Type type, bool demand, bool addWithContractOnly, bool addEvenIfAutoDisabled) { int key = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, type); if (key >= 0) { MetaType metaType = (MetaType)this.types[key]; if (metaType.Pending) { this.WaitOnLock(metaType); } return(key); } bool shouldAdd = this.AutoAddMissingTypes || addEvenIfAutoDisabled; if (Helpers.IsEnum(type) || this.TryGetBasicTypeSerializer(type) == null) { Type underlyingType = TypeModel.ResolveProxies(type); if (underlyingType != null) { key = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, underlyingType); type = underlyingType; } if (key < 0) { int opaqueToken = 0; try { this.TakeLock(ref opaqueToken); MetaType metaType; if ((metaType = this.RecogniseCommonTypes(type)) == null) { MetaType.AttributeFamily family = MetaType.GetContractFamily(this, type, null); if (family == MetaType.AttributeFamily.AutoTuple) { addEvenIfAutoDisabled = (shouldAdd = true); } if (!shouldAdd || (!Helpers.IsEnum(type) && addWithContractOnly && family == MetaType.AttributeFamily.None)) { if (demand) { TypeModel.ThrowUnexpectedType(type); } return(key); } metaType = this.Create(type); } metaType.Pending = true; bool weAdded = false; int winner = this.types.IndexOf(RuntimeTypeModel.MetaTypeFinder, type); if (winner < 0) { this.ThrowIfFrozen(); key = this.types.Add(metaType); weAdded = true; } else { key = winner; } if (weAdded) { metaType.ApplyDefaultBehaviour(); metaType.Pending = false; } } finally { this.ReleaseLock(opaqueToken); } return(key); } return(key); } if (shouldAdd && !addWithContractOnly) { throw MetaType.InbuiltType(type); } return(-1); }