예제 #1
0
        /// <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();
        }
예제 #2
0
 /// <summary>
 /// Generates code for writing one field
 /// </summary>
 public void FieldWriter(ProtoMessage m, Field f, CodeWriter cw, Options options)
 {
     if (f.Rule == FieldRule.Repeated)
     {
         //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);
         FieldWriterType(f, "stream", "bw", "i" + f.ID, cw);
         cw.EndBracket();
         cw.EndBracket();
     }
     else if (f.Rule == FieldRule.Optional)
     {
         if (options.Nullable ||
             f.ProtoType is ProtoMessage ||
             f.ProtoType.ProtoName == ProtoBuiltin.String ||
             f.ProtoType.ProtoName == ProtoBuiltin.Bytes)
         {
             if (f.ProtoType.Nullable || options.Nullable) //Struct always exist, not optional
             {
                 cw.IfBracket("instance." + f.CsName + " != null");
             }
             KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
             var needValue = !f.ProtoType.Nullable && options.Nullable;
             FieldWriterType(f, "stream", "bw", "instance." + f.CsName + (needValue ? ".Value" : ""), cw);
             if (f.ProtoType.Nullable || options.Nullable) //Struct always exist, not optional
             {
                 cw.EndBracket();
             }
             return;
         }
         if (f.ProtoType is ProtoEnum)
         {
             KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
             FieldWriterType(f, "stream", "bw", "instance." + f.CsName, cw);
             return;
         }
         KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
         FieldWriterType(f, "stream", "bw", "instance." + f.CsName, cw);
         return;
     }
     else if (f.Rule == FieldRule.Required)
     {
         if (f.ProtoType is ProtoMessage ||
             f.ProtoType.ProtoName == ProtoBuiltin.String ||
             f.ProtoType.ProtoName == ProtoBuiltin.Bytes)
         {
             cw.WriteLine("if (instance." + f.CsName + " == null)");
             cw.WriteIndent("throw new global::SilentOrbit.ProtocolBuffers.ProtocolBufferException(\"" + f.CsName + " is required by the proto specification.\");");
         }
         KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
         FieldWriterType(f, "stream", "bw", "instance." + f.CsName, cw);
         return;
     }
     throw new NotImplementedException("Unknown rule: " + f.Rule);
 }
예제 #3
0
        /// <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(CitoStream stream, " + m.FullCsType + " 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("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.FullCsType + " instance)");
            cw.WriteLine("CitoMemoryStream ms = new CitoMemoryStream();");
            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(CitoStream stream, " + m.FullCsType + " instance)");
            cw.WriteLine("byte[] data = SerializeToBytes(instance);");
            cw.WriteLine("ProtocolParser.WriteUInt32_(stream, ProtoPlatform.ArrayLength(data));");
            cw.WriteLine("stream.Write(data, 0, ProtoPlatform.ArrayLength(data));");
            cw.EndBracket();
        }
예제 #4
0
        /// <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();
        }
예제 #5
0
        /// <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(CitoStream stream, " + m.FullCsType + " 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("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.FullCsType + " instance)");
            cw.WriteLine("CitoMemoryStream ms = new CitoMemoryStream();");
            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(CitoStream stream, " + m.FullCsType + " instance)");
            cw.WriteLine("byte[] data = SerializeToBytes(instance);");
            cw.WriteLine("ProtocolParser.WriteUInt32_(stream, ProtoPlatform.ArrayLength(data));");
            cw.WriteLine("stream.Write(data, 0, ProtoPlatform.ArrayLength(data));");
            cw.EndBracket();
        }
