internal static void WriteObject(object value, int key, ProtoWriter writer, PrefixStyle style, int fieldNumber) { if (writer.model == null) { throw new InvalidOperationException("Cannot serialize sub-objects unless a model is provided"); } if (writer.wireType != WireType.None) throw ProtoWriter.CreateException(writer); switch (style) { case PrefixStyle.Base128: writer.wireType = WireType.String; writer.fieldNumber = fieldNumber; if (fieldNumber > 0) WriteHeaderCore(fieldNumber, WireType.String, writer); break; case PrefixStyle.Fixed32: case PrefixStyle.Fixed32BigEndian: writer.fieldNumber = 0; writer.wireType = WireType.Fixed32; break; default: throw new ArgumentOutOfRangeException("style"); } SubItemToken token = StartSubItem(value, writer, true); writer.model.Serialize(key, value, writer); EndSubItem(token, writer, style); }
internal static void WriteObject(object value, int key, ProtoWriter writer, PrefixStyle style, int fieldNumber) { #if FEAT_IKVM throw new NotSupportedException(); #else if (writer.model == null) { throw new InvalidOperationException("Cannot serialize sub-objects unless a model is provided"); } if (writer.wireType != WireType.None) throw ProtoWriter.CreateException(writer); switch (style) { case PrefixStyle.Base128: writer.wireType = WireType.String; writer.fieldNumber = fieldNumber; if (fieldNumber > 0) WriteHeaderCore(fieldNumber, WireType.String, writer); break; case PrefixStyle.Fixed32: case PrefixStyle.Fixed32BigEndian: writer.fieldNumber = 0; writer.wireType = WireType.Fixed32; break; default: throw new ArgumentOutOfRangeException("style"); } SubItemToken token = StartSubItem(value, writer, true); if (key < 0) { if (!writer.model.TrySerializeAuxiliaryType(writer, value.GetType(), DataFormat.Default, Serializer.ListItemTag, value, false)) { TypeModel.ThrowUnexpectedType(value.GetType()); } } else { writer.model.Serialize(key, value, writer); } EndSubItem(token, writer, style); #endif }
public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber, out int bytesRead) { fieldNumber = 0; switch (style) { case PrefixStyle.None: bytesRead = 0; return 2147483647; case PrefixStyle.Base128: { bytesRead = 0; uint num2; int num; if (!expectHeader) { num = ProtoReader.TryReadUInt32Variant(source, out num2); bytesRead += num; return (int)((bytesRead >= 0) ? num2 : 4294967295u); } num = ProtoReader.TryReadUInt32Variant(source, out num2); bytesRead += num; if (num <= 0) { bytesRead = 0; return -1; } if ((num2 & 7u) != 2u) { throw new InvalidOperationException(); } fieldNumber = (int)(num2 >> 3); num = ProtoReader.TryReadUInt32Variant(source, out num2); bytesRead += num; if (bytesRead == 0) { throw ProtoReader.EoF(null); } return (int)num2; } case PrefixStyle.Fixed32: { int num3 = source.ReadByte(); if (num3 < 0) { bytesRead = 0; return -1; } bytesRead = 4; return num3 | ProtoReader.ReadByteOrThrow(source) << 8 | ProtoReader.ReadByteOrThrow(source) << 16 | ProtoReader.ReadByteOrThrow(source) << 24; } case PrefixStyle.Fixed32BigEndian: { int num4 = source.ReadByte(); if (num4 < 0) { bytesRead = 0; return -1; } bytesRead = 4; return num4 << 24 | ProtoReader.ReadByteOrThrow(source) << 16 | ProtoReader.ReadByteOrThrow(source) << 8 | ProtoReader.ReadByteOrThrow(source); } default: throw new ArgumentOutOfRangeException("style"); } }
private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixStyle style) { if (writer == null) { throw new ArgumentNullException("writer"); } if (writer.wireType != WireType.None) { throw CreateException(writer); } int value = token.value; if (writer.depth <= 0) { throw CreateException(writer); } if (writer.depth-- > RecursionCheckDepth) { writer.PopRecursionStack(); } writer.packedFieldNumber = 0; // ending the sub-item always wipes packed encoding if (value < 0) { // group - very simple append WriteHeaderCore(-value, WireType.EndGroup, writer); writer.wireType = WireType.None; return; } // so we're backfilling the length into an existing sequence int len; switch (style) { case PrefixStyle.Fixed32: len = (int)((writer.ioIndex - value) - 4); ProtoWriter.WriteInt32ToBuffer(len, writer.ioBuffer, value); break; case PrefixStyle.Fixed32BigEndian: len = (int)((writer.ioIndex - value) - 4); byte[] buffer = writer.ioBuffer; ProtoWriter.WriteInt32ToBuffer(len, buffer, value); // and swap the byte order byte b = buffer[value]; buffer[value] = buffer[value + 3]; buffer[value + 3] = b; b = buffer[value + 1]; buffer[value + 1] = buffer[value + 2]; buffer[value + 2] = b; break; case PrefixStyle.Base128: // string - complicated because we only reserved one byte; // if the prefix turns out to need more than this then // we need to shuffle the existing data len = (int)((writer.ioIndex - value) - 1); int offset = 0; uint tmp = (uint)len; while ((tmp >>= 7) != 0) { offset++; } if (offset == 0) { writer.ioBuffer[value] = (byte)(len & 0x7F); } else { DemandSpace(offset, writer); byte[] blob = writer.ioBuffer; Helpers.BlockCopy(blob, value + 1, blob, value + 1 + offset, len); tmp = (uint)len; do { blob[value++] = (byte)((tmp & 0x7F) | 0x80); } while ((tmp >>= 7) != 0); blob[value - 1] = (byte)(blob[value - 1] & ~0x80); writer.position += offset; writer.ioIndex += offset; } break; default: throw new ArgumentOutOfRangeException("style"); } // and this object is no longer a blockage - also flush if sensible const int ADVISORY_FLUSH_SIZE = 1024; if (--writer.flushLock == 0 && writer.ioIndex >= ADVISORY_FLUSH_SIZE) { ProtoWriter.Flush(writer); } }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream, /// with a length-prefix. This is useful for socket programming, /// as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back /// from an ongoing stream. /// </summary> /// <param name="instance">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="destination">The destination stream to write to.</param> /// <param name="fieldNumber">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public static void SerializeWithLengthPrefix(Stream destination, object instance, PrefixStyle style, int fieldNumber) { RuntimeTypeModel model = RuntimeTypeModel.Default; model.SerializeWithLengthPrefix(destination, instance, model.MapType(instance.GetType()), style, fieldNumber); }
/// <summary> /// Applies a protocol-buffer stream to an existing instance, using length-prefixed /// data - useful with network IO. /// </summary> /// <typeparam name="T">The type being merged.</typeparam> /// <param name="instance">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public static T MergeWithLengthPrefix <T>(Stream source, T instance, PrefixStyle style) { RuntimeTypeModel model = RuntimeTypeModel.Default; return((T)model.DeserializeWithLengthPrefix(source, instance, model.MapType(typeof(T)), style, 0)); }
/// <summary> /// Reads the length-prefix of a message from a stream without buffering additional data, allowing a fixed-length /// reader to be created. /// </summary> public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber, out int bytesRead) { fieldNumber = 0; switch (style) { case PrefixStyle.None: bytesRead = 0; return int.MaxValue; case PrefixStyle.Base128: uint val; int tmpBytesRead; bytesRead = 0; if (expectHeader) { tmpBytesRead = ProtoReader.TryReadUInt32Variant(source, out val); bytesRead += tmpBytesRead; if (tmpBytesRead > 0) { if ((val & 7) != (uint)WireType.String) { // got a header, but it isn't a string throw new InvalidOperationException(); } fieldNumber = (int)(val >> 3); tmpBytesRead = ProtoReader.TryReadUInt32Variant(source, out val); bytesRead += tmpBytesRead; if (bytesRead == 0) { // got a header, but no length throw EoF(null); } return (int)val; } else { // no header bytesRead = 0; return -1; } } // check for a length tmpBytesRead = ProtoReader.TryReadUInt32Variant(source, out val); bytesRead += tmpBytesRead; return bytesRead < 0 ? -1 : (int)val; case PrefixStyle.Fixed32: { int b = source.ReadByte(); if (b < 0) { bytesRead = 0; return -1; } bytesRead = 4; return b | (ReadByteOrThrow(source) << 8) | (ReadByteOrThrow(source) << 16) | (ReadByteOrThrow(source) << 24); } case PrefixStyle.Fixed32BigEndian: { int b = source.ReadByte(); if (b < 0) { bytesRead = 0; return -1; } bytesRead = 4; return (b << 24) | (ReadByteOrThrow(source) << 16) | (ReadByteOrThrow(source) << 8) | ReadByteOrThrow(source); } default: throw new ArgumentOutOfRangeException("style"); } }
/// <summary> /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed /// data - useful with network IO. /// </summary> /// <param name="type">The type being merged.</param> /// <param name="value">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="expectedField">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> /// <param name="resolver">Used to resolve types on a per-field basis.</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver) { int bytesRead; return DeserializeWithLengthPrefix(source, value, type, style, expectedField, resolver, out bytesRead); }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream, /// with a length-prefix. This is useful for socket programming, /// as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back /// from an ongoing stream. /// </summary> /// <param name="instance">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="destination">The destination stream to write to.</param> /// <param name="fieldNumber">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public static void SerializeWithLengthPrefix(Stream destination, object instance, PrefixStyle style, int fieldNumber) { if (instance is null) { throw new ArgumentNullException(nameof(instance)); } RuntimeTypeModel.Default.SerializeWithLengthPrefix(destination, instance, instance.GetType(), style, fieldNumber); }
/// <summary>Indicates the number of bytes expected for the next message.</summary> /// <param name="buffer">The buffer containing the data to investigate for a length.</param> /// <param name="index">The offset of the first byte to read from the buffer.</param> /// <param name="count">The number of bytes to read from the buffer.</param> /// <param name="style">The algorithm used to encode the length.</param> /// <param name="length">The length of the message, if it could be identified.</param> /// <returns>True if a length could be obtained, false otherwise.</returns> public static bool TryReadLengthPrefix(byte[] buffer, int index, int count, PrefixStyle style, out int length) { using Stream source = new MemoryStream(buffer, index, count); return(TryReadLengthPrefix(source, style, out length)); }
/// <summary>Indicates the number of bytes expected for the next message.</summary> /// <param name="source">The stream containing the data to investigate for a length.</param> /// <param name="style">The algorithm used to encode the length.</param> /// <param name="length">The length of the message, if it could be identified.</param> /// <returns>True if a length could be obtained, false otherwise.</returns> public static bool TryReadLengthPrefix(Stream source, PrefixStyle style, out int length) { length = ProtoReader.ReadLengthPrefix(source, false, style, out int _, out int bytesRead); return(bytesRead > 0); }
/// <summary> /// Applies a protocol-buffer stream to an existing instance, using length-prefixed /// data - useful with network IO. /// </summary> /// <typeparam name="T">The type being merged.</typeparam> /// <param name="instance">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public static T MergeWithLengthPrefix <[DynamicallyAccessedMembers(DynamicAccess.ContractType)] T>(Stream source, T instance, PrefixStyle style) { return((T)RuntimeTypeModel.Default.DeserializeWithLengthPrefix(source, instance, typeof(T), style, 0)); }
/// <summary> /// Creates a new instance from a protocol-buffer stream that has a length-prefix /// on data (to assist with network IO). /// </summary> /// <typeparam name="T">The type to be created.</typeparam> /// <param name="source">The binary stream to apply to the new instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="fieldNumber">The expected tag of the item (only used with base-128 prefix style).</param> /// <returns>A new, initialized instance.</returns> public static T DeserializeWithLengthPrefix <[DynamicallyAccessedMembers(DynamicAccess.ContractType)] T>(Stream source, PrefixStyle style, int fieldNumber) { return((T)RuntimeTypeModel.Default.DeserializeWithLengthPrefix(source, null, typeof(T), style, fieldNumber)); }
/// <summary> /// Creates a new instance from a protocol-buffer stream that has a length-prefix /// on data (to assist with network IO). /// </summary> /// <typeparam name="T">The type to be created.</typeparam> /// <param name="source">The binary stream to apply to the new instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <returns>A new, initialized instance.</returns> public static T DeserializeWithLengthPrefix <[DynamicallyAccessedMembers(DynamicAccess.ContractType)] T>(Stream source, PrefixStyle style) { return(DeserializeWithLengthPrefix <T>(source, style, 0)); }
/// <summary> /// Reads a sequence of consecutive length-prefixed items from a stream, using /// either base-128 or fixed-length prefixes. Base-128 prefixes with a tag /// are directly comparable to serializing multiple items in succession /// (use the <see cref="ListItemTag"/> tag to emulate the implicit behavior /// when serializing a list/array). When a tag is /// specified, any records with different tags are silently omitted. The /// tag is ignored. The tag is ignored for fixed-length prefixes. /// </summary> /// <typeparam name="T">The type of object to deserialize.</typeparam> /// <param name="source">The binary stream containing the serialized records.</param> /// <param name="style">The prefix style used in the data.</param> /// <param name="fieldNumber">The tag of records to return (if non-positive, then no tag is /// expected and all records are returned).</param> /// <returns>The sequence of deserialized objects.</returns> public static IEnumerable <T> DeserializeItems <[DynamicallyAccessedMembers(DynamicAccess.ContractType)] T>(Stream source, PrefixStyle style, int fieldNumber) { return(RuntimeTypeModel.Default.DeserializeItems <T>(source, style, fieldNumber)); }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream. /// </summary> /// <param name="instance">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="destination">The destination stream to write to.</param> /// <param name="tag">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public static void SerializeWithLengthPrefix(Stream destination, object instance, PrefixStyle style, int tag) { if (destination == null) throw new ArgumentNullException("destination"); if (instance == null) return; // nothing to do foreach (MethodInfo method in typeof(Serializer).GetMethods( BindingFlags.Static | BindingFlags.Public)) { ParameterInfo[] p; if (method.Name == "SerializeWithLengthPrefix" && method.IsGenericMethod) { MethodInfo genericMethod = method.MakeGenericMethod(instance.GetType()); if((p = genericMethod.GetParameters()).Length == 4 && p[0].ParameterType == typeof(Stream) && p[2].ParameterType == typeof(PrefixStyle) && p[3].ParameterType == typeof(int)) { genericMethod.Invoke( null, new object[] { destination, instance, style, tag }); return; } } } throw new ProtoException("Unable to resolve SerializeWithLengthPrefix method"); }
public static IExtensible ReadProtobufMessage(this BinaryReader reader, Type T, PrefixStyle style) { var type = typeof(ProtoBuf.Serializer); var deserialize = type.GetMethod("DeserializeWithLengthPrefix", new Type[] { typeof(Stream), typeof(PrefixStyle) }); deserialize = deserialize.MakeGenericMethod(T); return((IExtensible)deserialize.Invoke(null, new object[] { reader.BaseStream, style })); }
public static T ReadProtobufMessage <T>(this BinaryReader reader, PrefixStyle style) { return(ProtoBuf.Serializer.DeserializeWithLengthPrefix <T>(reader.BaseStream, style)); }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream, /// with a length-prefix. This is useful for socket programming, /// as DeserializeWithLengthPrefix can be used to read the single object back /// from an ongoing stream. /// </summary> /// <param name="type">The type being serialized.</param> /// <param name="value">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="dest">The destination stream to write to.</param> /// <param name="fieldNumber">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public void SerializeWithLengthPrefix(Stream dest, object value, Type type, PrefixStyle style, int fieldNumber) { if (type == null) { if(value == null) throw new ArgumentNullException("value"); type = value.GetType(); } int key = GetKey(ref type); using (ProtoWriter writer = new ProtoWriter(dest, this)) { switch (style) { case PrefixStyle.None: Serialize(key, value, writer); break; case PrefixStyle.Base128: case PrefixStyle.Fixed32: case PrefixStyle.Fixed32BigEndian: ProtoWriter.WriteObject(value, key, writer, style, fieldNumber); break; default: throw new ArgumentOutOfRangeException("style"); } writer.Close(); } }
public static IProtobufQueryable <T> AsQueryable <T>(this RuntimeTypeModel model, Stream source, PrefixStyle prefix = PrefixStyle.Base128) { var options = QueryableOptions.GetDefault(); options.PrefixStyle = prefix; return(model.AsQueryable <T>(source, options)); }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream, /// with a length-prefix. This is useful for socket programming, /// as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back /// from an ongoing stream. /// </summary> /// <param name="instance">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="destination">The destination stream to write to.</param> /// <param name="fieldNumber">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public static void SerializeWithLengthPrefix(Stream destination, object instance, PrefixStyle style, int fieldNumber) { throw new NotImplementedException();//TODO: NotImplementedException }
private protected override SubItemToken ImplStartLengthPrefixedSubItem(ref State state, object instance, PrefixStyle style) { WireType = WireType.None; return(new SubItemToken(_position64)); }
public static void SerializeWithLengthPrefix <T>(Stream destination, T instance, PrefixStyle style, int fieldNumber) { RuntimeTypeModel @default = RuntimeTypeModel.Default; @default.SerializeWithLengthPrefix(destination, instance, @default.MapType(typeof(T)), style, fieldNumber); }
private protected override void ImplEndLengthPrefixedSubItem(ref State state, SubItemToken token, PrefixStyle style) { var len = _position64 - token.value64; int bytes; switch (style) { case PrefixStyle.Fixed32BigEndian: case PrefixStyle.Fixed32: bytes = 4; break; case PrefixStyle.Base128: bytes = ImplWriteVarint64(ref state, (ulong)len); break; default: state.ThrowInvalidSerializationOperation(); goto case PrefixStyle.None; case PrefixStyle.None: bytes = 0; break; } Advance(bytes); }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream, /// with a length-prefix. This is useful for socket programming, /// as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back /// from an ongoing stream. /// </summary> /// <typeparam name="T">The type being serialized.</typeparam> /// <param name="instance">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="destination">The destination stream to write to.</param> public static void SerializeWithLengthPrefix <T>(Stream destination, T instance, PrefixStyle style) { SerializeWithLengthPrefix <T>(destination, instance, style, 0); }
protected internal override void WriteMessage <T>(ref State state, T value, ISerializer <T> serializer, PrefixStyle style, bool recursionCheck) { if (serializer == null) { serializer = TypeModel.GetSerializer <T>(Model); } var len = Measure <T>(this, value, serializer); AdvanceSubMessage(ref state, len, style); }
/// <summary> /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed /// data - useful with network IO. /// </summary> /// <param name="value">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="resolver">Used to resolve types on a per-field basis.</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public static bool TryDeserializeWithLengthPrefix(Stream source, PrefixStyle style, TypeResolver resolver, out object value) { value = RuntimeTypeModel.Default.DeserializeWithLengthPrefix(source, null, null, style, 0, resolver); return(value != null); }
public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber) { int num; return(ReadLengthPrefix(source, expectHeader, style, out fieldNumber, out num)); }
public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber) { int num; return ProtoReader.ReadLengthPrefix(source, expectHeader, style, out fieldNumber, out num); }
public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber, out int bytesRead) { fieldNumber = 0; switch (style) { case PrefixStyle.None: bytesRead = 0; return(2147483647); case PrefixStyle.Base128: { bytesRead = 0; uint num2; int num3; if (expectHeader) { num3 = TryReadUInt32Variant(source, out num2); bytesRead += num3; if (num3 > 0) { if ((num2 & 7) != 2) { throw new InvalidOperationException(); } fieldNumber = (int)(num2 >> 3); num3 = TryReadUInt32Variant(source, out num2); bytesRead += num3; if (bytesRead == 0) { throw EoF(null); } return((int)num2); } bytesRead = 0; return(-1); } num3 = TryReadUInt32Variant(source, out num2); bytesRead += num3; if (bytesRead >= 0) { return((int)num2); } return(-1); } case PrefixStyle.Fixed32: { int num4 = source.ReadByte(); if (num4 < 0) { bytesRead = 0; return(-1); } bytesRead = 4; return(num4 | ReadByteOrThrow(source) << 8 | ReadByteOrThrow(source) << 16 | ReadByteOrThrow(source) << 24); } case PrefixStyle.Fixed32BigEndian: { int num = source.ReadByte(); if (num < 0) { bytesRead = 0; return(-1); } bytesRead = 4; return(num << 24 | ReadByteOrThrow(source) << 16 | ReadByteOrThrow(source) << 8 | ReadByteOrThrow(source)); } default: throw new ArgumentOutOfRangeException("style"); } }
/// <summary> /// Reads a sequence of consecutive length-prefixed items from a stream, using /// either base-128 or fixed-length prefixes. Base-128 prefixes with a tag /// are directly comparable to serializing multiple items in succession /// (use the <see cref="ListItemTag"/> tag to emulate the implicit behavior /// when serializing a list/array). When a tag is /// specified, any records with different tags are silently omitted. The /// tag is ignored. The tag is ignores for fixed-length prefixes. /// </summary> /// <typeparam name="T">The type of object to deserialize.</typeparam> /// <param name="source">The binary stream containing the serialized records.</param> /// <param name="style">The prefix style used in the data.</param> /// <param name="fieldNumber">The tag of records to return (if non-positive, then no tag is /// expected and all records are returned).</param> /// <returns>The sequence of deserialized objects.</returns> public static IEnumerable <T> DeserializeItems <T>(Stream source, PrefixStyle style, int fieldNumber) { return(RuntimeTypeModel.Default.DeserializeItems <T>(source, style, fieldNumber)); }
/// <summary> /// Writes a protocol-buffer representation of the given instance to the supplied stream, /// with a length-prefix. This is useful for socket programming, /// as DeserializeWithLengthPrefix/MergeWithLengthPrefix can be used to read the single object back /// from an ongoing stream. /// </summary> /// <param name="instance">The existing instance to be serialized (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="destination">The destination stream to write to.</param> /// <param name="fieldNumber">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public static void SerializeWithLengthPrefix(Stream destination, object instance, PrefixStyle style, int fieldNumber) { if (instance == null) { throw new ArgumentNullException("instance"); } RuntimeTypeModel model = RuntimeTypeModel.Default; model.SerializeWithLengthPrefix(destination, instance, model.MapType(instance.GetType()), style, fieldNumber); }
/// <summary> /// Deserialize object of unknown types from in input stream. /// </summary> /// <param name="source">The input stream.</param> /// <param name="style">The prefix style used to encode the lengths.</param> /// <param name="typeReader">The caller must provide a mechanism to resolve a Type from /// the tags encountered in the stream. If the delegate returns null, then the instance /// is skipped - otherwise, the object is deserialized according to type.</param> /// <param name="item">The deserialized instance, or null if the stream terminated.</param> /// <returns>True if an object was idenfified; false if the stream terminated. Note /// that unexpected types are skipped.</returns> public static bool TryDeserializeWithLengthPrefix(Stream source, PrefixStyle style, Getter<int,Type> typeReader, out object item) { uint len; Type itemType = null; Getter<int, bool> processField = null; if(typeReader != null) processField = delegate(int checkTag) { itemType = typeReader(checkTag); return itemType != null; }; if(!Serializer.TryReadPrefixLength(source, style, 1, out len, processField)) { item = null; return false; } if (len == uint.MaxValue) { item = NonGeneric.Deserialize(itemType, source); } else { using (SubStream subStream = new SubStream(source, len, false)) { item = NonGeneric.Deserialize(itemType, subStream); } } return true; }
private bool TryDeserializeWithLengthPrefix(Stream source, PrefixStyle style, Serializer.TypeResolver resolver, out object value) { value = _model.DeserializeWithLengthPrefix(source, null, typeof(TDeserialized), style, 0, resolver); return(value != null); }
/// <summary> /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed /// data - useful with network IO. /// </summary> /// <param name="type">The type being merged.</param> /// <param name="value">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="fieldNumber">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int fieldNumber) { int bytesRead; return DeserializeWithLengthPrefix(source, value, type, style, fieldNumber, null, out bytesRead); }
public static void SerializeToStreamWithLength <T>(Stream stream, T obj, PrefixStyle style) { Serializer.SerializeWithLengthPrefix(stream, obj, style); }
/// <summary> /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed /// data - useful with network IO. /// </summary> /// <param name="type">The type being merged.</param> /// <param name="value">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="expectedField">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> /// <param name="resolver">Used to resolve types on a per-field basis.</param> /// <param name="bytesRead">Returns the number of bytes consumed by this operation (includes length-prefix overheads and any skipped data).</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out int bytesRead) { bool skip; int len; int tmpBytesRead; bytesRead = 0; do { int actualField; bool expectPrefix = expectedField > 0 || resolver != null; len = ProtoReader.ReadLengthPrefix(source, expectPrefix, style, out actualField, out tmpBytesRead); bytesRead += tmpBytesRead; if (len < 0) return value; if (expectedField == 0 && type == null && resolver != null) { type = resolver(actualField); skip = type == null; } else { skip = expectedField != actualField; } if (skip) { if (len == int.MaxValue) throw new InvalidOperationException(); ProtoReader.Seek(source, len, null); bytesRead += len; } } while (skip); int key = GetKey(ref type); if (key < 0) throw new InvalidOperationException(); using (ProtoReader reader = new ProtoReader(source, this, len)) { object result = Deserialize(key, value, reader); bytesRead += reader.Position; return result; } }
private protected override SubItemToken ImplStartLengthPrefixedSubItem(ref State state, object instance, PrefixStyle style) { switch (WireType) { case WireType.String: WireType = WireType.None; DemandSpace(32, this, ref state); // make some space in anticipation... flushLock++; Advance(1); return(new SubItemToken((long)(ioIndex++))); // leave 1 space (optimistic) for length case WireType.Fixed32: DemandSpace(32, this, ref state); // make some space in anticipation... flushLock++; SubItemToken token = new SubItemToken((long)ioIndex); IncrementedAndReset(4, this); // leave 4 space (rigid) for length return(token); default: state.ThrowInvalidSerializationOperation(); return(default); } }
/// <summary> /// Reads the length-prefix of a message from a stream without buffering additional data, allowing a fixed-length /// reader to be created. /// </summary> public static int ReadLengthPrefix(Stream source, bool expectHeader, PrefixStyle style, out int fieldNumber) { int bytesRead; return ReadLengthPrefix(source, expectHeader, style, out fieldNumber, out bytesRead); }
private protected override void ImplEndLengthPrefixedSubItem(ref State state, SubItemToken token, PrefixStyle style) { // so we're backfilling the length into an existing sequence int len; int value = (int)token.value64; switch (style) { case PrefixStyle.Fixed32: len = (int)(ioIndex - value - 4); WriteUInt32ToBuffer((uint)len, ioBuffer, value); break; case PrefixStyle.Fixed32BigEndian: len = (int)(ioIndex - value - 4); byte[] buffer = ioBuffer; WriteUInt32ToBuffer((uint)len, buffer, value); // and swap the byte order byte b = buffer[value]; buffer[value] = buffer[value + 3]; buffer[value + 3] = b; b = buffer[value + 1]; buffer[value + 1] = buffer[value + 2]; buffer[value + 2] = b; break; case PrefixStyle.Base128: // string - complicated because we only reserved one byte; // if the prefix turns out to need more than this then // we need to shuffle the existing data len = (int)(ioIndex - value - 1); int offset = 0; uint tmp = (uint)len; while ((tmp >>= 7) != 0) { offset++; } if (offset == 0) { ioBuffer[value] = (byte)(len & 0x7F); } else { DemandSpace(offset, this, ref state); byte[] blob = ioBuffer; Buffer.BlockCopy(blob, value + 1, blob, value + 1 + offset, len); tmp = (uint)len; do { blob[value++] = (byte)((tmp & 0x7F) | 0x80); } while ((tmp >>= 7) != 0); blob[value - 1] = (byte)(blob[value - 1] & ~0x80); Advance(offset); ioIndex += offset; } break; default: ThrowHelper.ThrowArgumentOutOfRangeException(nameof(style)); break; } // and this object is no longer a blockage - also flush if sensible const int ADVISORY_FLUSH_SIZE = 1024; if (--flushLock == 0 && ioIndex >= ADVISORY_FLUSH_SIZE) { state.Flush(); } }
private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixStyle style) { if (writer == null) { throw new ArgumentNullException("writer"); } if (writer.wireType != WireType.None) { throw ProtoWriter.CreateException(writer); } int value = token.value; if (writer.depth <= 0) { throw ProtoWriter.CreateException(writer); } if (writer.depth-- > 25) { writer.PopRecursionStack(); } writer.packedFieldNumber = 0; if (value < 0) { ProtoWriter.WriteHeaderCore(-value, WireType.EndGroup, writer); writer.wireType = WireType.None; return; } switch (style) { case PrefixStyle.Base128: { int num = writer.ioIndex - value - 1; int num2 = 0; uint num3 = (uint)num; while ((num3 >>= 7) != 0u) { num2++; } if (num2 == 0) { writer.ioBuffer[value] = (byte)(num & 127); } else { ProtoWriter.DemandSpace(num2, writer); byte[] array = writer.ioBuffer; Helpers.BlockCopy(array, value + 1, array, value + 1 + num2, num); num3 = (uint)num; do { array[value++] = (byte)((num3 & 127u) | 128u); } while ((num3 >>= 7) != 0u); array[value - 1] = (byte)((int)array[value - 1] & -129); writer.position += num2; writer.ioIndex += num2; } break; } case PrefixStyle.Fixed32: { int num = writer.ioIndex - value - 4; ProtoWriter.WriteInt32ToBuffer(num, writer.ioBuffer, value); break; } case PrefixStyle.Fixed32BigEndian: { int num = writer.ioIndex - value - 4; byte[] array2 = writer.ioBuffer; ProtoWriter.WriteInt32ToBuffer(num, array2, value); byte b = array2[value]; array2[value] = array2[value + 3]; array2[value + 3] = b; b = array2[value + 1]; array2[value + 1] = array2[value + 2]; array2[value + 2] = b; break; } default: throw new ArgumentOutOfRangeException("style"); } if (--writer.flushLock == 0 && writer.ioIndex >= 1024) { ProtoWriter.Flush(writer); } }
/// <summary> /// Creates a new instance from a protocol-buffer stream that has a length-prefix /// on data (to assist with network IO). /// </summary> /// <typeparam name="T">The type to be created.</typeparam> /// <param name="source">The binary stream to apply to the new instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <returns>A new, initialized instance.</returns> public static T DeserializeWithLengthPrefix <T>(Stream source, PrefixStyle style) { return(DeserializeWithLengthPrefix <T>(source, style, 0)); }
/// <summary> /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed /// data - useful with network IO. /// </summary> /// <param name="value">The existing instance to be modified (can be null).</param> /// <param name="source">The binary stream to apply to the instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="resolver">Used to resolve types on a per-field basis.</param> /// <returns>The updated instance; this may be different to the instance argument if /// either the original instance was null, or the stream defines a known sub-type of the /// original instance.</returns> public static bool TryDeserializeWithLengthPrefix(Stream source, PrefixStyle style, TypeResolver resolver, out object value) { throw new NotImplementedException();//TODO: NotImplementedException }
/// <summary> /// Creates a new instance from a protocol-buffer stream that has a length-prefix /// on data (to assist with network IO). /// </summary> /// <typeparam name="T">The type to be created.</typeparam> /// <param name="source">The binary stream to apply to the new instance (cannot be null).</param> /// <param name="style">How to encode the length prefix.</param> /// <param name="fieldNumber">The expected tag of the item (only used with base-128 prefix style).</param> /// <returns>A new, initialized instance.</returns> public static T DeserializeWithLengthPrefix <T>(Stream source, PrefixStyle style, int fieldNumber) { RuntimeTypeModel model = RuntimeTypeModel.Default; return((T)model.DeserializeWithLengthPrefix(source, null, model.MapType(typeof(T)), style, fieldNumber)); }
private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixStyle style) { if (writer.wireType != WireType.None) { throw CreateException(writer); } int value = token.value; if (writer.depth <= 0) throw CreateException(writer); if (writer.depth-- > RecursionCheckDepth) { writer.PopRecursionStack(); } writer.packedFieldNumber = 0; // ending the sub-item always wipes packed encoding if (value < 0) { // group - very simple append WriteHeaderCore(-value, WireType.EndGroup, writer); writer.wireType = WireType.None; return; } // so we're backfilling the length into an existing sequence int len; switch(style) { case PrefixStyle.Fixed32: len = (int)((writer.ioIndex - value) - 4); ProtoWriter.WriteInt32ToBuffer(len, writer.ioBuffer, value); break; case PrefixStyle.Fixed32BigEndian: len = (int)((writer.ioIndex - value) - 4); byte[] buffer = writer.ioBuffer; ProtoWriter.WriteInt32ToBuffer(len, buffer, value); // and swap the byte order byte b = buffer[value]; buffer[value] = buffer[value + 3]; buffer[value + 3] = b; b = buffer[value + 1]; buffer[value + 1] = buffer[value + 2]; buffer[value + 2] = b; break; case PrefixStyle.Base128: // string - complicated because we only reserved one byte; // if the prefix turns out to need more than this then // we need to shuffle the existing data len = (int)((writer.ioIndex - value) - 1); int offset = 0; uint tmp = (uint)len; while ((tmp >>= 7) != 0) offset++; if (offset == 0) { writer.ioBuffer[value] = (byte)(len & 0x7F); } else { DemandSpace(offset, writer); byte[] blob = writer.ioBuffer; Helpers.BlockCopy(blob, value + 1, blob, value + 1 + offset, len); tmp = (uint)len; do { blob[value++] = (byte)((tmp & 0x7F) | 0x80); } while ((tmp >>= 7) != 0); blob[value - 1] = (byte)(blob[value - 1] & ~0x80); writer.position += offset; writer.ioIndex += offset; } break; default: throw new ArgumentOutOfRangeException("style"); } // and this object is no longer a blockage writer.flushLock--; }
public T DeserializeWithLengthPrefix <T>(Stream stream, PrefixStyle prefixStyle) { return(Serializer.DeserializeWithLengthPrefix <T>(stream, prefixStyle)); }