/// <summary> /// Generates code for writing a class/message /// </summary> static void GenerateWriter(ProtoMessage m, CodeWriter cw, Options options) { string stack = "global::SilentOrbit.ProtocolBuffers.ProtocolParser.Stack"; if (options.ExperimentalStack != null) { cw.WriteLine("[ThreadStatic]"); cw.WriteLine("static global::SilentOrbit.ProtocolBuffers.MemoryStreamStack stack = new " + options.ExperimentalStack + "();"); stack = "stack"; } cw.Summary("Serialize the instance into the stream"); cw.Bracket(m.OptionAccess + " static void Serialize(Stream stream, " + m.CsType + " instance)"); if (m.OptionTriggers) { cw.WriteLine("instance.BeforeSerialize();"); cw.WriteLine(); } if (m.IsUsingBinaryWriter) { cw.WriteLine("BinaryWriter bw = new BinaryWriter(stream);"); } //Shared memorystream for all fields cw.WriteLine("var msField = " + stack + ".Pop();"); foreach (Field f in m.Fields.Values) { FieldSerializer.FieldWriter(m, f, cw); } cw.WriteLine(stack + ".Push(msField);"); if (m.OptionPreserveUnknown) { cw.IfBracket("instance.PreservedFields != null"); cw.ForeachBracket("var kv in instance.PreservedFields"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteKey(stream, kv.Key);"); cw.WriteLine("stream.Write(kv.Value, 0, kv.Value.Length);"); cw.EndBracket(); cw.EndBracket(); } cw.EndBracket(); cw.WriteLine(); cw.Summary("Helper: Serialize into a MemoryStream and return its byte array"); cw.Bracket(m.OptionAccess + " static byte[] SerializeToBytes(" + m.CsType + " instance)"); cw.Using("var ms = new MemoryStream()"); cw.WriteLine("Serialize(ms, instance);"); cw.WriteLine("return ms.ToArray();"); cw.EndBracket(); cw.EndBracket(); cw.Summary("Helper: Serialize with a varint length prefix"); cw.Bracket(m.OptionAccess + " static void SerializeLengthDelimited(Stream stream, " + m.CsType + " instance)"); cw.WriteLine("var data = SerializeToBytes(instance);"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(stream, (uint)data.Length);"); cw.WriteLine("stream.Write(data, 0, data.Length);"); cw.EndBracket(); }
static string FieldWriterPrimitive(Field f, string stream, string binaryWriter, string instance) { if (f.ProtoType is ProtoEnum) { return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ",(ulong)" + instance + ");"); } if (f.ProtoType is ProtoMessage) { ProtoMessage pm = f.ProtoType as ProtoMessage; CodeWriter cw = new CodeWriter(); cw.Using("var ms" + f.ID + " = new MemoryStream()"); cw.WriteLine(pm.FullSerializerType + ".Serialize(ms" + f.ID + ", " + instance + ");"); BytesWriter(stream, "ms" + f.ID, cw); cw.EndBracket(); return(cw.Code); } switch (f.ProtoType.ProtoName) { case ProtoBuiltin.Double: case ProtoBuiltin.Float: case ProtoBuiltin.Fixed32: case ProtoBuiltin.Fixed64: case ProtoBuiltin.SFixed32: case ProtoBuiltin.SFixed64: return(binaryWriter + ".Write(" + instance + ");"); case ProtoBuiltin.Int32: //Serialized as 64 bit varint return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ",(ulong)" + instance + ");"); case ProtoBuiltin.Int64: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ",(ulong)" + instance + ");"); case ProtoBuiltin.UInt32: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(" + stream + ", " + instance + ");"); case ProtoBuiltin.UInt64: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ", " + instance + ");"); case ProtoBuiltin.SInt32: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteZInt32(" + stream + ", " + instance + ");"); case ProtoBuiltin.SInt64: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteZInt64(" + stream + ", " + instance + ");"); case ProtoBuiltin.Bool: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteBool(" + stream + ", " + instance + ");"); case ProtoBuiltin.String: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteBytes(" + stream + ", Encoding.UTF8.GetBytes(" + instance + "));"); case ProtoBuiltin.Bytes: return("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteBytes(" + stream + ", " + instance + ");"); } throw new NotImplementedException(); }
/// <summary> /// Generates code for writing a class/message /// </summary> static void GenerateWriter(ProtoMessage m, CodeWriter cw) { cw.Summary("Serialize the instance into the stream"); cw.Bracket(m.OptionAccess + " static void Serialize(Stream stream, " + m.CsType + " instance)"); if (m.OptionTriggers) { cw.WriteLine("instance.BeforeSerialize();"); cw.WriteLine(); } if (m.IsUsingBinaryWriter) { cw.WriteLine("BinaryWriter bw = new BinaryWriter(stream);"); } foreach (Field f in m.Fields.Values) { FieldSerializer.FieldWriter(m, f, cw); } if (m.OptionPreserveUnknown) { cw.IfBracket("instance.PreservedFields != null"); cw.ForeachBracket("var kv in instance.PreservedFields"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteKey(stream, kv.Key);"); cw.WriteLine("stream.Write(kv.Value, 0, kv.Value.Length);"); cw.EndBracket(); cw.EndBracket(); } cw.EndBracket(); cw.WriteLine(); cw.Summary("Helper: Serialize into a MemoryStream and return its byte array"); cw.Bracket(m.OptionAccess + " static byte[] SerializeToBytes(" + m.CsType + " instance)"); cw.Using("var ms = new MemoryStream()"); cw.WriteLine("Serialize(ms, instance);"); cw.WriteLine("return ms.ToArray();"); cw.EndBracket(); cw.EndBracket(); }
/// <summary> /// Generates code for writing one field /// </summary> public static void FieldWriter(ProtoMessage m, Field f, CodeWriter cw) { if (f.Rule == FieldRule.Repeated) { if (f.OptionPacked == true) { //Repeated packed cw.IfBracket("instance." + f.CsName + " != null"); KeyWriter("stream", f.ID, Wire.LengthDelimited, cw); if (f.ProtoType.WireSize < 0) { //Un-optimized, unknown size cw.Using("var ms" + f.ID + " = new MemoryStream()"); if (f.IsUsingBinaryWriter) cw.WriteLine("BinaryWriter bw" + f.ID + " = new BinaryWriter(ms" + f.ID + ");"); cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName); cw.WriteLine(FieldWriterType(f, "ms" + f.ID, "bw" + f.ID, "i" + f.ID)); cw.EndBracket(); BytesWriter("stream", "ms" + f.ID, cw); cw.EndBracket(); } else { //Optimized with known size //No memorystream buffering, write size first at once //For constant size messages we can skip serializing to the MemoryStream cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(stream, " + f.ProtoType.WireSize + "u * (uint)instance." + f.CsName + ".Count);"); cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName); cw.WriteLine(FieldWriterType(f, "stream", "bw", "i" + f.ID)); cw.EndBracket(); } cw.EndBracket(); } else { //Repeated not packet cw.IfBracket("instance." + f.CsName + " != null"); cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName); KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "i" + f.ID)); cw.EndBracket(); cw.EndBracket(); } return; } else if (f.Rule == FieldRule.Optional) { if (f.ProtoType is ProtoMessage || f.ProtoType.ProtoName == ProtoBuiltin.String || f.ProtoType.ProtoName == ProtoBuiltin.Bytes) { if (f.ProtoType.Nullable) //Struct always exist, not optional cw.IfBracket("instance." + f.CsName + " != null"); KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); if (f.ProtoType.Nullable) //Struct always exist, not optional cw.EndBracket(); return; } if (f.ProtoType is ProtoEnum) { if (f.OptionDefault != null) cw.IfBracket("instance." + f.CsName + " != " + f.ProtoType.CsType + "." + f.OptionDefault); KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); if (f.OptionDefault != null) cw.EndBracket(); return; } KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); return; } else if (f.Rule == FieldRule.Required) { if (f.ProtoType is ProtoMessage && f.ProtoType.OptionType != "struct" || f.ProtoType.ProtoName == ProtoBuiltin.String || f.ProtoType.ProtoName == ProtoBuiltin.Bytes) { cw.WriteLine("if (instance." + f.CsName + " == null)"); cw.WriteIndent("throw new ArgumentNullException(\"" + f.CsName + "\", \"Required by proto specification.\");"); } KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); return; } throw new NotImplementedException("Unknown rule: " + f.Rule); }
static string FieldWriterPrimitive(Field f, string stream, string binaryWriter, string instance) { if (f.ProtoType is ProtoEnum) return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ",(ulong)" + instance + ");"; if (f.ProtoType is ProtoMessage) { ProtoMessage pm = f.ProtoType as ProtoMessage; CodeWriter cw = new CodeWriter(); cw.Using("var ms" + f.ID + " = new MemoryStream()"); cw.WriteLine(pm.FullSerializerType + ".Serialize(ms" + f.ID + ", " + instance + ");"); BytesWriter(stream, "ms" + f.ID, cw); cw.EndBracket(); return cw.Code; } switch (f.ProtoType.ProtoName) { case ProtoBuiltin.Double: case ProtoBuiltin.Float: case ProtoBuiltin.Fixed32: case ProtoBuiltin.Fixed64: case ProtoBuiltin.SFixed32: case ProtoBuiltin.SFixed64: return binaryWriter + ".Write(" + instance + ");"; case ProtoBuiltin.Int32: //Serialized as 64 bit varint return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ",(ulong)" + instance + ");"; case ProtoBuiltin.Int64: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ",(ulong)" + instance + ");"; case ProtoBuiltin.UInt32: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(" + stream + ", " + instance + ");"; case ProtoBuiltin.UInt64: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt64(" + stream + ", " + instance + ");"; case ProtoBuiltin.SInt32: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteZInt32(" + stream + ", " + instance + ");"; case ProtoBuiltin.SInt64: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteZInt64(" + stream + ", " + instance + ");"; case ProtoBuiltin.Bool: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteBool(" + stream + ", " + instance + ");"; case ProtoBuiltin.String: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteBytes(" + stream + ", Encoding.UTF8.GetBytes(" + instance + "));"; case ProtoBuiltin.Bytes: return "global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteBytes(" + stream + ", " + instance + ");"; } throw new NotImplementedException(); }
/// <summary> /// Return true for normal code and false for generated throw. /// In the later case a break is not needed to be generated afterwards. /// </summary> public static bool FieldReader(Field f, CodeWriter cw) { if (f.Rule == FieldRule.Repeated) { //Make sure we are not reading a list of interfaces if (f.ProtoType.OptionType == "interface") { cw.WriteLine("throw new InvalidOperationException(\"Can't deserialize a list of interfaces\");"); return false; } if (f.OptionPacked == true) { //TODO: read without buffering cw.Comment("repeated packed"); cw.Using("var ms" + f.ID + " = new MemoryStream(global::SilentOrbit.ProtocolBuffers.ProtocolParser.ReadBytes(stream))"); if (f.IsUsingBinaryWriter) cw.WriteLine("BinaryReader br" + f.ID + " = new BinaryReader(ms" + f.ID + ");"); cw.WhileBracket("ms" + f.ID + ".Position < ms" + f.ID + ".Length"); cw.WriteLine("instance." + f.CsName + ".Add(" + FieldReaderType(f, "ms" + f.ID, "br" + f.ID, null) + ");"); cw.EndBracket(); cw.EndBracket(); } else { cw.Comment("repeated"); cw.WriteLine("instance." + f.CsName + ".Add(" + FieldReaderType(f, "stream", "br", null) + ");"); } } else { if (f.OptionReadOnly) { //The only "readonly" fields we can modify //We could possibly support bytes primitive too but it would require the incoming length to match the wire length if (f.ProtoType is ProtoMessage) { cw.WriteLine(FieldReaderType(f, "stream", "br", "instance." + f.CsName) + ";"); return true; } cw.WriteLine("throw new InvalidOperationException(\"Can't deserialize into a readonly primitive field\");"); return false; } if (f.ProtoType is ProtoMessage) { if (f.ProtoType.OptionType == "struct") { cw.WriteLine(FieldReaderType(f, "stream", "br", "ref instance." + f.CsName) + ";"); return true; } cw.WriteLine("if (instance." + f.CsName + " == null)"); if (f.ProtoType.OptionType == "interface") cw.WriteIndent("throw new InvalidOperationException(\"Can't deserialize into a interfaces null pointer\");"); else cw.WriteIndent("instance." + f.CsName + " = " + FieldReaderType(f, "stream", "br", null) + ";"); cw.WriteLine("else"); cw.WriteIndent(FieldReaderType(f, "stream", "br", "instance." + f.CsName) + ";"); return true; } cw.WriteLine("instance." + f.CsName + " = " + FieldReaderType(f, "stream", "br", "instance." + f.CsName) + ";"); } return true; }
/// <summary> /// Generates code for writing one field /// </summary> public static void FieldWriter(ProtoMessage m, Field f, CodeWriter cw) { if (f.Rule == FieldRule.Repeated) { if (f.OptionPacked == true) { //Repeated packed cw.IfBracket("instance." + f.CsName + " != null"); KeyWriter("stream", f.ID, Wire.LengthDelimited, cw); if (f.ProtoType.WireSize < 0) { //Un-optimized, unknown size cw.Using("var ms" + f.ID + " = new MemoryStream()"); if (f.IsUsingBinaryWriter) { cw.WriteLine("BinaryWriter bw" + f.ID + " = new BinaryWriter(ms" + f.ID + ");"); } cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName); cw.WriteLine(FieldWriterType(f, "ms" + f.ID, "bw" + f.ID, "i" + f.ID)); cw.EndBracket(); BytesWriter("stream", "ms" + f.ID, cw); cw.EndBracket(); } else { //Optimized with known size //No memorystream buffering, write size first at once //For constant size messages we can skip serializing to the MemoryStream cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(stream, " + f.ProtoType.WireSize + "u * (uint)instance." + f.CsName + ".Count);"); cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName); cw.WriteLine(FieldWriterType(f, "stream", "bw", "i" + f.ID)); cw.EndBracket(); } cw.EndBracket(); } else { //Repeated not packet cw.IfBracket("instance." + f.CsName + " != null"); cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName); KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "i" + f.ID)); cw.EndBracket(); cw.EndBracket(); } return; } else if (f.Rule == FieldRule.Optional) { if (f.ProtoType is ProtoMessage || f.ProtoType.ProtoName == ProtoBuiltin.String || f.ProtoType.ProtoName == ProtoBuiltin.Bytes) { if (f.ProtoType.Nullable) //Struct always exist, not optional { cw.IfBracket("instance." + f.CsName + " != null"); } KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); if (f.ProtoType.Nullable) //Struct always exist, not optional { cw.EndBracket(); } return; } if (f.ProtoType is ProtoEnum) { if (f.OptionDefault != null) { cw.IfBracket("instance." + f.CsName + " != " + f.ProtoType.CsType + "." + f.OptionDefault); } KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); if (f.OptionDefault != null) { cw.EndBracket(); } return; } KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); return; } else if (f.Rule == FieldRule.Required) { if (f.ProtoType is ProtoMessage && f.ProtoType.OptionType != "struct" || f.ProtoType.ProtoName == ProtoBuiltin.String || f.ProtoType.ProtoName == ProtoBuiltin.Bytes) { cw.WriteLine("if (instance." + f.CsName + " == null)"); cw.WriteIndent("throw new ArgumentNullException(\"" + f.CsName + "\", \"Required by proto specification.\");"); } KeyWriter("stream", f.ID, f.ProtoType.WireType, cw); cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName)); return; } throw new NotImplementedException("Unknown rule: " + f.Rule); }
/// <summary> /// Return true for normal code and false for generated throw. /// In the later case a break is not needed to be generated afterwards. /// </summary> public static bool FieldReader(Field f, CodeWriter cw) { if (f.Rule == FieldRule.Repeated) { //Make sure we are not reading a list of interfaces if (f.ProtoType.OptionType == "interface") { cw.WriteLine("throw new InvalidOperationException(\"Can't deserialize a list of interfaces\");"); return(false); } if (f.OptionPacked == true) { //TODO: read without buffering cw.Comment("repeated packed"); cw.Using("var ms" + f.ID + " = new MemoryStream(global::SilentOrbit.ProtocolBuffers.ProtocolParser.ReadBytes(stream))"); if (f.IsUsingBinaryWriter) { cw.WriteLine("BinaryReader br" + f.ID + " = new BinaryReader(ms" + f.ID + ");"); } cw.WhileBracket("ms" + f.ID + ".Position < ms" + f.ID + ".Length"); cw.WriteLine("instance." + f.CsName + ".Add(" + FieldReaderType(f, "ms" + f.ID, "br" + f.ID, null) + ");"); cw.EndBracket(); cw.EndBracket(); } else { cw.Comment("repeated"); cw.WriteLine("instance." + f.CsName + ".Add(" + FieldReaderType(f, "stream", "br", null) + ");"); } } else { if (f.OptionReadOnly) { //The only "readonly" fields we can modify //We could possibly support bytes primitive too but it would require the incoming length to match the wire length if (f.ProtoType is ProtoMessage) { cw.WriteLine(FieldReaderType(f, "stream", "br", "instance." + f.CsName) + ";"); return(true); } cw.WriteLine("throw new InvalidOperationException(\"Can't deserialize into a readonly primitive field\");"); return(false); } if (f.ProtoType is ProtoMessage) { if (f.ProtoType.OptionType == "struct") { cw.WriteLine(FieldReaderType(f, "stream", "br", "ref instance." + f.CsName) + ";"); return(true); } cw.WriteLine("if (instance." + f.CsName + " == null)"); if (f.ProtoType.OptionType == "interface") { cw.WriteIndent("throw new InvalidOperationException(\"Can't deserialize into a interfaces null pointer\");"); } else { cw.WriteIndent("instance." + f.CsName + " = " + FieldReaderType(f, "stream", "br", null) + ";"); } cw.WriteLine("else"); cw.WriteIndent(FieldReaderType(f, "stream", "br", "instance." + f.CsName) + ";"); return(true); } cw.WriteLine("instance." + f.CsName + " = " + FieldReaderType(f, "stream", "br", "instance." + f.CsName) + ";"); } return(true); }
/// <summary> /// Generates code for writing a class/message /// </summary> static void GenerateWriter(ProtoMessage m, CodeWriter cw) { cw.Summary("Serialize the instance into the stream"); cw.Bracket(m.OptionAccess + " static void Serialize(Stream stream, " + m.CsType + " instance)"); if (m.OptionTriggers) { cw.WriteLine("instance.BeforeSerialize();"); cw.WriteLine(); } if (m.IsUsingBinaryWriter) cw.WriteLine("BinaryWriter bw = new BinaryWriter(stream);"); foreach (Field f in m.Fields.Values) FieldSerializer.FieldWriter(m, f, cw); if (m.OptionPreserveUnknown) { cw.IfBracket("instance.PreservedFields != null"); cw.ForeachBracket("var kv in instance.PreservedFields"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteKey(stream, kv.Key);"); cw.WriteLine("stream.Write(kv.Value, 0, kv.Value.Length);"); cw.EndBracket(); cw.EndBracket(); } cw.EndBracket(); cw.WriteLine(); cw.Summary("Helper: Serialize into a MemoryStream and return its byte array"); cw.Bracket(m.OptionAccess + " static byte[] SerializeToBytes(" + m.CsType + " instance)"); cw.Using("var ms = new MemoryStream()"); cw.WriteLine("Serialize(ms, instance);"); cw.WriteLine("return ms.ToArray();"); cw.EndBracket(); cw.EndBracket(); cw.Summary("Helper: Serialize with a varint length prefix"); cw.Bracket(m.OptionAccess + " static void SerializeLengthDelimited(Stream stream, " + m.CsType + " instance)"); cw.WriteLine("var data = SerializeToBytes(instance);"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(stream, (uint)data.Length);"); cw.WriteLine("stream.Write(data, 0, data.Length);"); cw.EndBracket(); }
/// <summary> /// Generates code for writing a class/message /// </summary> void GenerateWriter(ProtoMessage m) { string mTableParamDefs, mTableParams; FindMessageTableParams(m, out mTableParamDefs, out mTableParams); string stack = "global::SilentOrbit.ProtocolBuffers.ProtocolParser.Stack"; if (options.ExperimentalStack != null) { cw.WriteLine("[ThreadStatic]"); cw.WriteLine("static global::SilentOrbit.ProtocolBuffers.MemoryStreamStack stack = new " + options.ExperimentalStack + "();"); stack = "stack"; } cw.Summary("Serialize the instance into the stream"); cw.Bracket(m.OptionAccess + " static void Serialize(Stream stream, " + m.CsType + " instance" + mTableParamDefs + ")"); if (m.OptionTriggers) { cw.WriteLine("instance.BeforeSerialize();"); cw.WriteLine(); } if (m.IsUsingBinaryWriter) { cw.WriteLine("BinaryWriter bw = new BinaryWriter(stream);"); } //Shared memorystream for all fields cw.WriteLine("var msField = " + stack + ".Pop();"); foreach (Field f in m.Fields.Values) { FieldSerializer.FieldWriter(m, f, cw, options); } cw.WriteLine(stack + ".Push(msField);"); if (m.OptionPreserveUnknown) { cw.IfBracket("instance.PreservedFields != null"); cw.ForeachBracket("var kv in instance.PreservedFields"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteKey(stream, kv.Key);"); cw.WriteLine("stream.Write(kv.Value, 0, kv.Value.Length);"); cw.EndBracket(); cw.EndBracket(); } cw.EndBracket(); cw.WriteLine(); if (m.OptionType != "interface" && !m.OptionNoPartials) { cw.Summary("Serialize and return data as a byte array (use this sparingly)"); cw.Bracket(m.OptionAccess + " byte[] ToProtoBytes(" + mTableParamDefs.TrimStart(',', ' ') + ")"); cw.WriteLine("return SerializeToBytes( this" + mTableParams + " );"); cw.EndBracketSpace(); cw.Summary("Serialize to a Stream"); cw.Bracket(m.OptionAccess + " void ToProto( Stream stream" + mTableParamDefs + " )"); cw.WriteLine("Serialize( stream, this" + mTableParams + " );"); cw.EndBracketSpace(); cw.Summary("Serialize to a JSON string"); cw.Bracket(m.OptionAccess + " string ToJson(" + mTableParamDefs.TrimStart(',', ' ') + ")"); cw.WriteLine("var writer = new global::System.IO.StringWriter();"); cw.WriteLine("SerializeJson(writer, this" + mTableParams + ");"); cw.WriteLine("return writer.ToString();"); cw.EndBracketSpace(); } cw.Summary("Helper: Serialize into a MemoryStream and return its byte array"); cw.Bracket(m.OptionAccess + " static byte[] SerializeToBytes(" + m.CsType + " instance" + mTableParamDefs + ")"); cw.Using("var ms = new MemoryStream()"); cw.WriteLine("Serialize(ms, instance" + mTableParams + ");"); cw.WriteLine("return ms.ToArray();"); cw.EndBracket(); cw.EndBracket(); cw.Summary("Helper: Serialize with a varint length prefix"); cw.Bracket(m.OptionAccess + " static void SerializeLengthDelimited(Stream stream, " + m.CsType + " instance" + mTableParamDefs + ")"); cw.WriteLine("var data = SerializeToBytes(instance" + mTableParams + ");"); cw.WriteLine("global::SilentOrbit.ProtocolBuffers.ProtocolParser.WriteUInt32(stream, (uint)data.Length);"); cw.WriteLine("stream.Write(data, 0, data.Length);"); cw.EndBracket(); cw.Summary("Serialize into a JSON string"); cw.Bracket(m.OptionAccess + " static void SerializeJson(TextWriter writer, " + m.CsType + " instance" + mTableParamDefs + ")"); cw.WriteLine("writer.Write(\"{\");"); var first = true; foreach (Field f in m.Fields.Values) { if (!first) { cw.WriteLine("writer.Write(\",\");"); } else { first = false; } FieldSerializer.FieldJsonWriter(m, f, cw, options); } cw.WriteLine("writer.Write(\"}\");"); cw.EndBracket(); }