public ProtoPrepare(Options options)
        {
            if (options.PreserveNames)
                ConvertToCamelCase = false;

            this.options = options;
        }
Exemple #2
0
        public static void GenerateClass(ProtoMessage m, CodeWriter cw, Options options)
        {
            //Do not generate class code for external classes
            if (m.OptionExternal)
            {
                cw.Comment("Written elsewhere");
                cw.Comment(m.OptionAccess + " " + m.OptionType + " " + m.CsType + " {}");
                return;
            }

            //Default class
            cw.Summary(m.Comments);
            cw.Bracket(m.OptionAccess + " partial " + m.OptionType + " " + m.CsType);

            GenerateEnums(m, cw);

            GenerateProperties(m, cw);

            //if(options.GenerateToString...
            // ...

            if (m.OptionPreserveUnknown)
            {
                cw.Summary("Values for unknown fields.");
                cw.WriteLine("public List<global::SilentOrbit.ProtocolBuffers.KeyValue> PreservedFields;");
                cw.WriteLine();
            }

            if (m.OptionTriggers)
            {
                cw.Comment("protected virtual void BeforeSerialize() {}");
                cw.Comment("protected virtual void AfterDeserialize() {}");
                cw.WriteLine();
            }

            foreach (ProtoMessage sub in m.Messages.Values)
            {
                GenerateClass(sub, cw, options);
                cw.WriteLine();
            }
            cw.EndBracket();
            return;
        }
        public static void Build(Options options)
        {
            var parser = new FileParser();
            var collection = parser.Import(options.InputProto);

            Console.WriteLine(collection);

            //Interpret and reformat
            try
            {
                var pp = new ProtoPrepare(options);
                pp.Prepare(collection);
            }
            catch (ProtoFormatException pfe)
            {
                Console.WriteLine();
                Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message);
                throw;
            }

            //Generate code
            ProtoCode.Save(collection, options);
            Console.WriteLine("Saved: " + options.OutputPath);
        }
 public MessageSerializer(CodeWriter cw, Options options)
 {
     this.cw = cw;
     this.options = options;
     this.fieldSerializer = new FieldSerializer(cw, options);
 }
Exemple #5
0
 public MessageCode(CodeWriter cw, Options options)
 {
     this.cw = cw;
     this.options = options;
 }
        /// <summary>
        /// Generates code for writing one field
        /// </summary>
        public 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);
                        FieldWriterType(f, "msField", "bw" + f.ID, "i" + f.ID, cw);
                        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(ProtocolParser.Base + ".WriteUInt32(stream, " + f.ProtoType.WireSize + "u * (uint)instance." + f.CsName + ".Count);");

                        cw.ForeachBracket("var i" + f.ID + " in instance." + f.CsName);
                        FieldWriterType(f, "stream", "bw", "i" + f.ID, cw);
                        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);
                    FieldWriterType(f, "stream", "bw", "i" + f.ID, cw);
                    cw.EndBracket();
                    cw.EndBracket();
                }
                return;
            }
            else if (f.Rule == FieldRule.Optional)
            {
                bool skip = options.SkipSerializeDefault && f.OptionDefault != null;

                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)
                {
                    if (skip)
                        cw.IfBracket("instance." + f.CsName + " != " + f.FormatDefaultForTypeAssignment());
                    KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
                    FieldWriterType(f, "stream", "bw", "instance." + f.CsName, cw);
                    if (skip)
                        cw.EndBracket();
                    return;
                }
                if (skip) //Skip writing value if default
                    cw.IfBracket("instance." + f.CsName + " != " + f.FormatDefaultForTypeAssignment());
                KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
                FieldWriterType(f, "stream", "bw", "instance." + f.CsName, cw);
                if (skip)
                    cw.EndBracket();
                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 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);
        }
 public FieldSerializer(CodeWriter cw, Options options)
 {
     this.cw = cw;
     this.options = options;
 }