예제 #6
0
        /// <summary>
        /// Generates code for writing one field
        /// </summary>
        public static void FieldWriter(ProtoMessage m, Field f, CodeWriter cw, Options options)
        {
            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.WriteLine("msField.SetLength(0);");
                        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, "msField", "bw" + f.ID, "i" + f.ID));
                        cw.EndBracket();

                        BytesWriter(f, "stream", cw);
                    }
                    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 (options.Nullable ||
                    f.ProtoType is ProtoMessage ||
                    f.ProtoType.ProtoName == ProtoBuiltin.String ||
                    f.ProtoType.ProtoName == ProtoBuiltin.Bytes)
                {
                    if (f.ProtoType.Nullable || options.Nullable) //Struct always exist, not optional
                    {
                        cw.IfBracket("instance." + f.CsName + " != null");
                    }
                    KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
                    var needValue = !f.ProtoType.Nullable && options.Nullable;
                    cw.WriteLine(FieldWriterType(f, "stream", "bw", "instance." + f.CsName + (needValue ? ".Value" : "")));
                    if (f.ProtoType.Nullable || options.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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        /// <summary>
        /// Generates code for writing a class/message
        /// </summary>
        static void GenerateWriter(ProtoMessage m, CodeWriter cw, Options options)
        {
            cw.WriteLine("#region [Methods] Writer");

            #region [Method] Serialize
            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();
                }

                //Shared memorystream for all fields
                cw.WriteLine("var msField = Pool.Get<MemoryStream>();");

                foreach (Field f in m.Fields.Values)
                {
                    FieldSerializer.FieldWriter(m, f, cw, false);
                }

                cw.WriteLine("Pool.FreeMemoryStream(ref 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.EndBracketSpace();
            #endregion

            #region [Method] SerializeToBytes
            cw.Summary("Helper: Serialize into a MemoryStream and return its byte array");
            cw.Bracket(m.OptionAccess + " static byte[] SerializeToBytes(" + m.CsType + " instance)");
            {
                cw.WriteLine("var ms = Pool.Get<MemoryStream>();");
                cw.WriteLine("Serialize(ms, instance);");
                cw.WriteLine("var arr = ms.ToArray();");
                cw.WriteLine("Pool.FreeMemoryStream(ref ms);");
                cw.WriteLine("return arr;");
            }
            cw.EndBracket();
            #endregion

            #region [Method] SerializeLengthDelimited
            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.EndBracketSpace();
            #endregion

            #region [Method] SerializeDelta
            cw.Bracket($"public static void SerializeDelta(Stream stream, {m.CsType} instance, {m.CsType} previous)");
            {
                cw.WriteLine("var msField = Pool.Get<MemoryStream>();");

                foreach (Field f in m.Fields.Values)
                {
                    cw.IfBracket($"instance.{f.CsName} != previous.{f.CsName}");
                    FieldSerializer.FieldWriter(m, f, cw, true);
                    cw.EndBracket();
                }

                cw.WriteLine("Pool.FreeMemoryStream(ref msField);");
            }
            cw.EndBracket();
            #endregion

            #region [Method] WriteToStream
            if (m.OptionExternal == false)
            {
                cw.Bracket("public void WriteToStream(Stream stream)");
                {
                    cw.WriteLine("Serialize(stream, this);");
                }
                cw.EndBracket();
            }
            #endregion

            #region [Method] WriteToStreamDelta
            if (m.OptionExternal == false)
            {
                cw.Bracket($"public void WriteToStreamDelta(Stream stream, {m.CsType} previous)");
                {
                    cw.IfBracket("previous != null");
                    {
                        cw.WriteLine("SerializeDelta(stream, this, previous);");
                    }
                    cw.EndBracket();
                    cw.Bracket("else");
                    {
                        cw.WriteLine("Serialize(stream, this);");
                    }
                    cw.EndBracket();
                }
                cw.EndBracket();
            }
            #endregion

            cw.WriteLine("#endregion");
        }
예제 #9
0
        /// <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();
        }
예제 #10
0
 /// <summary>
 /// Generates code for writing one field as a JSON string
 /// </summary>
 public static void FieldJsonWriter(ProtoMessage m, Field f, CodeWriter cw, Options options)
 {
     cw.WriteLine("writer.Write(\"\\\"" + f.ProtoName + "\\\":\");");
     if (f.Rule == FieldRule.Repeated)
     {
         cw.WriteLine();
         cw.IfBracket("instance." + f.CsName + " != null");
         cw.WriteLine("writer.Write(\"[\");");
         cw.WriteLine("var first = true;");
         cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName);
         cw.WriteLine("if (!first) writer.Write(\",\");");
         cw.WriteLine("else first = false;");
         cw.WriteLine(FieldWriterJsonType(f, m.RequiredMessageTables, "writer", "i" + f.ID));
         cw.EndBracket();
         cw.WriteLine("writer.Write(\"]\");");
         cw.ElseBracket();
         cw.WriteLine("writer.Write(\"null\");");
         cw.EndBracket();
         return;
     }
     else if (f.Rule == FieldRule.Optional)
     {
         if (options.Nullable ||
             f.ProtoType is ProtoMessage ||
             f.ProtoType.ProtoName == ProtoBuiltin.String ||
             f.ProtoType.ProtoName == ProtoBuiltin.Bytes)
         {
             var nullable = (f.ProtoType.Nullable || options.Nullable) && !(f.ProtoType.OptionType == "interface" && m.RequiredMessageTables.Contains(f.ProtoType));
             if (nullable) //Struct always exist, not optional
             {
                 cw.IfBracket("instance." + f.CsName + " != null");
             }
             var needValue = !f.ProtoType.Nullable && options.Nullable;
             cw.WriteLine(FieldWriterJsonType(f, m.RequiredMessageTables, "writer", "instance." + f.CsName + (needValue ? ".Value" : "")));
             if (nullable)   //Struct always exist, not optional
             {
                 cw.ElseBracket();
                 cw.WriteLine("writer.Write(\"null\");");
                 cw.EndBracket();
             }
             return;
         }
         if (f.ProtoType is ProtoEnum)
         {
             cw.WriteLine(FieldWriterJsonType(f, m.RequiredMessageTables, "writer", "instance." + f.CsName));
             return;
         }
         cw.WriteLine(FieldWriterJsonType(f, m.RequiredMessageTables, "writer", "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.\");");
         }
         cw.WriteLine(FieldWriterJsonType(f, m.RequiredMessageTables, "writer", "instance." + f.CsName));
         return;
     }
     throw new NotImplementedException("Unknown rule: " + f.Rule);
 }
