Ejemplo n.º 1
0
        private void DoParseFile(ProtoInputData inputData)
        {
            var sb = new StringBuilder();

            DumpFileDescriptor(inputData, sb);

            outputProtoDefs.Add(new ProtoOutputData {
                file = inputData.proto, buffer = sb
            });
            ProtoList.Add(inputData.proto.name);
        }
Ejemplo n.º 2
0
        private bool ShouldDeferProto(ProtoInputData inputData)
        {
            foreach (var dependency in inputData.proto.dependency)
            {
                if (!dependency.StartsWith("google", StringComparison.Ordinal) && !ProtoList.Contains(dependency))
                {
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 3
0
        private bool HandleProto(string name, byte[] data)
        {
            Console.Write("{0}... ", name);

            var inputData = new ProtoInputData();

            if (Environment.GetCommandLineArgs().Contains("-dump", StringComparer.OrdinalIgnoreCase))
            {
                var fileName = Path.Combine(OutputDir, $"{name}.dump");
                Directory.CreateDirectory(Path.GetDirectoryName(fileName));

                Console.WriteLine("  ! Dumping to '{0}'!", fileName);

                try
                {
                    File.WriteAllBytes(fileName, data);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Unable to dump: {0}", ex.Message);
                }
            }

            try
            {
                using (var ms = new MemoryStream(data))
                    inputData.proto = Serializer.Deserialize <FileDescriptorProto>(ms);
            }
            catch (EndOfStreamException ex)
            {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine("needs rescan: {0}", ex.Message);
                Console.ResetColor();
                return(false);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("is invalid: {0}", ex.Message);
                Console.ResetColor();
                return(true);
            }

            inputProtoDefs.Add(inputData);

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("OK!");
            Console.ResetColor();

            return(true);
        }
Ejemplo n.º 4
0
        // because of protobuf-net we're limited to parsing simple types at run-time as we can't parse the protobuf, but options shouldn't be too complex
        private void BuildExtension(string key, IEnumerable <FieldDescriptorProto> fields, ProtoInputData protoData)
        {
            var name      = $"{key}Ext{Guid.NewGuid()}";
            var extension = moduleBuilder.DefineType(name, TypeAttributes.Class);

            var pcType    = typeof(ProtoContractAttribute);
            var pcCtor    = pcType.GetConstructor(Type.EmptyTypes);
            var pcBuilder = new CustomAttributeBuilder(pcCtor, Type.EmptyTypes);

            extension.SetCustomAttribute(pcBuilder);

            foreach (var field in fields)
            {
                var fieldType = LookupBasicType(field.type, out var format, out var buildEnumProxy);
                var fbuilder  = extension.DefineField(field.name, fieldType, FieldAttributes.Public);

                object defaultValue = field.default_value;
                if (field.type == FieldDescriptorProto.Type.TYPE_ENUM)
                {
                    defaultValue = 0;
                }
                else if (string.IsNullOrEmpty(field.default_value))
                {
                    if (field.type == FieldDescriptorProto.Type.TYPE_STRING)
                    {
                        defaultValue = "";
                    }
                    else
                    {
                        defaultValue = Activator.CreateInstance(fieldType);
                    }
                }
                else
                {
                    try
                    {
                        defaultValue = Convert.ChangeType(field.default_value, fieldType);
                    }
                    catch (FormatException)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("Constructor for extension had bad format: {0}", key);
                        Console.ResetColor();
                        return;
                    }
                }


                if (buildEnumProxy)
                {
                    var epType    = typeof(EnumProxyAttribute);
                    var epCtor    = epType.GetConstructor(new[] { typeof(object), typeof(string) });
                    var epBuilder = new CustomAttributeBuilder(epCtor, new object[] { field.default_value, field.type_name });

                    fbuilder.SetCustomAttribute(epBuilder);
                }

                var dvType    = typeof(DefaultValueAttribute);
                var dvCtor    = dvType.GetConstructor(new[] { typeof(object) });
                var dvBuilder = new CustomAttributeBuilder(dvCtor, new[] { defaultValue });

                fbuilder.SetCustomAttribute(dvBuilder);

                var pmType    = typeof(ProtoMemberAttribute);
                var pmCtor    = pmType.GetConstructor(new[] { typeof(int) });
                var pmBuilder = new CustomAttributeBuilder(pmCtor, new object[] { field.number },
                                                           new[] { pmType.GetProperty("Name"), pmType.GetProperty("DataFormat") },
                                                           new object[] { $"({field.name})", format });


                fbuilder.SetCustomAttribute(pmBuilder);
            }

            var extensionType = extension.CreateType();

            if (!protoData.extensions.ContainsKey(key))
            {
                protoData.extensions[key] = new List <Type>();
            }

            protoData.extensions[key].Add(extensionType);

            // Update extensions known by protodefs that rely on us
            foreach (var dependent in inputProtoDefs.Where(x => x.proto.dependency.Contains(protoData.proto.name)))
            {
                if (!dependent.extensions.ContainsKey(key))
                {
                    dependent.extensions[key] = new List <Type>();
                }

                dependent.extensions[key].Add(extensionType);
            }
        }
Ejemplo n.º 5
0
        private void DumpDescriptor(DescriptorProto proto, ProtoInputData inputData, StringBuilder sb, int level)
        {
            PushDescriptorName(proto);

            var levelspace = new string('\t', level);

            sb.AppendLine($"{levelspace}message {proto.name} {{");

            foreach (var option in DumpOptions(proto.options, inputData.extensions))
            {
                sb.AppendLine($"{levelspace}\toption {option.Key} = {option.Value};");
            }

            foreach (var field in proto.nested_type)
            {
                DumpDescriptor(field, inputData, sb, level + 1);
            }

            DumpExtensionDescriptor(proto.extension, inputData, sb, $"{levelspace}\t");

            foreach (var field in proto.enum_type)
            {
                DumpEnumDescriptor(field, inputData.extensions, sb, level + 1);
            }

            foreach (var field in proto.field.Where(x => !x.oneof_indexSpecified))
            {
                var enumLookup = new List <EnumDescriptorProto>();

                enumLookup.AddRange(inputData.proto.enum_type); // add global enums
                enumLookup.AddRange(proto.enum_type);           // add this message's nested enums

                sb.AppendLine($"{levelspace}\t{BuildDescriptorDeclaration(field, inputData.extensions)}");
            }

            for (var i = 0; i < proto.oneof_decl.Count; i++)
            {
                var oneof  = proto.oneof_decl[i];
                var fields = proto.field.Where(x => x.oneof_indexSpecified && x.oneof_index == i).ToArray();

                sb.AppendLine($"{levelspace}\toneof {oneof.name} {{");

                foreach (var field in fields)
                {
                    sb.AppendLine($"{levelspace}\t\t{BuildDescriptorDeclaration(field, inputData.extensions, emitFieldLabel: false)}");
                }

                sb.AppendLine($"{levelspace}\t}}");
            }

            if (proto.extension_range.Count > 0)
            {
                sb.AppendLine();
            }

            foreach (var range in proto.extension_range)
            {
                var max = Convert.ToString(range.end);

                // http://code.google.com/apis/protocolbuffers/docs/proto.html#extensions
                // If your numbering convention might involve extensions having very large numbers as tags, you can specify
                // that your extension range goes up to the maximum possible field number using the max keyword:
                // max is 2^29 - 1, or 536,870,911.
                if (range.end >= 536870911)
                {
                    max = "max";
                }

                sb.AppendLine($"{levelspace}\textensions {range.start} to {max};");
            }

            sb.AppendLine($"{levelspace}}}");
            sb.AppendLine();

            PopDescriptorName();
        }
Ejemplo n.º 6
0
        private void DumpFileDescriptor(ProtoInputData inputData, StringBuilder sb)
        {
            if (!string.IsNullOrEmpty(inputData.proto.package))
            {
                PushDescriptorName(inputData.proto);
            }

            var marker = false;

            foreach (var dependency in inputData.proto.dependency)
            {
                sb.AppendLine($"import \"{dependency}\";");
                marker = true;
            }

            if (marker)
            {
                sb.AppendLine();
                marker = false;
            }

            if (!string.IsNullOrEmpty(inputData.proto.package))
            {
                sb.AppendLine($"package {inputData.proto.package};");
                marker = true;
            }

            if (marker)
            {
                sb.AppendLine();
                marker = false;
            }

            foreach (var option in DumpOptions(inputData.proto.options, inputData.extensions))
            {
                sb.AppendLine($"option {option.Key} = {option.Value};");
                marker = true;
            }

            if (marker)
            {
                sb.AppendLine();
            }

            DumpExtensionDescriptor(inputData.proto.extension, inputData, sb, string.Empty);

            foreach (var field in inputData.proto.enum_type)
            {
                DumpEnumDescriptor(field, inputData.extensions, sb, 0);
            }

            foreach (var proto in inputData.proto.message_type)
            {
                DumpDescriptor(proto, inputData, sb, 0);
            }

            foreach (var service in inputData.proto.service)
            {
                sb.AppendLine($"service {service.name} {{");

                foreach (var option in DumpOptions(service.options, inputData.extensions))
                {
                    sb.AppendLine($"\toption {option.Key} = {option.Value};");
                }

                foreach (var method in service.method)
                {
                    var declaration = $"\trpc {method.name} ({method.input_type}) returns ({method.output_type})";

                    var options = DumpOptions(method.options, inputData.extensions);

                    var parameters = string.Empty;
                    if (options.Count == 0)
                    {
                        sb.AppendLine($"{declaration};");
                    }
                    else
                    {
                        sb.AppendLine($"{declaration} {{");

                        foreach (var option in options)
                        {
                            sb.AppendLine($"\t\toption {option.Key} = {option.Value};");
                        }

                        sb.AppendLine("\t}");
                    }
                }

                sb.AppendLine("}");
            }

            if (!string.IsNullOrEmpty(inputData.proto.package))
            {
                PopDescriptorName();
            }
        }
Ejemplo n.º 7
0
        private void DumpExtensionDescriptor(IEnumerable <FieldDescriptorProto> fields, ProtoInputData inputData, StringBuilder sb, string levelspace)
        {
            foreach (var mapping in fields.GroupBy(x => x.extendee))
            {
                if (string.IsNullOrEmpty(mapping.Key))
                {
                    throw new Exception("Empty extendee in extension, this should not be possible");
                }

                if (mapping.Key.StartsWith(".google.protobuf", StringComparison.Ordinal))
                {
                    BuildExtension(mapping.Key.Substring(1), mapping.ToArray(), inputData);
                }

                sb.AppendLine($"{levelspace}extend {mapping.Key} {{");

                foreach (var field in mapping)
                {
                    sb.AppendLine($"{levelspace}\t{BuildDescriptorDeclaration(field, inputData.extensions)}");
                }

                sb.AppendLine($"{levelspace}}}");
                sb.AppendLine();
            }
        }