Exemple #8
0
        /// <summary>
        /// Generate code for reading and writing protocol buffer messages
        /// </summary>
        public static void Save(ProtoCollection file, Options options)
        {
            string csPath = options.OutputPath;
            CodeWriter.DefaultIndentPrefix = options.UseTabs ? "\t" : "    ";

            string ext = Path.GetExtension(csPath);
            string prefix = csPath.Substring(0, csPath.Length - ext.Length);

            string csDir = Path.GetDirectoryName(csPath);
            if (Directory.Exists(csDir) == false)
                Directory.CreateDirectory(csDir);

            //Basic structures
            using (var cw = new CodeWriter(csPath))
            {
                cw.Comment(@"Classes and structures being serialized");
                cw.WriteLine();
                cw.Comment(@"Generated by ProtocolBuffer
            - a pure c# code generation implementation of protocol buffers
            Report bugs to: https://silentorbit.com/protobuf/");
                cw.WriteLine();
                cw.Comment(@"DO NOT EDIT
            This file will be overwritten when CodeGenerator is run.
            To make custom modifications, edit the .proto file and add //:external before the message line
            then write the code and the changes in a separate file.");

                cw.WriteLine("using System;");
                cw.WriteLine("using System.Collections.Generic;");
                cw.WriteLine();

                string ns = null; //avoid writing namespace between classes if they belong to the same
                foreach (ProtoMessage m in file.Messages.Values)
                {
                    if (ns != m.CsNamespace)
                    {
                        if (ns != null) //First time
                            cw.EndBracket();
                        cw.Bracket("namespace " + m.CsNamespace);
                        ns = m.CsNamespace;
                    }
                    MessageCode.GenerateClass(m, cw, options);
                    cw.WriteLine();
                }

                foreach (ProtoEnum e in file.Enums.Values)
                {
                    if (ns != e.CsNamespace)
                    {
                        if (ns != null) //First time
                            cw.EndBracket();
                        cw.Bracket("namespace " + e.CsNamespace);
                        ns = e.CsNamespace;
                    }
                    MessageCode.GenerateEnum(e, cw);
                    cw.WriteLine();
                }

                cw.EndBracket();
            }

            //.Serializer.cs
            //Code for Reading/Writing
            using (var cw = new CodeWriter(prefix + ".Serializer" + ext))
            {
                cw.Comment(@"This is the backend code for reading and writing");
                cw.WriteLine();
                cw.Comment(@"Generated by ProtocolBuffer
            - a pure c# code generation implementation of protocol buffers
            Report bugs to: https://silentorbit.com/protobuf/");
                cw.WriteLine();
                cw.Comment(@"DO NOT EDIT
            This file will be overwritten when CodeGenerator is run.");

                cw.WriteLine("using System;");
                cw.WriteLine("using System.IO;");
                cw.WriteLine("using System.Text;");
                cw.WriteLine("using System.Collections.Generic;");
                cw.WriteLine();

                string ns = null; //avoid writing namespace between classes if they belong to the same
                foreach (ProtoMessage m in file.Messages.Values)
                {
                    if (ns != m.CsNamespace)
                    {
                        if (ns != null) //First time
                            cw.EndBracket();
                        cw.Bracket("namespace " + m.CsNamespace);
                        ns = m.CsNamespace;
                    }
                    MessageSerializer.GenerateClassSerializer(m, cw);
                }
                cw.EndBracket();
            }

            string libPath = Path.Combine(Path.GetDirectoryName(csPath), "ProtocolParser.cs");
            using (TextWriter codeWriter = new StreamWriter(libPath, false, Encoding.UTF8))
            {
                codeWriter.NewLine = "\r\n";
                ReadCode(codeWriter, "ProtocolParser", true);
                ReadCode(codeWriter, "ProtocolParserFixed", false);
                ReadCode(codeWriter, "ProtocolParserKey", false);
                ReadCode(codeWriter, "ProtocolParserVarInt", false);
            }
        }
        public void FieldSizeWriter(ProtoMessage m, Field f, CodeWriter cw, Options options)
        {
            if (f.Rule == FieldRule.Repeated)
            {
                if (f.OptionPacked == true)
                {
                    Console.WriteLine("not support");
                }
                else
                {
                    //Repeated not packet
                    cw.IfBracket("this." + f.CsName + " != null");
                    cw.ForeachBracket("var i" + f.ID + " in this." + f.CsName);
                    //KeyWriter("stream", f.ID, f.ProtoType.WireType, cw);
                    FieldSizeWriterType(f, "i" + f.ID, cw);
                    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("this." + f.CsName + " != null");

                    FieldSizeWriterType(f, "this." + f.CsName, cw);

                    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("this." + f.CsName + " != " + f.ProtoType.CsType + "." + f.OptionDefault);

                    FieldSizeWriterType(f, "this." + f.CsName, cw);

                    if (f.OptionDefault != null)
                        cw.EndBracket();
                    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.OptionType != "struct" ||
                    f.ProtoType.ProtoName == ProtoBuiltin.String ||
                    f.ProtoType.ProtoName == ProtoBuiltin.Bytes)
                {
                    cw.WriteLine("if (this." + f.CsName + " == null)");
                    cw.WriteIndent("throw new global::SilentOrbit.ProtocolBuffers.ProtocolBufferException(\"" + f.CsName + " is required by the proto specification.\");");
                }
                cw.WriteLine();
                FieldSizeWriterType(f, "this." + f.CsName, cw);
                return;
            }
            throw new NotImplementedException("Unknown rule: " + f.Rule);
        }