/// <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> /// <param name="tag">The tag used as a prefix to each record (only used with base-128 style prefixes).</param> public static void SerializeWithLengthPrefix <T>(Stream destination, T instance, PrefixStyle style, int tag) { if (style == PrefixStyle.None) { Serialize <T>(destination, instance); return; } using (MemoryStream ms = new MemoryStream()) { Serialize <T>(ms, instance); byte[] tmp = new byte[20]; int len; switch (style) { case PrefixStyle.Base128: len = 0; if (tag > 0) { uint prefix = GetFieldToken(tag, WireType.String); len += SerializationContext.EncodeUInt32(prefix, tmp, 0); } len += SerializationContext.EncodeUInt32((uint)ms.Length, tmp, len); break; case PrefixStyle.Fixed32: SerializationContext.EncodeUInt32Fixed((uint)ms.Length, tmp, 0); len = 4; break; default: throw new NotSupportedException("Invalid prefix style: " + style); } destination.Write(tmp, 0, len); destination.Write(ms.GetBuffer(), 0, (int)ms.Length); } destination.Flush(); }