예제 #11
0
        public bool JsonFieldReader(Field f, ProtoMessage[] messageTables, string jToken)
        {
            if (f.Rule == FieldRule.Repeated)
            {
                //Make sure we are not reading a list of interfaces
                if (f.ProtoType.OptionType == "interface" && !messageTables.Contains(f.ProtoType))
                {
                    cw.WriteLine("throw new NotSupportedException(\"Can't deserialize a list of interfaces\");");
                    return(false);
                }

                cw.Comment("repeated");
                cw.ForeachBracket("var val in ((global::Newtonsoft.Json.Linq.JArray) " + jToken + ")");
                cw.WriteLine("instance." + f.CsName + ".Add(" + JsonFieldReaderType(f, messageTables, "val", null) + ");");
                cw.EndBracket();
            }
            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(JsonFieldReaderType(f, messageTables, jToken, "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")
                    {
                        if (f.OptionUseReferences)
                        {
                            cw.WriteLine(JsonFieldReaderType(f, messageTables, jToken, "ref instance." + f.CsName) + ";");
                        }
                        else
                        {
                            cw.WriteLine("{");
                            cw.WriteIndent("var a = instance." + f.CsName + ";");
                            cw.WriteIndent("instance." + f.CsName + " = " + JsonFieldReaderType(f, messageTables, jToken, "ref a") + ";");
                            cw.WriteLine("}");
                        }

                        return(true);
                    }

                    cw.WriteLine("if (instance." + f.CsName + " == null)");
                    if (f.ProtoType.OptionType == "interface" && !messageTables.Contains(f.ProtoType))
                    {
                        cw.WriteIndent("throw new InvalidOperationException(\"Can't deserialize into a interfaces null pointer\");");
                    }
                    else
                    {
                        cw.WriteIndent("instance." + f.CsName + " = " + JsonFieldReaderType(f, messageTables, jToken, null) + ";");
                    }
                    cw.WriteLine("else");
                    cw.WriteIndent(JsonFieldReaderType(f, messageTables, jToken, "instance." + f.CsName) + ";");
                    return(true);
                }

                cw.WriteLine("instance." + f.CsName + " = " + JsonFieldReaderType(f, messageTables, jToken, "instance." + f.CsName) + ";");
            }
            return(true);
        }
예제 #12
0
        /// <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();
        }