diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..c90128e3 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,46 @@ +version: 2.1 + +jobs: + # skipping build step because Gemfile.lock is not included in the source + # this makes the bundler caching step a noop + test: + parameters: + ruby-image: + type: string + docker: + - image: << parameters.ruby-image >> + steps: + - run: + name: Install protobuf compiler + command: | + archive=protoc-3.16.0-linux-x86_64 + curl -O -L https://github.com/protocolbuffers/protobuf/releases/download/v3.16.0/$archive.zip + sudo unzip -d '/usr/local' $archive.zip 'bin/*' 'include/*' + sudo chown -R $(whoami) /usr/local/bin/protoc /usr/local/include/google + rm -rf $archive.zip + - run: + command: protoc --version + - run: + command: sudo apt-get update + - run: + message: Install ZeroMQ + command: sudo apt-get -y install libzmq3-dev + - checkout + - run: + command: gem install bundler + - run: + command: bundle install + - run: + command: bundle exec rake + +workflows: + build_and_test: + jobs: + - test: + matrix: + parameters: + ruby-image: + - circleci/jruby:9.2.6.0-jdk + - circleci/jruby:9.1.17.0-jdk + - circleci/ruby:2.5 + - circleci/ruby:2.7 diff --git a/.rubocop.yml b/.rubocop.yml index 9972b631..ea05f74d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,9 +4,13 @@ AllCops: DisplayCopNames: true Exclude: - 'spec/support/protos/*.pb.rb' + - 'varint_prof.rb' -Lint/EndAlignment: - AlignWith: keyword +Bundler/DuplicatedGem: + Enabled: false + +Layout/EndAlignment: + EnforcedStyleAlignWith: keyword Lint/Loop: Enabled: false @@ -17,25 +21,26 @@ Metrics/ClassLength: Metrics/ModuleLength: Enabled: false -Style/CaseIndentation: - IndentWhenRelativeTo: end +Layout/CaseIndentation: + EnforcedStyle: end Style/ClassAndModuleChildren: Exclude: - '**/*.pb.rb' + - 'spec/**/*.rb' -Style/ClassAndModuleCamelCase: +Naming/ClassAndModuleCamelCase: Exclude: - '**/*.pb.rb' -Style/EmptyLineBetweenDefs: +Layout/EmptyLineBetweenDefs: AllowAdjacentOneLineDefs: true -Style/EmptyLines: +Layout/EmptyLines: Exclude: - '**/*.pb.rb' -Style/FileName: +Naming/FileName: Exclude: - '**/protoc-gen-ruby*' @@ -45,7 +50,7 @@ Style/GuardClause: Style/HashSyntax: EnforcedStyle: hash_rockets -Style/IndentHash: +Layout/FirstHashElementIndentation: EnforcedStyle: consistent Style/Semicolon: @@ -54,16 +59,23 @@ Style/Semicolon: Style/SingleLineBlockParams: Enabled: false -Style/TrailingBlankLines: +Layout/TrailingEmptyLines: Exclude: - '**/*.pb.rb' Style/TrailingCommaInArguments: EnforcedStyleForMultiline: comma -Style/TrailingCommaInLiteral: +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: comma + +Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: comma Style/TrivialAccessors: AllowDSLWriters: true AllowPredicates: true + +Style/Encoding: + Exclude: + - '**/*.pb.rb' diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 611730ad..bd670fea 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,30 +1,208 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2015-09-25 12:31:31 -0700 using RuboCop version 0.34.2. +# on 2020-04-13 09:00:39 +0200 using RuboCop version 0.81.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 31 +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: TreatCommentsAsGroupSeparators, Include. +# Include: **/*.gemspec +Gemspec/OrderedDependencies: + Exclude: + - 'protobuf.gemspec' + +# Offense count: 2 +# Configuration parameters: Include. +# Include: **/*.gemspec +Gemspec/RubyVersionGlobalsUsage: + Exclude: + - 'protobuf.gemspec' + +# Offense count: 2 +# Cop supports --auto-correct. +Layout/ClosingParenthesisIndentation: + Exclude: + - 'spec/lib/protobuf/generators/base_spec.rb' + - 'spec/lib/protobuf/rpc/service_spec.rb' + +# Offense count: 42 +# Cop supports --auto-correct. +Layout/EmptyLineAfterGuardClause: + Enabled: false + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/EmptyLineAfterMagicComment: + Exclude: + - 'protobuf.gemspec' + +# Offense count: 83 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, no_empty_lines +Layout/EmptyLinesAroundBlockBody: + Enabled: false + +# Offense count: 75 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only +Layout/EmptyLinesAroundClassBody: + Enabled: false + +# Offense count: 39 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines +Layout/EmptyLinesAroundModuleBody: + Enabled: false + +# Offense count: 30 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. +# SupportedHashRocketStyles: key, separator, table +# SupportedColonStyles: key, separator, table +# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit +Layout/HashAlignment: + Exclude: + - 'Rakefile' + - 'lib/protobuf/field.rb' + - 'lib/protobuf/rpc/connectors/base.rb' + - 'spec/lib/protobuf/enum_spec.rb' + - 'spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb' + +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: squiggly, active_support, powerpack, unindent +Layout/HeredocIndentation: + Exclude: + - 'spec/lib/protobuf/generators/enum_generator_spec.rb' + - 'spec/lib/protobuf/generators/file_generator_spec.rb' + - 'spec/lib/protobuf/generators/service_generator_spec.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineArrayBraceLayout: + Exclude: + - 'spec/lib/protobuf/generators/field_generator_spec.rb' + - 'spec/lib/protobuf/message_spec.rb' + +# Offense count: 10 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: symmetrical, new_line, same_line +Layout/MultilineMethodCallBraceLayout: + Exclude: + - 'spec/functional/code_generator_spec.rb' + - 'spec/lib/protobuf/generators/field_generator_spec.rb' + - 'spec/lib/protobuf/optionable_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, IndentationWidth. +# SupportedStyles: aligned, indented, indented_relative_to_receiver +Layout/MultilineMethodCallIndentation: + Exclude: + - 'spec/lib/protobuf/generators/file_generator_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/RescueEnsureAlignment: + Exclude: + - 'lib/protobuf/rpc/servers/socket/server.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +Layout/SpaceAfterNot: + Exclude: + - 'lib/protobuf/field/base_field.rb' + - 'lib/protobuf/rpc/connectors/zmq.rb' + - 'lib/protobuf/rpc/servers/socket/worker.rb' + - 'lib/protobuf/tasks/compile.rake' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator. +# SupportedStylesForExponentOperator: space, no_space +Layout/SpaceAroundOperators: + Exclude: + - 'lib/protobuf/field/base_field.rb' + +# Offense count: 6 +Lint/DuplicateMethods: + Exclude: + - 'lib/protobuf/generators/field_generator.rb' + - 'lib/protobuf/rpc/buffer.rb' + - 'lib/protobuf/rpc/stat.rb' + +# Offense count: 1 +Lint/EmptyWhen: + Exclude: + - 'lib/protobuf/rpc/servers/socket/server.rb' + +# Offense count: 1 +Lint/InterpolationCheck: + Exclude: + - 'spec/lib/protobuf/message_spec.rb' + +# Offense count: 1 +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'lib/protobuf/message/fields.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +Lint/RedundantCopDisableDirective: + Exclude: + - 'lib/protobuf.rb' + - 'lib/protobuf/message/fields.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +Lint/RedundantRequireStatement: + Exclude: + - 'lib/protobuf/rpc/servers/zmq/broker.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + - 'lib/protobuf/rpc/servers/zmq/worker.rb' + - 'lib/protobuf/rpc/servers/zmq_runner.rb' + - 'lib/protobuf/rpc/service_directory.rb' + +# Offense count: 2 +# Configuration parameters: AllowComments. +Lint/SuppressedException: + Exclude: + - 'lib/protobuf.rb' + +# Offense count: 44 +# Configuration parameters: IgnoredMethods. Metrics/AbcSize: - Max: 59 + Max: 55 + +# Offense count: 116 +# Configuration parameters: CountComments, ExcludedMethods. +# ExcludedMethods: refine +Metrics/BlockLength: + Max: 742 # Offense count: 1 +# Configuration parameters: CountBlocks. Metrics/BlockNesting: Max: 5 -# Offense count: 6 +# Offense count: 19 +# Configuration parameters: IgnoredMethods. Metrics/CyclomaticComplexity: Max: 12 -# Offense count: 493 -# Configuration parameters: AllowURI, URISchemes. -Metrics/LineLength: - Max: 199 - -# Offense count: 44 -# Configuration parameters: CountComments. +# Offense count: 65 +# Configuration parameters: CountComments, ExcludedMethods. Metrics/MethodLength: Max: 38 @@ -33,21 +211,73 @@ Metrics/MethodLength: Metrics/ParameterLists: Max: 7 -# Offense count: 6 +# Offense count: 18 +# Configuration parameters: IgnoredMethods. Metrics/PerceivedComplexity: - Max: 17 + Max: 13 -# Offense count: 1 +# Offense count: 5 +# Configuration parameters: ForbiddenDelimiters. +# ForbiddenDelimiters: (?-mix:(^|\s)(EO[A-Z]{1}|END)(\s|$)) +Naming/HeredocDelimiterNaming: + Exclude: + - 'spec/lib/protobuf/generators/file_generator_spec.rb' + - 'spec/lib/protobuf/generators/service_generator_spec.rb' + +# Offense count: 13 +# Configuration parameters: EnforcedStyleForLeadingUnderscores. +# SupportedStylesForLeadingUnderscores: disallowed, required, optional +Naming/MemoizedInstanceVariableName: + Exclude: + - 'lib/protobuf/field/base_field.rb' + - 'lib/protobuf/logging.rb' + - 'lib/protobuf/rpc/client.rb' + - 'lib/protobuf/rpc/connectors/base.rb' + - 'lib/protobuf/rpc/connectors/socket.rb' + - 'lib/protobuf/rpc/connectors/zmq.rb' + - 'lib/protobuf/rpc/server.rb' + - 'lib/protobuf/rpc/servers/socket/server.rb' + - 'lib/protobuf/rpc/servers/socket/worker.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + - 'lib/protobuf/rpc/stat.rb' + - 'spec/support/server.rb' + +# Offense count: 2 +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: io, id, to, by, on, in, at, ip, db, os, pp +Naming/MethodParameterName: + Exclude: + - 'lib/protobuf/logging.rb' + - 'spec/lib/protobuf/rpc/service_filters_spec.rb' + +# Offense count: 6 # Cop supports --auto-correct. -Performance/StringReplacement: +# Configuration parameters: PreferredName. +Naming/RescuedExceptionsVariableName: Exclude: - - 'lib/protobuf/rpc/buffer.rb' + - 'lib/protobuf/rpc/connectors/base.rb' + - 'lib/protobuf/rpc/middleware/exception_handler.rb' + - 'lib/protobuf/rpc/middleware/request_decoder.rb' + - 'lib/protobuf/rpc/middleware/response_encoder.rb' + - 'lib/protobuf/rpc/service_filters.rb' -Performance/TimesMap: - Enabled: false +# Offense count: 6 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, EnforcedStyle. +# SupportedStyles: nested, compact +Style/ClassAndModuleChildren: + Exclude: + - '**/*.pb.rb' + - 'spec/lib/protobuf/generators/field_generator_spec.rb' + - 'spec/lib/protobuf/generators/service_generator_spec.rb' + +# Offense count: 2 +Style/CommentedKeyword: + Exclude: + - 'lib/protobuf/rpc/servers/socket_runner.rb' + - 'lib/protobuf/rpc/servers/zmq_runner.rb' -# Offense count: 127 -# Configuration parameters: Exclude. +# Offense count: 203 Style/Documentation: Enabled: false @@ -62,84 +292,250 @@ Style/DoubleNegation: - 'lib/protobuf/rpc/servers/zmq/worker.rb' - 'lib/protobuf/rpc/service_directory.rb' +# Offense count: 9 +# Cop supports --auto-correct. +Style/EmptyCaseCondition: + Exclude: + - 'lib/protobuf/enum.rb' + - 'lib/protobuf/field/base_field.rb' + - 'lib/protobuf/rpc/connectors/zmq.rb' + - 'lib/protobuf/rpc/servers/socket/server.rb' + - 'lib/protobuf/rpc/servers/socket_runner.rb' + - 'lib/protobuf/rpc/servers/zmq_runner.rb' + # Offense count: 2 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: empty, nil, both Style/EmptyElse: Exclude: - 'lib/protobuf/enum.rb' - 'lib/protobuf/message/fields.rb' -# Offense count: 77 +# Offense count: 1 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/EmptyLinesAroundBlockBody: - Enabled: false +# Configuration parameters: EnforcedStyle. +# SupportedStyles: compact, expanded +Style/EmptyMethod: + Exclude: + - 'lib/protobuf/code_generator.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Style/Encoding: + Exclude: + - '**/*.pb.rb' + - 'protobuf.gemspec' + - 'spec/lib/protobuf/field/string_field_spec.rb' + - 'spec/lib/protobuf/message_spec.rb' -# Offense count: 90 +# Offense count: 1 +Style/EvalWithLocation: + Exclude: + - 'lib/protobuf/message/fields.rb' + +# Offense count: 2 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/EmptyLinesAroundClassBody: +Style/ExpandPathArguments: + Exclude: + - 'spec/benchmark/tasks.rb' + - 'spec/lib/protobuf/cli_spec.rb' + +# Offense count: 167 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: always, always_true, never +Style/FrozenStringLiteralComment: Enabled: false -# Offense count: 50 +# Offense count: 1 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Exclude: + - 'lib/protobuf/generators/base.rb' + +# Offense count: 22 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -Style/EmptyLinesAroundModuleBody: +Style/IfUnlessModifier: Enabled: false -# Offense count: 2 -Style/IndentationWidth: +# Offense count: 1 +Style/MethodMissingSuper: Exclude: - - 'protobuf.gemspec' - - 'lib/protobuf/cli.rb' + - 'lib/protobuf/rpc/client.rb' -# Offense count: 3 -Style/ElseAlignment: +# Offense count: 1 +Style/MissingRespondToMissing: Exclude: - - 'protobuf.gemspec' - - 'lib/protobuf/cli.rb' + - 'lib/protobuf/rpc/client.rb' -# Offense count: 8 +# Offense count: 17 # Cop supports --auto-correct. -# Configuration parameters: AllowForAlignment. -Style/ExtraSpacing: +Style/MultilineWhenThen: Exclude: - - 'lib/protobuf/rpc/connectors/common.rb' - - 'lib/protobuf/rpc/connectors/socket.rb' + - 'lib/protobuf/generators/field_generator.rb' + - 'lib/protobuf/generators/printable.rb' - 'lib/protobuf/rpc/connectors/zmq.rb' - - 'lib/protobuf/rpc/servers/socket/server.rb' - - 'spec/lib/protobuf/rpc/service_directory_spec.rb' + - 'lib/protobuf/rpc/servers/socket_runner.rb' + - 'lib/protobuf/rpc/servers/zmq_runner.rb' + +# Offense count: 1 +Style/MultipleComparison: + Exclude: + - 'lib/protobuf/generators/group_generator.rb' + +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'lib/protobuf/generators/field_generator.rb' + - 'lib/protobuf/rpc/buffer.rb' + - 'lib/protobuf/rpc/servers/zmq/util.rb' -# Offense count: 46 +# Offense count: 51 # Cop supports --auto-correct. +# Configuration parameters: Strict. Style/NumericLiterals: MinDigits: 21 +# Offense count: 10 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. +# SupportedStyles: predicate, comparison +Style/NumericPredicate: + Exclude: + - 'spec/**/*' + - 'lib/protobuf/generators/file_generator.rb' + - 'lib/protobuf/generators/message_generator.rb' + - 'lib/protobuf/rpc/buffer.rb' + - 'lib/protobuf/rpc/servers/socket/server.rb' + - 'lib/protobuf/rpc/servers/zmq/broker.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + - 'lib/protobuf/rpc/servers/zmq/worker.rb' + +# Offense count: 15 +# Cop supports --auto-correct. +# Configuration parameters: PreferredDelimiters. +Style/PercentLiteralDelimiters: + Exclude: + - 'lib/protobuf/cli.rb' + - 'spec/lib/protobuf/field/field_array_spec.rb' + - 'spec/lib/protobuf/rpc/service_directory_spec.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Style/RedundantBegin: + Exclude: + - 'lib/protobuf/message/fields.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantCondition: + Exclude: + - 'lib/protobuf/rpc/connectors/base.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +Style/RedundantInterpolation: + Exclude: + - 'lib/protobuf.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Exclude: + - 'lib/protobuf/field/int64_field.rb' + - 'lib/protobuf/rpc/connectors/base.rb' + - 'lib/protobuf/rpc/connectors/zmq.rb' + +# Offense count: 23 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'lib/protobuf/cli.rb' + - 'lib/protobuf/field/int64_field.rb' + - 'lib/protobuf/field/varint_field.rb' + - 'lib/protobuf/generators/file_generator.rb' + - 'lib/protobuf/message.rb' + - 'lib/protobuf/rpc/connectors/base.rb' + - 'lib/protobuf/rpc/connectors/ping.rb' + - 'lib/protobuf/rpc/connectors/socket.rb' + - 'lib/protobuf/rpc/middleware/exception_handler.rb' + - 'lib/protobuf/rpc/middleware/request_decoder.rb' + - 'lib/protobuf/rpc/middleware/response_encoder.rb' + - 'lib/protobuf/rpc/servers/zmq/broker.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + - 'lib/protobuf/rpc/servers/zmq/worker.rb' + - 'lib/protobuf/rpc/service_directory.rb' + +# Offense count: 9 +# Cop supports --auto-correct. +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. +# AllowedMethods: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'lib/protobuf/generators/field_generator.rb' + - 'lib/protobuf/generators/service_generator.rb' + - 'lib/protobuf/message/serialization.rb' + - 'lib/protobuf/rpc/connectors/base.rb' + - 'lib/protobuf/rpc/connectors/ping.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + +# Offense count: 71 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: only_raise, only_fail, semantic Style/SignalException: Enabled: false -# Offense count: 473 +# Offense count: 6 +# Cop supports --auto-correct. +Style/StderrPuts: + Exclude: + - 'lib/protobuf/cli.rb' + - 'lib/protobuf/code_generator.rb' + - 'lib/protobuf/rpc/servers/zmq/server.rb' + +# Offense count: 627 # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. +# SupportedStyles: single_quotes, double_quotes Style/StringLiterals: Enabled: false -# Offense count: 7 +# Offense count: 26 # Cop supports --auto-correct. -# Configuration parameters: IgnoredMethods. -Style/SymbolProc: +# Configuration parameters: MinSize. +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: brackets + +# Offense count: 4 +# Cop supports --auto-correct. +Style/UnpackFirst: Exclude: - - 'lib/protobuf/generators/printable.rb' - - 'lib/protobuf/rpc/servers/socket/server.rb' - - 'spec/encoding/all_types_spec.rb' - - 'spec/encoding/extreme_values_spec.rb' - - 'spec/functional/socket_server_spec.rb' - - 'spec/functional/zmq_server_spec.rb' - - 'spec/lib/protobuf/rpc/servers/socket_server_spec.rb' + - 'lib/protobuf/field/double_field.rb' + - 'lib/protobuf/field/fixed32_field.rb' + - 'lib/protobuf/field/float_field.rb' + - 'lib/protobuf/field/sfixed32_field.rb' # Offense count: 4 # Cop supports --auto-correct. # Configuration parameters: WordRegex. +# SupportedStyles: percent, brackets Style/WordArray: - MinSize: 4 + EnforcedStyle: percent + MinSize: 3 + +# Offense count: 728 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. +# URISchemes: http, https +Layout/LineLength: + Max: 196 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f0153d97..00000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -before_install: - - wget https://github.com/zeromq/libzmq/releases/download/v4.2.1/zeromq-4.2.1.tar.gz - - tar xvf zeromq-4.2.1.tar.gz - - cd zeromq-4.2.1 - - ./configure - - make -j4 - - sudo make install - # Retrun to project directory - - cd .. - - sudo -E ./install-protobuf.sh - - java -Xmx1g -version - - javac -J-Xmx1g -version - - export JRUBY_OPTS=-J-Xmx1g - # Required for rainbow installation issue, https://github.com/sickill/rainbow/issues/44 - - gem update --system - - gem update bundler -language: ruby -rvm: - - 1.9.3 - - 2.0.0 - - 2.1 - - 2.2 - - 2.2.2 - - 2.3 - - 2.4 - - jruby-9.1.7.0 - - rbx-2 -env: - - PROTOBUF_VERSION=2.6.1 - - PROTOBUF_VERSION=3.0.0-alpha-2 -matrix: - allow_failures: - - rvm: rbx-2 - - env: PROTOBUF_VERSION=3.0.0-alpha-2 -notifications: - webhooks: - urls: - - https://webhooks.gitter.im/e/51a956bcd2b1854d6756 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/CHANGES.md b/CHANGES.md index 2677938a..032d0ce5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,15 @@ # Stable (3.8.x) + +3.10.0 +------ +- Add headers to request proto +- Add support for compiling v3 protos with optional fields as v2 optional fields + +3.9.0 +----- +- Performance improvements + 3.8.0 ----- - Map types now supported (#367) diff --git a/Gemfile b/Gemfile index d5b5bd21..ea1fdd91 100644 --- a/Gemfile +++ b/Gemfile @@ -1,5 +1,26 @@ source 'https://rubygems.org/' -gem 'protobuf_java_helpers', :path => "~/code/protobuf_java_helpers" - gemspec + +group :development do + # debuggers only work in MRI + if RUBY_ENGINE.to_sym == :ruby + if RUBY_VERSION < '2.0.0' + gem 'pry-debugger' + elsif RUBY_VERSION < '2.4.0' + gem 'pry', '~> 0.12.0' + gem 'pry-byebug' + else + gem 'pry', '~> 0.13.0' + gem 'pry-byebug', '~> 3.9.0' + end + + gem 'pry-stack_explorer' + + gem 'ruby-prof' + gem 'varint' + elsif RUBY_PLATFORM =~ /java/i + gem 'fast_blank_java' + gem 'pry' + end +end diff --git a/Rakefile b/Rakefile index 8df9895f..cecc48a4 100644 --- a/Rakefile +++ b/Rakefile @@ -22,10 +22,12 @@ namespace :compile do task :spec do proto_path = ::File.expand_path('../spec/support/', __FILE__) proto_files = Dir[File.join(proto_path, '**', '*.proto')] - cmd = %(protoc --plugin=./bin/protoc-gen-ruby --ruby_out=#{proto_path} -I #{proto_path} #{proto_files.join(' ')}) - puts cmd - system(cmd) + proto_files.each do |proto_file| + cmd = %(protoc --plugin=protoc-gen-ruby-protobuf=./bin/protoc-gen-ruby --ruby-protobuf_out=#{proto_path} -I #{proto_path} #{proto_file}) + puts cmd + system(cmd) || fail("Failed to compile spec proto: #{proto_file}") + end end desc 'Compile rpc protos in protos/ directory' @@ -35,10 +37,10 @@ namespace :compile do output_dir = ::File.expand_path('../tmp/rpc', __FILE__) ::FileUtils.mkdir_p(output_dir) - cmd = %(protoc --plugin=./bin/protoc-gen-ruby --ruby_out=#{output_dir} -I #{proto_path} #{proto_files.join(' ')}) + cmd = %(protoc --plugin=protoc-gen-ruby-protobuf=./bin/protoc-gen-ruby --ruby-protobuf_out=#{output_dir} -I #{proto_path} #{proto_files.join(' ')}) puts cmd - system(cmd) + system(cmd) || fail("Failed to compile rpc protos!") files = { 'tmp/rpc/dynamic_discovery.pb.rb' => 'lib/protobuf/rpc', diff --git a/install-protobuf.sh b/install-protobuf.sh deleted file mode 100755 index b3872fd0..00000000 --- a/install-protobuf.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env sh - -set -ex - -gdie() { - echo "$@" >&2 - exit 1 -} - -test -n "$PROTOBUF_VERSION" || die "PROTOBUF_VERSION env var is undefined" - -case "$PROTOBUF_VERSION" in -2*) - basename=protobuf-$PROTOBUF_VERSION - ;; -3*) - basename=protobuf-cpp-$PROTOBUF_VERSION - ;; -*) - die "unknown protobuf version: $PROTOBUF_VERSION" - ;; -esac - -curl -sL https://github.com/google/protobuf/releases/download/v$PROTOBUF_VERSION/$basename.tar.gz | tar zx - -cd protobuf-$PROTOBUF_VERSION - -./configure --prefix=/usr && make -j2 && make install diff --git a/lib/protobuf.rb b/lib/protobuf.rb index 3f9b7e91..c6040fd4 100644 --- a/lib/protobuf.rb +++ b/lib/protobuf.rb @@ -4,12 +4,20 @@ require 'socket' require 'stringio' +require 'active_support' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' require 'active_support/inflector' require 'active_support/json' require 'active_support/notifications' - +# Under MRI, this optimizes proto decoding by around 15% in tests. +# When unavailable, we fall to pure Ruby. +# rubocop:disable Lint/HandleExceptions +begin + require 'varint/varint' +rescue LoadError +end +# rubocop:enable Lint/HandleExceptions # rubocop:disable Lint/HandleExceptions begin require 'protobuf_java_helpers' @@ -47,6 +55,18 @@ class << self attr_writer :client_host end + def self.after_server_bind(&block) + ::ActiveSupport::Notifications.subscribe('after_server_bind') do |*args| + block.call(*args) + end + end + + def self.before_server_bind(&block) + ::ActiveSupport::Notifications.subscribe('before_server_bind') do |*args| + block.call(*args) + end + end + def self.client_host @client_host ||= Socket.gethostname end diff --git a/lib/protobuf/cli.rb b/lib/protobuf/cli.rb index 3432a0dd..0a84443b 100644 --- a/lib/protobuf/cli.rb +++ b/lib/protobuf/cli.rb @@ -1,3 +1,4 @@ +require 'active_support' require 'active_support/core_ext/hash/keys' require 'active_support/inflector' @@ -240,6 +241,8 @@ def shutdown_server def start_server debug_say('Running server') + ::ActiveSupport::Notifications.instrument("before_server_bind") + runner.run do logger.info do "pid #{::Process.pid} -- #{mode} RPC Server listening at #{options.host}:#{options.port}" diff --git a/lib/protobuf/code_generator.rb b/lib/protobuf/code_generator.rb index 230a7501..0a006f56 100644 --- a/lib/protobuf/code_generator.rb +++ b/lib/protobuf/code_generator.rb @@ -1,3 +1,4 @@ +require 'active_support' require 'active_support/core_ext/module/aliasing' require 'protobuf/generators/file_generator' @@ -46,10 +47,22 @@ def response_bytes generate_file(file_descriptor) end - ::Google::Protobuf::Compiler::CodeGeneratorResponse.encode(:file => generated_files) + ::Google::Protobuf::Compiler::CodeGeneratorResponse.encode( + :file => generated_files, + :supported_features => supported_features, + ) + end + + def supported_features + # The only available feature is proto3 with optional fields. + # This is backwards compatible with proto2 optional fields. + ::Google::Protobuf::Compiler::CodeGeneratorResponse::Feature::FEATURE_PROTO3_OPTIONAL.to_i end Protobuf::Field::BaseField.module_eval do + def define_set_method! + end + def set_without_options(message_instance, bytes) return message_instance[name] = decode(bytes) unless repeated? @@ -98,6 +111,7 @@ def set_with_options(message_instance, bytes) set_without_options(message_instance, bytes) end + alias_method :set, :set_with_options def option_set(message_field, subfield, subvalue) return unless yield diff --git a/lib/protobuf/deprecation.rb b/lib/protobuf/deprecation.rb index 8c0d415e..97b56698 100644 --- a/lib/protobuf/deprecation.rb +++ b/lib/protobuf/deprecation.rb @@ -1,3 +1,4 @@ +require 'active_support' require 'active_support/deprecation' module Protobuf diff --git a/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb b/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb index 354aa845..62e17f56 100644 --- a/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +++ b/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb @@ -19,8 +19,14 @@ module Compiler ## # Message Classes # + class Version < ::Protobuf::Message; end class CodeGeneratorRequest < ::Protobuf::Message; end class CodeGeneratorResponse < ::Protobuf::Message + class Feature < ::Protobuf::Enum + define :FEATURE_NONE, 0 + define :FEATURE_PROTO3_OPTIONAL, 1 + end + class File < ::Protobuf::Message; end end @@ -32,15 +38,24 @@ class File < ::Protobuf::Message; end # set_option :java_package, "com.google.protobuf.compiler" set_option :java_outer_classname, "PluginProtos" + set_option :go_package, "google.golang.org/protobuf/types/pluginpb" ## # Message Fields # + class Version + optional :int32, :major, 1 + optional :int32, :minor, 2 + optional :int32, :patch, 3 + optional :string, :suffix, 4 + end + class CodeGeneratorRequest repeated :string, :file_to_generate, 1 optional :string, :parameter, 2 repeated ::Google::Protobuf::FileDescriptorProto, :proto_file, 15 + optional ::Google::Protobuf::Compiler::Version, :compiler_version, 3 end class CodeGeneratorResponse @@ -48,9 +63,11 @@ class File optional :string, :name, 1 optional :string, :insertion_point, 2 optional :string, :content, 15 + optional ::Google::Protobuf::GeneratedCodeInfo, :generated_code_info, 16 end optional :string, :error, 1 + optional :uint64, :supported_features, 2 repeated ::Google::Protobuf::Compiler::CodeGeneratorResponse::File, :file, 15 end diff --git a/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb b/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb index 534d83a5..acff3ebd 100644 --- a/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +++ b/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb @@ -20,6 +20,7 @@ class ReservedRange < ::Protobuf::Message; end end + class ExtensionRangeOptions < ::Protobuf::Message; end class FieldDescriptorProto < ::Protobuf::Message class Type < ::Protobuf::Enum define :TYPE_DOUBLE, 1 @@ -51,7 +52,11 @@ class Label < ::Protobuf::Enum end class OneofDescriptorProto < ::Protobuf::Message; end - class EnumDescriptorProto < ::Protobuf::Message; end + class EnumDescriptorProto < ::Protobuf::Message + class EnumReservedRange < ::Protobuf::Message; end + + end + class EnumValueDescriptorProto < ::Protobuf::Message; end class ServiceDescriptorProto < ::Protobuf::Message; end class MethodDescriptorProto < ::Protobuf::Message; end @@ -80,10 +85,19 @@ class JSType < ::Protobuf::Enum end + class OneofOptions < ::Protobuf::Message; end class EnumOptions < ::Protobuf::Message; end class EnumValueOptions < ::Protobuf::Message; end class ServiceOptions < ::Protobuf::Message; end - class MethodOptions < ::Protobuf::Message; end + class MethodOptions < ::Protobuf::Message + class IdempotencyLevel < ::Protobuf::Enum + define :IDEMPOTENCY_UNKNOWN, 0 + define :NO_SIDE_EFFECTS, 1 + define :IDEMPOTENT, 2 + end + + end + class UninterpretedOption < ::Protobuf::Message class NamePart < ::Protobuf::Message; end @@ -94,6 +108,11 @@ class Location < ::Protobuf::Message; end end + class GeneratedCodeInfo < ::Protobuf::Message + class Annotation < ::Protobuf::Message; end + + end + ## @@ -102,7 +121,8 @@ class Location < ::Protobuf::Message; end set_option :java_package, "com.google.protobuf" set_option :java_outer_classname, "DescriptorProtos" set_option :optimize_for, ::Google::Protobuf::FileOptions::OptimizeMode::SPEED - set_option :go_package, "descriptor" + set_option :go_package, "google.golang.org/protobuf/types/descriptorpb" + set_option :cc_enable_arenas, true set_option :objc_class_prefix, "GPB" set_option :csharp_namespace, "Google.Protobuf.Reflection" @@ -133,6 +153,7 @@ class DescriptorProto class ExtensionRange optional :int32, :start, 1 optional :int32, :end, 2 + optional ::Google::Protobuf::ExtensionRangeOptions, :options, 3 end class ReservedRange @@ -152,6 +173,12 @@ class ReservedRange repeated :string, :reserved_name, 10 end + class ExtensionRangeOptions + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + class FieldDescriptorProto optional :string, :name, 1 optional :int32, :number, 3 @@ -163,16 +190,25 @@ class FieldDescriptorProto optional :int32, :oneof_index, 9 optional :string, :json_name, 10 optional ::Google::Protobuf::FieldOptions, :options, 8 + optional :bool, :proto3_optional, 17 end class OneofDescriptorProto optional :string, :name, 1 + optional ::Google::Protobuf::OneofOptions, :options, 2 end class EnumDescriptorProto + class EnumReservedRange + optional :int32, :start, 1 + optional :int32, :end, 2 + end + optional :string, :name, 1 repeated ::Google::Protobuf::EnumValueDescriptorProto, :value, 2 optional ::Google::Protobuf::EnumOptions, :options, 3 + repeated ::Google::Protobuf::EnumDescriptorProto::EnumReservedRange, :reserved_range, 4 + repeated :string, :reserved_name, 5 end class EnumValueDescriptorProto @@ -200,18 +236,23 @@ class FileOptions optional :string, :java_package, 1 optional :string, :java_outer_classname, 8 optional :bool, :java_multiple_files, 10, :default => false - optional :bool, :java_generate_equals_and_hash, 20, :default => false + optional :bool, :java_generate_equals_and_hash, 20, :deprecated => true optional :bool, :java_string_check_utf8, 27, :default => false optional ::Google::Protobuf::FileOptions::OptimizeMode, :optimize_for, 9, :default => ::Google::Protobuf::FileOptions::OptimizeMode::SPEED optional :string, :go_package, 11 optional :bool, :cc_generic_services, 16, :default => false optional :bool, :java_generic_services, 17, :default => false optional :bool, :py_generic_services, 18, :default => false + optional :bool, :php_generic_services, 42, :default => false optional :bool, :deprecated, 23, :default => false - optional :bool, :cc_enable_arenas, 31, :default => false + optional :bool, :cc_enable_arenas, 31, :default => true optional :string, :objc_class_prefix, 36 optional :string, :csharp_namespace, 37 - optional :bool, :javanano_use_deprecated_package, 38 + optional :string, :swift_prefix, 39 + optional :string, :php_class_prefix, 40 + optional :string, :php_namespace, 41 + optional :string, :php_metadata_namespace, 44 + optional :string, :ruby_package, 45 repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 # Extension Fields extensions 1000...536870912 @@ -239,6 +280,12 @@ class FieldOptions extensions 1000...536870912 end + class OneofOptions + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + class EnumOptions optional :bool, :allow_alias, 2 optional :bool, :deprecated, 3, :default => false @@ -263,6 +310,7 @@ class ServiceOptions class MethodOptions optional :bool, :deprecated, 33, :default => false + optional ::Google::Protobuf::MethodOptions::IdempotencyLevel, :idempotency_level, 34, :default => ::Google::Protobuf::MethodOptions::IdempotencyLevel::IDEMPOTENCY_UNKNOWN repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 # Extension Fields extensions 1000...536870912 @@ -295,6 +343,17 @@ class Location repeated ::Google::Protobuf::SourceCodeInfo::Location, :location, 1 end + class GeneratedCodeInfo + class Annotation + repeated :int32, :path, 1, :packed => true + optional :string, :source_file, 2 + optional :int32, :begin, 3 + optional :int32, :end, 4 + end + + repeated ::Google::Protobuf::GeneratedCodeInfo::Annotation, :annotation, 1 + end + end end diff --git a/lib/protobuf/enum.rb b/lib/protobuf/enum.rb index c38b216b..c0a2a809 100644 --- a/lib/protobuf/enum.rb +++ b/lib/protobuf/enum.rb @@ -313,10 +313,6 @@ def inspect "\#" end - def to_i - tag - end - def to_int tag.to_int end @@ -357,12 +353,13 @@ def try(*args, &block) end end - ::Protobuf.deprecator.define_deprecated_methods(self, :value => :to_i) - ## # Instance Aliases # - alias :to_hash_value to_i - alias :to_json_hash_value to_i + alias :to_i tag + alias :to_hash_value tag + alias :to_json_hash_value tag + + ::Protobuf.deprecator.define_deprecated_methods(self, :value => :to_i) end end diff --git a/lib/protobuf/field/base_field.rb b/lib/protobuf/field/base_field.rb index 689b23ca..86472738 100644 --- a/lib/protobuf/field/base_field.rb +++ b/lib/protobuf/field/base_field.rb @@ -1,7 +1,8 @@ +require 'active_support' require 'active_support/core_ext/hash/slice' require 'protobuf/field/field_array' require 'protobuf/field/field_hash' -require 'protobuf/field/base_field_method_definitions' +require 'protobuf/field/base_field_object_definitions' module Protobuf module Field @@ -12,7 +13,7 @@ class BaseField ## # Constants # - + OBJECT_MODULE = ::Protobuf::Field::BaseFieldObjectDefinitions PACKED_TYPES = [ ::Protobuf::WireType::VARINT, ::Protobuf::WireType::FIXED32, @@ -22,7 +23,7 @@ class BaseField ## # Attributes # - attr_reader :message_class, :name, :fully_qualified_name, :options, :rule, :tag, :type_class + attr_reader :default_value, :message_class, :name, :fully_qualified_name, :options, :rule, :tag, :type_class ## # Class Methods @@ -61,15 +62,25 @@ def initialize(message_class, rule, type_class, fully_qualified_name, tag, simpl define_accessor(simple_name, fully_qualified_name) if simple_name set_repeated_message! set_map! - define_hash_accessor_for_message! - define_field_p! - define_field_and_present_p! + @value_from_values = nil + @value_from_values_for_serialization = nil + @field_predicate = nil + @field_and_present_predicate = nil + @set_field = nil + @set_method = nil + @to_message_hash = nil + @to_message_hash_string_keys = nil + @encode_to_stream = nil + + define_value_from_values! + define_value_from_values_for_serialization! + define_field_predicate! + define_field_and_present_predicate! define_set_field! define_set_method! define_to_message_hash! define_encode_to_stream! set_default_value! - tag_encoded end ## @@ -104,72 +115,122 @@ def set_default_value! end end - def default_value - @default_value + def define_encode_to_stream! + @encode_to_stream = if repeated? && packed? + OBJECT_MODULE::RepeatedPackedEncodeToStream.new(self) + elsif repeated? + OBJECT_MODULE::RepeatedNotPackedEncodeToStream.new(self) + elsif message? || type_class == ::Protobuf::Field::BytesField + OBJECT_MODULE::BytesEncodeToStream.new(self) + elsif type_class == ::Protobuf::Field::StringField + OBJECT_MODULE::StringEncodeToStream.new(self) + else + OBJECT_MODULE::BaseEncodeToStream.new(self) + end + end + + def encode_to_stream(value, stream) + @encode_to_stream.call(value, stream) + end + + def define_field_predicate! + @field_predicate = if repeated? + OBJECT_MODULE::RepeatedFieldPredicate.new(self) + else + OBJECT_MODULE::BaseFieldPredicate.new(self) + end end - def define_encode_to_stream! - if repeated? && packed? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_packed_encode_to_stream_method!(self) - elsif repeated? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_not_packed_encode_to_stream_method!(self) - elsif message? || type_class == ::Protobuf::Field::BytesField - ::Protobuf::Field::BaseFieldMethodDefinitions.define_bytes_encode_to_stream_method!(self) - elsif type_class == ::Protobuf::Field::StringField - ::Protobuf::Field::BaseFieldMethodDefinitions.define_string_encode_to_stream_method!(self) - else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_base_encode_to_stream_method!(self) - end + def field?(values) + @field_predicate.call(values) end - def define_field_p! - if repeated? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_field_p!(self) - else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_base_field_p!(self) - end + def define_field_and_present_predicate! + @field_and_present_predicate = if !repeated? && type_class == ::Protobuf::Field::BoolField # boolean present check + OBJECT_MODULE::BoolFieldAndPresentPredicate.new(self) + else + OBJECT_MODULE::BaseFieldAndPresentPredicate.new(self) + end end - def define_field_and_present_p! - if type_class == ::Protobuf::Field::BoolField # boolean present check - ::Protobuf::Field::BaseFieldMethodDefinitions.define_bool_field_and_present_p!(self) - else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_base_field_and_present_p!(self) - end + def field_and_present?(values) + @field_and_present_predicate.call(values) end - def define_hash_accessor_for_message! - if map? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_map_value_from_values!(self) - elsif repeated? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_value_from_values!(self) - elsif type_class == ::Protobuf::Field::BoolField # boolean present check - ::Protobuf::Field::BaseFieldMethodDefinitions.define_bool_field_value_from_values!(self) - else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_field_value_from_values!(self) - end + def define_value_from_values! + @value_from_values = if map? + OBJECT_MODULE::MapValueFromValues.new(self) + elsif repeated? + OBJECT_MODULE::RepeatedFieldValueFromValues.new(self) + elsif type_class == ::Protobuf::Field::BoolField # boolean present check + OBJECT_MODULE::BoolFieldValueFromValues.new(self) + else + OBJECT_MODULE::BaseFieldValueFromValues.new(self) + end + end + + def value_from_values(values) + @value_from_values.call(values) + end + + def define_value_from_values_for_serialization! + @value_from_values_for_serialization = if map? + OBJECT_MODULE::MapValueFromValuesForSerialization.new(self) + elsif repeated? + OBJECT_MODULE::RepeatedFieldValueFromValuesForSerialization.new(self) + elsif type_class == ::Protobuf::Field::BoolField # boolean present check + OBJECT_MODULE::BoolFieldValueFromValuesForSerialization.new(self) + else + OBJECT_MODULE::BaseFieldValueFromValuesForSerialization.new(self) + end + end + + def value_from_values_for_serialization(values) + @value_from_values_for_serialization.call(values) end def define_set_field! - if map? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_map_set_field!(self) - elsif repeated? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_set_field!(self) - elsif type_class == ::Protobuf::Field::StringField - ::Protobuf::Field::BaseFieldMethodDefinitions.define_string_set_field!(self) - else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_base_set_field!(self) - end + @set_field = if map? && required? + OBJECT_MODULE::RequiredMapSetField.new(self) + elsif repeated? && required? + OBJECT_MODULE::RequiredRepeatedSetField.new(self) + elsif type_class == ::Protobuf::Field::StringField && required? + OBJECT_MODULE::RequiredStringSetField.new(self) + elsif required? + OBJECT_MODULE::RequiredBaseSetField.new(self) + elsif map? + OBJECT_MODULE::MapSetField.new(self) + elsif repeated? + OBJECT_MODULE::RepeatedSetField.new(self) + elsif type_class == ::Protobuf::Field::StringField + OBJECT_MODULE::StringSetField.new(self) + else + OBJECT_MODULE::BaseSetField.new(self) + end + end + + def set_field(values, value, ignore_nil_for_repeated, message_instance) + @set_field.call(values, value, ignore_nil_for_repeated, message_instance) end def define_to_message_hash! if message? || enum? || repeated? || map? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_to_hash_value_to_message_hash!(self) + @to_message_hash = OBJECT_MODULE::ToHashValueToMessageHash.new(self) + @to_message_hash_string_keys = OBJECT_MODULE::ToHashValueToMessageHashWithStringKey.new(self) else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_base_to_message_hash!(self) + @to_message_hash = OBJECT_MODULE::BaseToMessageHash.new(self) + @to_message_hash_string_keys = OBJECT_MODULE::BaseToMessageHashWithStringKey.new(self) end end + def to_message_hash(values, result) + @to_message_hash.call(values, result) + end + + def to_message_hash_with_string_key(values, result) + @to_message_hash_string_keys.call(values, result) + end + def deprecated? @deprecated end @@ -224,15 +285,19 @@ def required? end def define_set_method! - if map? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_map_set_method!(self) - elsif repeated? && packed? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_packed_set_method!(self) - elsif repeated? - ::Protobuf::Field::BaseFieldMethodDefinitions.define_repeated_not_packed_set_method!(self) - else - ::Protobuf::Field::BaseFieldMethodDefinitions.define_base_set_method!(self) - end + @set_method = if map? + OBJECT_MODULE::MapSetMethod.new(self) + elsif repeated? && packed? + OBJECT_MODULE::RepeatedPackedSetMethod.new(self) + elsif repeated? + OBJECT_MODULE::RepeatedNotPackedSetMethod.new(self) + else + OBJECT_MODULE::BaseSetMethod.new(self) + end + end + + def set(message_instance, bytes) + @set_method.call(message_instance, bytes) end def tag_encoded @@ -263,9 +328,10 @@ def fully_qualified_name_only! ## # Recreate all of the meta methods as they may have used the original `name` value # - define_hash_accessor_for_message! - define_field_p! - define_field_and_present_p! + define_value_from_values! + define_value_from_values_for_serialization! + define_field_predicate! + define_field_and_present_predicate! define_set_field! define_set_method! define_to_message_hash! diff --git a/lib/protobuf/field/base_field_method_definitions.rb b/lib/protobuf/field/base_field_method_definitions.rb deleted file mode 100644 index 2ff4786c..00000000 --- a/lib/protobuf/field/base_field_method_definitions.rb +++ /dev/null @@ -1,359 +0,0 @@ -module Protobuf - module Field - class BaseFieldMethodDefinitions - - def self.fully_qualified_name_string(selph) - fully_qualified_name = "" - fully_qualified_name << ":" - fully_qualified_name << '"' if selph.fully_qualified_name.to_s.start_with?(".") - fully_qualified_name << selph.fully_qualified_name.to_s - fully_qualified_name << '"' if selph.fully_qualified_name.to_s.start_with?(".") - fully_qualified_name - end - - def self.define_to_hash_value_to_message_hash!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def to_message_hash(values, result) - result[#{selph.name.inspect}] = value_from_values(values).to_hash_value - end - RUBY - end - - def self.define_base_to_message_hash!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def to_message_hash(values, result) - result[#{selph.name.inspect}] = value_from_values(values) - end - RUBY - end - - def self.define_repeated_packed_encode_to_stream_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def encode_to_stream(value, stream) - packed_value = value.map { |val| encode(val) }.join - stream << #{selph.tag_encoded.dump} << "\#{::Protobuf::Field::VarintField.encode(packed_value.size)}\#{packed_value}" - end - RUBY - end - - def self.define_bytes_encode_to_stream_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def encode_to_stream(value, stream) - value = value.encode if value.is_a?(::Protobuf::Message) - byte_size = ::Protobuf::Field::VarintField.encode(value.bytesize) - - stream << #{selph.tag_encoded.dump} << byte_size << value - end - RUBY - end - - def self.define_string_encode_to_stream_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def encode_to_stream(value, stream) - new_value = "" + value - if new_value.encoding != ::Protobuf::Field::StringField::ENCODING - new_value.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "") - end - - stream << #{selph.tag_encoded.dump} << ::Protobuf::Field::VarintField.encode(new_value.bytesize) << new_value - end - RUBY - end - - def self.define_base_encode_to_stream_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def encode_to_stream(value, stream) - stream << #{selph.tag_encoded.dump} << encode(value) - end - RUBY - end - - def self.define_repeated_not_packed_encode_to_stream_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def encode_to_stream(value, stream) - value.each do |val| - stream << #{selph.tag_encoded.dump} << encode(val) - end - end - RUBY - end - - def self.define_base_set_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set(message_instance, bytes) - message_instance.set_field("#{selph.name}", decode(bytes), true, self) - end - RUBY - end - - def self.define_map_set_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set(message_instance, bytes) - hash = message_instance["#{selph.name}"] - entry = decode(bytes) - # decoded value could be nil for an - # enum value that is not recognized - hash[entry.key] = entry.value unless entry.value.nil? - hash[entry.key] - end - RUBY - end - - def self.define_repeated_not_packed_set_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set(message_instance, bytes) - message_instance["#{selph.name}"] << decode(bytes) - end - RUBY - end - - def self.define_repeated_packed_set_method!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set(message_instance, bytes) - array = message_instance["#{selph.name}"] - stream = ::StringIO.new(bytes) - - if wire_type == ::Protobuf::WireType::VARINT - array << decode(Varint.decode(stream)) until stream.eof? - elsif wire_type == ::Protobuf::WireType::FIXED64 - array << decode(stream.read(8)) until stream.eof? - elsif wire_type == ::Protobuf::WireType::FIXED32 - array << decode(stream.read(4)) until stream.eof? - end - end - RUBY - end - - def self.define_map_set_field!(selph) - if selph.required? - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - unless value.is_a?(Hash) - fail TypeError, <<-TYPE_ERROR - Expected map value - Got '\#{value.class}' for map protobuf field #{selph.name} - TYPE_ERROR - end - - if value.empty? - values.delete(#{fully_qualified_name_string(selph)}) - message_instance._protobuf_message_required_field_tags << #{selph.tag} - else - message_instance._protobuf_message_required_field_tags.delete(#{selph.tag}) - values[#{fully_qualified_name_string(selph)}] ||= ::Protobuf::Field::FieldHash.new(self) - values[#{fully_qualified_name_string(selph)}].replace(value) - end - end - RUBY - else - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - unless value.is_a?(Hash) - fail TypeError, <<-TYPE_ERROR - Expected map value - Got '\#{value.class}' for map protobuf field #{selph.name} - TYPE_ERROR - end - - if value.empty? - values.delete(#{fully_qualified_name_string(selph)}) - else - values[#{fully_qualified_name_string(selph)}] ||= ::Protobuf::Field::FieldHash.new(self) - values[#{fully_qualified_name_string(selph)}].replace(value) - end - end - RUBY - end - end - - def self.define_repeated_set_field!(selph) - if selph.required? - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - if value.nil? && ignore_nil_for_repeated - ::Protobuf.deprecator.deprecation_warning("['#{fully_qualified_name_string(selph)}']=nil", "use an empty array instead of nil") - return - end - - unless value.is_a?(Array) - fail TypeError, <<-TYPE_ERROR - Expected repeated value of type '#{selph.type_class}' - Got '\#{value.class}' for repeated protobuf field #{selph.name} - TYPE_ERROR - end - - value = value.compact - - if value.empty? - values.delete(#{fully_qualified_name_string(selph)}) - message_instance._protobuf_message_required_field_tags << #{selph.tag} - else - message_instance._protobuf_message_required_field_tags.delete(#{selph.tag}) - values[#{fully_qualified_name_string(selph)}] ||= ::Protobuf::Field::FieldArray.new(self) - values[#{fully_qualified_name_string(selph)}].replace(value) - end - end - RUBY - else - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - if value.nil? && ignore_nil_for_repeated - ::Protobuf.deprecator.deprecation_warning("['#{fully_qualified_name_string(selph)}']=nil", "use an empty array instead of nil") - return - end - - unless value.is_a?(Array) - fail TypeError, <<-TYPE_ERROR - Expected repeated value of type '#{selph.type_class}' - Got '\#{value.class}' for repeated protobuf field #{selph.name} - TYPE_ERROR - end - - value = value.compact - - if value.empty? - values.delete(#{fully_qualified_name_string(selph)}) - else - values[#{fully_qualified_name_string(selph)}] ||= ::Protobuf::Field::FieldArray.new(self) - values[#{fully_qualified_name_string(selph)}].replace(value) - end - end - RUBY - end - end - - def self.define_string_set_field!(selph) - if selph.required? - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - if value.nil? - values.delete(#{fully_qualified_name_string(selph)}) - message_instance._protobuf_message_required_field_tags << #{selph.tag} - else - message_instance._protobuf_message_required_field_tags.delete(#{selph.tag}) - values[#{fully_qualified_name_string(selph)}] = value.to_s - end - end - RUBY - else - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - if value.nil? - values.delete(#{fully_qualified_name_string(selph)}) - else - values[#{fully_qualified_name_string(selph)}] = value.to_s - end - end - RUBY - end - end - - def self.define_base_set_field!(selph) - if selph.required? - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - if value.nil? - values.delete(#{fully_qualified_name_string(selph)}) - message_instance._protobuf_message_required_field_tags << #{selph.tag} - else - message_instance._protobuf_message_required_field_tags.delete(#{selph.tag}) - values[#{fully_qualified_name_string(selph)}] = coerce!(value) - end - end - RUBY - else - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def set_field(values, value, ignore_nil_for_repeated, message_instance) - if value.nil? - values.delete(#{fully_qualified_name_string(selph)}) - else - values[#{fully_qualified_name_string(selph)}] = coerce!(value) - end - end - RUBY - end - end - - def self.define_base_field_and_present_p!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def field_and_present?(values) - values[#{fully_qualified_name_string(selph)}].present? - end - RUBY - end - - def self.define_bool_field_and_present_p!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - BOOL_VALUES = [true, false].freeze unless defined?(BOOL_VALUES) - - def field_and_present?(values) - BOOL_VALUES.include?(values[#{fully_qualified_name_string(selph)}]) - end - RUBY - end - - def self.define_base_field_p!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def field?(values) - values.key?(#{fully_qualified_name_string(selph)}) - end - RUBY - end - - def self.define_repeated_field_p!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def field?(values) - values.key?(#{fully_qualified_name_string(selph)}) && values[#{fully_qualified_name_string(selph)}].present? - end - RUBY - end - - def self.define_bool_field_value_from_values!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def value_from_values(values) - values.fetch(#{fully_qualified_name_string(selph)}) { default_value } - end - alias :value_from_values_for_serialization value_from_values - RUBY - end - - def self.define_field_value_from_values!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def value_from_values(values) - values[#{fully_qualified_name_string(selph)}] || default_value - end - alias :value_from_values_for_serialization value_from_values - RUBY - end - - def self.define_map_value_from_values!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def value_from_values(values) - values[#{fully_qualified_name_string(selph)}] ||= ::Protobuf::Field::FieldHash.new(self) - end - - def value_from_values_for_serialization(values) - value = value_from_values(values) - - array = Array.new(value.size) - value.each do |k, v| - array << type_class.new(:key => k, :value => v) - end - - array - end - RUBY - end - - def self.define_repeated_value_from_values!(selph) - selph.instance_eval <<~RUBY, __FILE__, __LINE__ + 1 - def value_from_values(values) - values[#{fully_qualified_name_string(selph)}] ||= ::Protobuf::Field::FieldArray.new(self) - end - alias :value_from_values_for_serialization value_from_values - RUBY - end - - end - end -end diff --git a/lib/protobuf/field/base_field_object_definitions.rb b/lib/protobuf/field/base_field_object_definitions.rb new file mode 100644 index 00000000..93a93226 --- /dev/null +++ b/lib/protobuf/field/base_field_object_definitions.rb @@ -0,0 +1,504 @@ +module Protobuf + module Field + module BaseFieldObjectDefinitions + + class ToHashValueToMessageHashWithStringKey + def initialize(selph) + @selph = selph + @name = selph.name.to_s + end + + def call(values, result) + result[@name] = @selph.value_from_values(values).to_hash_value + end + end + + class BaseToMessageHashWithStringKey + def initialize(selph) + @selph = selph + @name = selph.name.to_s + end + + def call(values, result) + result[@name] = @selph.value_from_values(values) + end + end + + class ToHashValueToMessageHash + def initialize(selph) + @selph = selph + @name = selph.name.to_sym + end + + def call(values, result) + result[@name] = @selph.value_from_values(values).to_hash_value + end + end + + class BaseToMessageHash + def initialize(selph) + @selph = selph + @name = selph.name.to_sym + end + + def call(values, result) + result[@name] = @selph.value_from_values(values) + end + end + + class RepeatedPackedEncodeToStream + def initialize(selph) + @selph = selph + @tag_encoded = selph.tag_encoded + end + + def call(value, stream) + packed_value = value.map { |val| @selph.encode(val) }.join + stream << @tag_encoded << "#{::Protobuf::Field::VarintField.encode(packed_value.size)}#{packed_value}" + end + end + + class BytesEncodeToStream + def initialize(selph) + @selph = selph + @tag_encoded = selph.tag_encoded + end + + def call(value, stream) + value = value.encode if value.is_a?(::Protobuf::Message) + byte_size = ::Protobuf::Field::VarintField.encode(value.bytesize) + + stream << @tag_encoded << byte_size << value + end + end + + class StringEncodeToStream + def initialize(selph) + @selph = selph + @tag_encoded = selph.tag_encoded + end + + def call(value, stream) + new_value = "" + value + if new_value.encoding != ::Protobuf::Field::StringField::ENCODING + new_value.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "") + end + + stream << @tag_encoded << ::Protobuf::Field::VarintField.encode(new_value.bytesize) << new_value + end + end + + class BaseEncodeToStream + def initialize(selph) + @selph = selph + @tag_encoded = selph.tag_encoded + end + + def call(value, stream) + stream << @tag_encoded << @selph.encode(value) + end + end + + class RepeatedNotPackedEncodeToStream + def initialize(selph) + @selph = selph + @tag_encoded = selph.tag_encoded + end + + def call(value, stream) + value.each do |val| + stream << @tag_encoded << @selph.encode(val) + end + end + end + + class BaseSetMethod + def initialize(selph) + @selph = selph + @name = selph.name + end + + def call(message_instance, bytes) + message_instance.set_field(@name, @selph.decode(bytes), true, @selph) + end + end + + class MapSetMethod + def initialize(selph) + @selph = selph + @name = selph.name + end + + def call(message_instance, bytes) + hash = message_instance[@name] + entry = @selph.decode(bytes) + # decoded value could be nil for an + # enum value that is not recognized + hash[entry.key] = entry.value unless entry.value.nil? + hash[entry.key] + end + end + + class RepeatedNotPackedSetMethod + def initialize(selph) + @selph = selph + @name = selph.name + end + + def call(message_instance, bytes) + message_instance[@name] << @selph.decode(bytes) + end + end + + class RepeatedPackedSetMethod + def initialize(selph) + @selph = selph + @name = selph.name + @wire_type = selph.wire_type + end + + def call(message_instance, bytes) + array = message_instance[@name] + stream = ::StringIO.new(bytes) + + if @wire_type == ::Protobuf::WireType::VARINT + array << @selph.decode(Varint.decode(stream)) until stream.eof? + elsif @wire_type == ::Protobuf::WireType::FIXED64 + array << @selph.decode(stream.read(8)) until stream.eof? + elsif @wire_type == ::Protobuf::WireType::FIXED32 + array << @selph.decode(stream.read(4)) until stream.eof? + end + end + end + + class RequiredMapSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, _ignore_nil_for_repeated, message_instance) + unless value.is_a?(Hash) + fail TypeError, <<-TYPE_ERROR + Expected map value + Got '#{value.class}' for map protobuf field #{@selph.name} + TYPE_ERROR + end + + if value.empty? + values.delete(@fully_qualified_name) + message_instance._protobuf_message_unset_required_field_tags << @tag + else + message_instance._protobuf_message_unset_required_field_tags.delete(@tag) + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldHash.new(@selph) + values[@fully_qualified_name].replace(value) + end + end + end + + class MapSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, _ignore_nil_for_repeated, _message_instance) + unless value.is_a?(Hash) + fail TypeError, <<-TYPE_ERROR + Expected map value + Got '#{value.class}' for map protobuf field #{@selph.name} + TYPE_ERROR + end + + if value.empty? + values.delete(@fully_qualified_name) + else + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldHash.new(@selph) + values[@fully_qualified_name].replace(value) + end + end + end + + class RequiredRepeatedSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, ignore_nil_for_repeated, message_instance) + if value.nil? && ignore_nil_for_repeated + ::Protobuf.deprecator.deprecation_warning("['#{@fully_qualified_name}']=nil", "use an empty array instead of nil") + return + end + + unless value.is_a?(Array) + fail TypeError, <<-TYPE_ERROR + Expected repeated value of type '#{@selph.type_class}' + Got '#{value.class}' for repeated protobuf field #{@selph.name} + TYPE_ERROR + end + + value = value.compact + + if value.empty? + values.delete(@fully_qualified_name) + message_instance._protobuf_message_unset_required_field_tags << @tag + else + message_instance._protobuf_message_unset_required_field_tags.delete(@tag) + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldArray.new(@selph) + values[@fully_qualified_name].replace(value) + end + end + end + + class RepeatedSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, ignore_nil_for_repeated, _message_instance) + if value.nil? && ignore_nil_for_repeated + ::Protobuf.deprecator.deprecation_warning("['#{@fully_qualified_name}']=nil", "use an empty array instead of nil") + return + end + + unless value.is_a?(Array) + fail TypeError, <<-TYPE_ERROR + Expected repeated value of type '#{@selph.type_class}' + Got '#{value.class}' for repeated protobuf field #{@selph.name} + TYPE_ERROR + end + + value = value.compact + + if value.empty? + values.delete(@fully_qualified_name) + else + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldArray.new(@selph) + values[@fully_qualified_name].replace(value) + end + end + end + + class RequiredStringSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, _ignore_nil_for_repeated, message_instance) + if value + message_instance._protobuf_message_unset_required_field_tags.delete(@tag) + values[@fully_qualified_name] = if value.is_a?(String) + value + else + @selph.coerce!(value) + end + else + values.delete(@fully_qualified_name) + message_instance._protobuf_message_unset_required_field_tags << @tag + end + end + end + + class StringSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, _ignore_nil_for_repeated, _message_instance) + if value + values[@fully_qualified_name] = if value.is_a?(String) + value + else + @selph.coerce!(value) + end + else + values.delete(@fully_qualified_name) + end + end + end + + class RequiredBaseSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, _ignore_nil_for_repeated, message_instance) + if value.nil? + values.delete(@fully_qualified_name) + message_instance._protobuf_message_unset_required_field_tags << @tag + else + message_instance._protobuf_message_unset_required_field_tags.delete(@tag) + values[@fully_qualified_name] = @selph.coerce!(value) + end + end + end + + class BaseSetField + def initialize(selph) + @selph = selph + @tag = selph.tag + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values, value, _ignore_nil_for_repeated, _message_instance) + if value.nil? + values.delete(@fully_qualified_name) + else + values[@fully_qualified_name] = @selph.coerce!(value) + end + end + end + + class BaseFieldAndPresentPredicate + def initialize(selph) + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values[@fully_qualified_name].present? + end + end + + class BoolFieldAndPresentPredicate + BOOL_VALUES = [true, false].freeze + + def initialize(selph) + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + BOOL_VALUES.include?(values[@fully_qualified_name]) + end + end + + class BaseFieldPredicate + def initialize(selph) + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values.key?(@fully_qualified_name) + end + end + + class RepeatedFieldPredicate + def initialize(selph) + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values.key?(@fully_qualified_name) && + values[@fully_qualified_name].present? + end + end + + class BoolFieldValueFromValues + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values.fetch(@fully_qualified_name) { @selph.default_value } + end + end + + class BoolFieldValueFromValuesForSerialization + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values.fetch(@fully_qualified_name) { @selph.default_value } + end + end + + class BaseFieldValueFromValues + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values[@fully_qualified_name] || @selph.default_value + end + end + + class BaseFieldValueFromValuesForSerialization + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values[@fully_qualified_name] || @selph.default_value + end + end + + class MapValueFromValues + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldHash.new(@selph) + end + end + + class MapValueFromValuesForSerialization + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + @type_class = selph.type_class + end + + def call(values) + value = values[@fully_qualified_name] ||= ::Protobuf::Field::FieldHash.new(@selph) + + array = [] + value.each do |k, v| + array << @type_class.new(:key => k, :value => v) + end + + array + end + end + + class RepeatedFieldValueFromValues + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldArray.new(@selph) + end + end + + class RepeatedFieldValueFromValuesForSerialization + def initialize(selph) + @selph = selph + @fully_qualified_name = selph.fully_qualified_name + end + + def call(values) + values[@fully_qualified_name] ||= ::Protobuf::Field::FieldArray.new(@selph) + end + end + end + end +end diff --git a/lib/protobuf/field/bool_field.rb b/lib/protobuf/field/bool_field.rb index b325acfd..bba089f4 100644 --- a/lib/protobuf/field/bool_field.rb +++ b/lib/protobuf/field/bool_field.rb @@ -3,7 +3,7 @@ module Protobuf module Field class BoolField < VarintField - ONE = 1.freeze + ONE = 1 FALSE_ENCODE = [0].pack('C') FALSE_STRING = "false".freeze FALSE_VALUES = [false, FALSE_STRING].freeze diff --git a/lib/protobuf/field/enum_field.rb b/lib/protobuf/field/enum_field.rb index 9a29b42a..6993faff 100644 --- a/lib/protobuf/field/enum_field.rb +++ b/lib/protobuf/field/enum_field.rb @@ -15,27 +15,14 @@ def self.default ## # Public Instance Methods # - if defined?(::ProtobufJavaHelpers) - include ::ProtobufJavaHelpers::Varinter - include ::ProtobufJavaHelpers::IntegerProtobufField - - def encode(value) - to_varint_64(value.to_i) # Calling `to_i` because it is a delegator and the java side doesn't follow - end - - def decode(value) - decode_varint_64(value) - end - else - def encode(value) - # original Google's library uses 64bits integer for negative value - ::Protobuf::Field::VarintField.encode(value & 0xffff_ffff_ffff_ffff) - end + def encode(value) + # original Google's library uses 64bits integer for negative value + ::Protobuf::Field::VarintField.encode(value.to_i & 0xffff_ffff_ffff_ffff) + end - def decode(value) - value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero? - value if acceptable?(value) - end + def decode(value) + value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero? + value if acceptable?(value) end def acceptable?(val) diff --git a/lib/protobuf/field/int32_field.rb b/lib/protobuf/field/int32_field.rb index b8f3ab88..4a7865f9 100644 --- a/lib/protobuf/field/int32_field.rb +++ b/lib/protobuf/field/int32_field.rb @@ -7,28 +7,15 @@ class Int32Field < IntegerField ## # Class Methods # - if defined?(::ProtobufJavaHelpers) - include ::ProtobufJavaHelpers::Varinter - include ::ProtobufJavaHelpers::IntegerProtobufField - include ::ProtobufJavaHelpers::Int32ProtobufField - extend ::ProtobufJavaHelpers::Int32ProtobufField - def encode(value) - to_varint_64(value) - end - - def decode(value) - decode_varint_64(value) - end - else - def self.max - INT32_MAX - end + def self.max + INT32_MAX + end - def self.min - INT32_MIN - end + def self.min + INT32_MIN end + end end end diff --git a/lib/protobuf/field/int64_field.rb b/lib/protobuf/field/int64_field.rb index 493f6ab2..3b338894 100644 --- a/lib/protobuf/field/int64_field.rb +++ b/lib/protobuf/field/int64_field.rb @@ -7,26 +7,26 @@ class Int64Field < IntegerField ## # Class Methods # - if defined?(::ProtobufJavaHelpers) - include ::ProtobufJavaHelpers::Varinter - include ::ProtobufJavaHelpers::IntegerProtobufField - include ::ProtobufJavaHelpers::Int64ProtobufField - def encode(value) - to_varint_64(value) - end + def self.max + INT64_MAX + end - def decode(value) - decode_varint_64(value) - end - else - def self.max - INT64_MAX - end + def self.min + INT64_MIN + end - def self.min - INT64_MIN + ## + # Instance Methods + # + def acceptable?(val) + if val.is_a?(Integer) || val.is_a?(Numeric) + val >= INT64_MIN && val <= INT64_MAX + else + Integer(val, 10) >= INT64_MIN && Integer(val, 10) <= INT64_MAX end + rescue + return false end end diff --git a/lib/protobuf/field/integer_field.rb b/lib/protobuf/field/integer_field.rb index 3b66ec2c..5eb3b064 100644 --- a/lib/protobuf/field/integer_field.rb +++ b/lib/protobuf/field/integer_field.rb @@ -7,28 +7,6 @@ class IntegerField < VarintField ## # Public Instance Methods # - def acceptable?(val) - int_val = if val.is_a?(Integer) - return true if val >= 0 && val < INT32_MAX # return quickly for smallest integer size, hot code path - val - elsif val.is_a?(Numeric) - val.to_i - else - Integer(val, 10) - end - - int_val >= self.class.min && int_val <= self.class.max - rescue - false - end - - def coerce!(val) - fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'" unless acceptable?(val) - return val.to_i if val.is_a?(Numeric) - Integer(val, 10) - rescue ArgumentError - fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'" - end def decode(value) value -= 0x1_0000_0000_0000_0000 if (value & 0x8000_0000_0000_0000).nonzero? diff --git a/lib/protobuf/field/message_field.rb b/lib/protobuf/field/message_field.rb index 304a201f..34f45fd2 100644 --- a/lib/protobuf/field/message_field.rb +++ b/lib/protobuf/field/message_field.rb @@ -18,7 +18,7 @@ def decode(bytes) def encode(value) bytes = value.encode - result = ::Protobuf::Field::VarintField.encode(bytes.size) + result = ::Protobuf::Field::VarintField.encode(bytes.bytesize) result << bytes end diff --git a/lib/protobuf/field/string_field.rb b/lib/protobuf/field/string_field.rb index 055ace43..6c9c278f 100644 --- a/lib/protobuf/field/string_field.rb +++ b/lib/protobuf/field/string_field.rb @@ -21,8 +21,10 @@ def acceptable?(val) def coerce!(value) if value.nil? nil - else + elsif acceptable?(value) value.to_s + else + fail TypeError, "Unacceptable value #{value} for field #{name} of type #{type_class}" end end diff --git a/lib/protobuf/field/uint32_field.rb b/lib/protobuf/field/uint32_field.rb index 6d512c8e..50fa8fef 100644 --- a/lib/protobuf/field/uint32_field.rb +++ b/lib/protobuf/field/uint32_field.rb @@ -7,18 +7,15 @@ class Uint32Field < VarintField ## # Class Methods # - if defined?(::ProtobufJavaHelpers) - include ::ProtobufJavaHelpers::Uint32ProtobufField - extend ::ProtobufJavaHelpers::Uint32ProtobufField - else - def self.max - UINT32_MAX - end - def self.min - 0 - end + def self.max + UINT32_MAX end + + def self.min + 0 + end + end end end diff --git a/lib/protobuf/field/uint64_field.rb b/lib/protobuf/field/uint64_field.rb index 0ef93bdf..8a060f14 100644 --- a/lib/protobuf/field/uint64_field.rb +++ b/lib/protobuf/field/uint64_field.rb @@ -7,18 +7,15 @@ class Uint64Field < VarintField ## # Class Methods # - if defined?(::ProtobufJavaHelpers) - include ::ProtobufJavaHelpers::Uint64ProtobufField - extend ::ProtobufJavaHelpers::Uint64ProtobufField - else - def self.max - UINT64_MAX - end - def self.min - 0 - end + def self.max + UINT64_MAX end + + def self.min + 0 + end + end end end diff --git a/lib/protobuf/field/varint_field.rb b/lib/protobuf/field/varint_field.rb index 70879c03..0a183f0f 100644 --- a/lib/protobuf/field/varint_field.rb +++ b/lib/protobuf/field/varint_field.rb @@ -1,5 +1,4 @@ require 'protobuf/field/base_field' -require 'protobuf/field/varint_field_encoder_pure' module Protobuf module Field @@ -8,8 +7,6 @@ class VarintField < BaseField ## # Constants # - - CACHE_LIMIT = 2048 INT32_MAX = 2**31 - 1 INT32_MIN = -2**31 INT64_MAX = 2**63 - 1 @@ -25,27 +22,44 @@ def self.default 0 end - if defined?(::ProtobufJavaHelpers) - include ::ProtobufJavaHelpers::VarintProtobufField - extend ::ProtobufJavaHelpers::VarintProtobufField - extend ::ProtobufJavaHelpers::Varinter - - def self.encode(value) - to_varint(value) - end - else - include ::Protobuf::Field::VarintFieldEncoderPure - extend ::Protobuf::Field::VarintFieldEncoderPure::ClassMethods - - # Load the cache of VarInts on load of file - (0..CACHE_LIMIT).each do |cached_value| - cached_varint(cached_value) - end + def self.encode(value) + ::Protobuf::Varint.encode(value) end ## # Public Instance Methods # + def acceptable?(val) + int_val = if val.is_a?(Integer) + return true if val >= 0 && val < INT32_MAX # return quickly for smallest integer size, hot code path + val + elsif val.is_a?(Numeric) + val.to_i + else + Integer(val, 10) + end + + int_val >= self.class.min && int_val <= self.class.max + rescue + false + end + + def coerce!(val) + if val.is_a?(Integer) && val >= 0 && val <= INT32_MAX + val + else + fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'" unless acceptable?(val) + + if val.is_a?(Integer) || val.is_a?(Numeric) + val.to_i + else + Integer(val, 10) + end + end + rescue ArgumentError + fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'" + end + def decode(value) value end diff --git a/lib/protobuf/field/varint_field_encoder_pure.rb b/lib/protobuf/field/varint_field_encoder_pure.rb deleted file mode 100644 index 2dba22c5..00000000 --- a/lib/protobuf/field/varint_field_encoder_pure.rb +++ /dev/null @@ -1,48 +0,0 @@ -module Protobuf - module Field - module VarintFieldEncoderPure - module ClassMethods - # Because all tags and enums are calculated as VarInt it is "most common" to have - # values < CACHE_LIMIT (low numbers) which is defaulting to 1024 - def cached_varint(value) - @_varint_cache ||= {} - (@_varint_cache[value] ||= encode(value, false)).dup - end - - def encode(value, use_cache = true) - return cached_varint(value) if use_cache && value >= 0 && value <= CACHE_LIMIT - - bytes = [] - until value < 128 - bytes << (0x80 | (value & 0x7f)) - value >>= 7 - end - (bytes << value).pack('C*') - end - end - - def acceptable?(val) - int_val = if val.is_a?(Integer) - return true if val >= 0 && val < INT32_MAX # return quickly for smallest integer size, hot code path - val - elsif val.is_a?(Numeric) - val.to_i - else - Integer(val, 10) - end - - int_val >= self.class.min && int_val <= self.class.max - rescue - false - end - - def coerce!(val) - fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'" unless acceptable?(val) - return val.to_i if val.is_a?(Numeric) - Integer(val, 10) - rescue ArgumentError - fail TypeError, "Expected value of type '#{type_class}' for field #{name}, but got '#{val.class}'" - end - end - end -end diff --git a/lib/protobuf/generators/enum_generator.rb b/lib/protobuf/generators/enum_generator.rb index 1088e3ed..b8522171 100644 --- a/lib/protobuf/generators/enum_generator.rb +++ b/lib/protobuf/generators/enum_generator.rb @@ -29,6 +29,7 @@ def compile def build_value(enum_value_descriptor) name = enum_value_descriptor.name + name.capitalize! if ENV.key?('PB_CAPITALIZE_ENUMS') name.upcase! if ENV.key?('PB_UPCASE_ENUMS') number = enum_value_descriptor.number "define :#{name}, #{number}" diff --git a/lib/protobuf/generators/field_generator.rb b/lib/protobuf/generators/field_generator.rb index 68652fcc..1642308f 100644 --- a/lib/protobuf/generators/field_generator.rb +++ b/lib/protobuf/generators/field_generator.rb @@ -140,6 +140,8 @@ def enum_default_value optionally_upcased_default = if ENV.key?('PB_UPCASE_ENUMS') verbatim_default_value.upcase + elsif ENV.key?('PB_CAPITALIZE_ENUMS') + verbatim_default_value.capitalize else verbatim_default_value end diff --git a/lib/protobuf/message.rb b/lib/protobuf/message.rb index c61087db..a13c0d19 100644 --- a/lib/protobuf/message.rb +++ b/lib/protobuf/message.rb @@ -1,15 +1,5 @@ require 'protobuf/message/fields' require 'protobuf/message/serialization' - -# Under MRI, this optimizes proto decoding by around 15% in tests. -# When unavailable, we fall to pure Ruby. -# rubocop:disable Lint/HandleExceptions -begin - require 'varint/varint' -rescue LoadError -end -# rubocop:enable Lint/HandleExceptions - require 'protobuf/varint' module Protobuf @@ -23,20 +13,6 @@ class Message include ::Protobuf::Message::Serialization ::Protobuf::Optionable.inject(self) { ::Google::Protobuf::MessageOptions } - def self.inherited(subclass) - subclass.const_set("PROTOBUF_MESSAGE_REQUIRED_FIELD_TAGS", subclass.required_field_tags) - subclass.const_set("PROTOBUF_MESSAGE_GET_FIELD", subclass.field_store) - subclass.class_eval <<~RUBY, __FILE__, __LINE__ - def _protobuf_message_field - PROTOBUF_MESSAGE_GET_FIELD - end - - def _protobuf_message_required_field_tags - @_protobuf_message_required_field_tags ||= PROTOBUF_MESSAGE_REQUIRED_FIELD_TAGS.dup - end - RUBY - end - ## # Class Methods # @@ -94,7 +70,7 @@ def each_field end def each_field_for_serialization - _protobuf_message_required_field_tags.each do |tag| + _protobuf_message_unset_required_field_tags.each do |tag| fail ::Protobuf::SerializationError, "Required field #{self.class.name}##{_protobuf_message_field[tag].name} does not have a value." end @@ -146,6 +122,17 @@ def to_hash result end + def to_hash_with_string_keys + result = {} + + @values.each_key do |field_name| + field = _protobuf_message_field[field_name] + field.to_message_hash_with_string_key(@values, result) + end + + result + end + def to_json(options = {}) to_json_hash.to_json(options) end @@ -200,7 +187,9 @@ def []=(name, value) end def set_field(name, value, ignore_nil_for_repeated, field = nil) - if (field || field = _protobuf_message_field[name]) + field ||= _protobuf_message_field[name] + + if field field.set_field(@values, value, ignore_nil_for_repeated, self) else fail(::Protobuf::FieldNotDefinedError, name) unless ::Protobuf.ignore_unknown_fields? diff --git a/lib/protobuf/message/fields.rb b/lib/protobuf/message/fields.rb index 268851a8..d07e1eff 100644 --- a/lib/protobuf/message/fields.rb +++ b/lib/protobuf/message/fields.rb @@ -20,6 +20,17 @@ def self.extended(other) module ClassMethods def inherited(subclass) inherit_fields!(subclass) + subclass.const_set("PROTOBUF_MESSAGE_REQUIRED_FIELD_TAGS", subclass.required_field_tags) + subclass.const_set("PROTOBUF_MESSAGE_GET_FIELD", subclass.field_store) + subclass.class_eval <<-RUBY, __FILE__, __LINE__ + def _protobuf_message_field + PROTOBUF_MESSAGE_GET_FIELD + end + + def _protobuf_message_unset_required_field_tags + @_protobuf_message_unset_required_field_tags ||= PROTOBUF_MESSAGE_REQUIRED_FIELD_TAGS.dup + end + RUBY end ## diff --git a/lib/protobuf/rpc/buffer.rb b/lib/protobuf/rpc/buffer.rb index 53f163f2..afadec42 100644 --- a/lib/protobuf/rpc/buffer.rb +++ b/lib/protobuf/rpc/buffer.rb @@ -44,7 +44,7 @@ def <<(data) end end - def set_data(data) # rubocop:disable Style/AccessorMethodName + def set_data(data) # rubocop:disable Naming/AccessorMethodName @data = data.to_s @size = @data.size end @@ -61,7 +61,7 @@ def flushed? @flush end - def get_data_size # rubocop:disable Style/AccessorMethodName + def get_data_size # rubocop:disable Naming/AccessorMethodName if @size == 0 || @data.match(SIZE_REGEX) sliced_size = @data.slice!(SIZE_REGEX) @size = sliced_size.delete('-').to_i unless sliced_size.nil? diff --git a/lib/protobuf/rpc/connectors/base.rb b/lib/protobuf/rpc/connectors/base.rb index 2e9c76ba..969d777c 100644 --- a/lib/protobuf/rpc/connectors/base.rb +++ b/lib/protobuf/rpc/connectors/base.rb @@ -63,8 +63,9 @@ def data_callback(data) # @param [String] message The error message def failure(code, message) @error = ClientError.new - @error.code = ::Protobuf::Socketrpc::ErrorReason.fetch(code) + @stats.status = @error.code = ::Protobuf::Socketrpc::ErrorReason.fetch(code) @error.message = message + logger.debug { sign_message("Server failed request (invoking on_failure): #{@error.inspect}") } @failure_cb.call(@error) unless @failure_cb.nil? @@ -139,12 +140,7 @@ def ping_port_enabled? def request_bytes validate_request_type! - fields = { :service_name => @options[:service].name, - :method_name => @options[:method].to_s, - :request_proto => @options[:request], - :caller => request_caller } - - return ::Protobuf::Socketrpc::Request.encode(fields) + return ::Protobuf::Socketrpc::Request.encode(request_fields) rescue => e failure(:INVALID_REQUEST_PROTO, "Could not set request proto: #{e.message}") end @@ -153,6 +149,13 @@ def request_caller @options[:client_host] || ::Protobuf.client_host end + def request_fields + { :service_name => @options[:service].name, + :method_name => @options[:method].to_s, + :request_proto => @options[:request], + :caller => request_caller } + end + def send_request fail 'If you inherit a Connector from Base you must implement send_request' end diff --git a/lib/protobuf/rpc/env.rb b/lib/protobuf/rpc/env.rb index cf6aea60..3d7c166e 100644 --- a/lib/protobuf/rpc/env.rb +++ b/lib/protobuf/rpc/env.rb @@ -41,6 +41,7 @@ def self.hash_accessor(*names) #:nodoc: :method_name, :request, :request_type, + :request_wrapper, :response, :response_type, :rpc_method, diff --git a/lib/protobuf/rpc/error.rb b/lib/protobuf/rpc/error.rb index 343d1889..584a0425 100644 --- a/lib/protobuf/rpc/error.rb +++ b/lib/protobuf/rpc/error.rb @@ -13,12 +13,12 @@ def initialize(message = 'An unknown RpcError occurred', error_type = 'RPC_ERROR super message end - def encode - to_response.encode + def encode(args = {}) + to_response(args).encode end - def to_response - ::Protobuf::Socketrpc::Response.new(:error => message, :error_reason => error_type) + def to_response(args = {}) + ::Protobuf::Socketrpc::Response.new({ :error => message, :error_reason => error_type }.merge(args)) end end end diff --git a/lib/protobuf/rpc/middleware/exception_handler.rb b/lib/protobuf/rpc/middleware/exception_handler.rb index 9592c049..376e0375 100644 --- a/lib/protobuf/rpc/middleware/exception_handler.rb +++ b/lib/protobuf/rpc/middleware/exception_handler.rb @@ -22,7 +22,7 @@ def _call(env) # Rescue exceptions, re-wrap them as generic Protobuf errors, # and encode them env.response = wrap_exception(exception) - env.encoded_response = env.response.encode + env.encoded_response = wrap_and_encode_with_server(env.response, env) env end @@ -34,6 +34,17 @@ def wrap_exception(exception) exception = RpcFailed.new(exception.message) unless exception.is_a?(PbError) exception end + + # If the response is a PbError, it won't have the server merged into the response proto. + # We should add it here since exception handler is always at the bottom of the middleware + # stack. Without this, the server hostname in the client rpc log will not be set. + def wrap_and_encode_with_server(response, env) + if response.is_a?(PbError) + response.encode(:server => env.server) + else + response.encode + end + end end end end diff --git a/lib/protobuf/rpc/middleware/request_decoder.rb b/lib/protobuf/rpc/middleware/request_decoder.rb index 45469883..c4efe823 100644 --- a/lib/protobuf/rpc/middleware/request_decoder.rb +++ b/lib/protobuf/rpc/middleware/request_decoder.rb @@ -21,6 +21,7 @@ def _call(env) env.service_name = service_name env.method_name = method_name env.request = request + env.request_wrapper = request_wrapper env.client_host = request_wrapper.caller env.rpc_service = service diff --git a/lib/protobuf/rpc/rpc.pb.rb b/lib/protobuf/rpc/rpc.pb.rb index eaea971f..0d2937a7 100644 --- a/lib/protobuf/rpc/rpc.pb.rb +++ b/lib/protobuf/rpc/rpc.pb.rb @@ -31,6 +31,7 @@ class ErrorReason < ::Protobuf::Enum # class Request < ::Protobuf::Message; end class Response < ::Protobuf::Message; end + class Header < ::Protobuf::Message; end ## @@ -41,6 +42,7 @@ class Request required :string, :method_name, 2 optional :bytes, :request_proto, 3 optional :string, :caller, 4 + repeated ::Protobuf::Socketrpc::Header, :headers, 5 end class Response @@ -51,6 +53,11 @@ class Response optional :string, :server, 5 end + class Header + required :string, :key, 1 + optional :string, :value, 2 + end + end end diff --git a/lib/protobuf/rpc/stat.rb b/lib/protobuf/rpc/stat.rb index 18d0eff6..841181a3 100644 --- a/lib/protobuf/rpc/stat.rb +++ b/lib/protobuf/rpc/stat.rb @@ -1,16 +1,30 @@ require 'date' require 'time' require 'protobuf/logging' +require 'protobuf/rpc/rpc.pb' module Protobuf module Rpc class Stat attr_accessor :mode, :start_time, :end_time, :request_size, :dispatcher - attr_accessor :response_size, :client, :service, :method_name + attr_accessor :response_size, :client, :service, :method_name, :status attr_reader :server MODES = [:SERVER, :CLIENT].freeze + ERROR_TRANSLATIONS = { + ::Protobuf::Socketrpc::ErrorReason::BAD_REQUEST_DATA => "BAD_REQUEST_DATA", + ::Protobuf::Socketrpc::ErrorReason::BAD_REQUEST_PROTO => "BAD_REQUEST_PROTO", + ::Protobuf::Socketrpc::ErrorReason::SERVICE_NOT_FOUND => "SERVICE_NOT_FOUND", + ::Protobuf::Socketrpc::ErrorReason::METHOD_NOT_FOUND => "METHOD_NOT_FOUND", + ::Protobuf::Socketrpc::ErrorReason::RPC_ERROR => "RPC_ERROR", + ::Protobuf::Socketrpc::ErrorReason::RPC_FAILED => "RPC_FAILED", + ::Protobuf::Socketrpc::ErrorReason::INVALID_REQUEST_PROTO => "INVALID_REQUEST_PROTO", + ::Protobuf::Socketrpc::ErrorReason::BAD_RESPONSE_PROTO => "BAD_RESPONSE_PROTO", + ::Protobuf::Socketrpc::ErrorReason::UNKNOWN_HOST => "UNKNOWN_HOST", + ::Protobuf::Socketrpc::ErrorReason::IO_ERROR => "IO_ERROR", + }.freeze + def initialize(mode = :SERVER) @mode = mode @request_size = 0 @@ -78,6 +92,12 @@ def client? @mode == :CLIENT end + def status_string + return "OK" if status.nil? + + ERROR_TRANSLATIONS.fetch(status, "UNKNOWN_ERROR") + end + def to_s [ server? ? "[SRV]" : "[CLT]", @@ -86,6 +106,7 @@ def to_s rpc, sizes, elapsed_time, + status_string, @end_time.try(:iso8601), ].compact.join(' - ') end @@ -93,7 +114,6 @@ def to_s def trace_id ::Thread.current.object_id.to_s(16) end - end end end diff --git a/lib/protobuf/varint.rb b/lib/protobuf/varint.rb index 1012d658..be70cca3 100644 --- a/lib/protobuf/varint.rb +++ b/lib/protobuf/varint.rb @@ -2,12 +2,17 @@ module Protobuf class Varint if defined?(::Varint) extend ::Varint - elsif defined?(::ProtobufJavaHelpers) - extend ::ProtobufJavaHelpers::Varinter - def self.decode(stream) - read_varint(stream) + def self.encode(value) + bytes = [] + until value < 128 + bytes << (0x80 | (value & 0x7f)) + value >>= 7 + end + (bytes << value).pack('C*') end + elsif defined?(::ProtobufJavaHelpers) + extend ::ProtobufJavaHelpers::EncodeDecode else extend VarintPure end diff --git a/lib/protobuf/varint_pure.rb b/lib/protobuf/varint_pure.rb index eeffbecc..6013241c 100644 --- a/lib/protobuf/varint_pure.rb +++ b/lib/protobuf/varint_pure.rb @@ -1,5 +1,12 @@ module Protobuf module VarintPure + CACHE_LIMIT = 2048 + + def cached_varint(value) + @_varint_cache ||= {} + (@_varint_cache[value] ||= encode(value, false)).dup + end + def decode(stream) value = index = 0 begin @@ -9,5 +16,16 @@ def decode(stream) end while (byte & 0x80).nonzero? value end + + def encode(value, use_cache = true) + return cached_varint(value) if use_cache && value >= 0 && value <= CACHE_LIMIT + + bytes = [] + until value < 128 + bytes << (0x80 | (value & 0x7f)) + value >>= 7 + end + (bytes << value).pack('C*') + end end end diff --git a/lib/protobuf/version.rb b/lib/protobuf/version.rb index 9a70aa66..0d7d5f38 100644 --- a/lib/protobuf/version.rb +++ b/lib/protobuf/version.rb @@ -1,3 +1,3 @@ module Protobuf - VERSION = '3.8.5' # rubocop:disable Style/MutableConstant + VERSION = '3.10.9' # rubocop:disable Style/MutableConstant end diff --git a/profile.html b/profile.html index 301a2adf..6ac4b900 100644 --- a/profile.html +++ b/profile.html @@ -52,7 +52,7 @@

Profile Report: main

-

Total time: 63.22

+

Total time: 123.51

@@ -67,3893 +67,3542 @@

Total time: 63.22

- + - + - + - + - + - + - + - + - + - - - - + + + + - + - - - - - + + + + + - + - + - + - + - - - - - + + + + + - + - - - + + + - - - - - - - - + + + + + + + + - + - - - - + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + + - - + - - + + + - + - - - - - + + + + + - - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - + + - - - + + - + - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + - - - - + + + + - + - - - - + + + + - + - - + + - - + + - + - - + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - - - - - - + - - - - + + + + - + - - - - + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - + + + + - + - - + + - + - + + + + + + + + + + - + - + - + - + - + - + - - - - - - - - - - - + - - - - - + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + - + - - - - - + + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - + - - - - - - - - - - - - - - + + + + + - + - - - - - + + + + + - + - + - + - + - + - + - + - + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - + - - - - + + + + - + - - - - + + + + - + - - - - + + + + - - - - + + + + - + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - + + - + - + - - + + - - + + - + - - + + - - + + - + - - + + - - + + - + - - + + - - + + - + - - - + + + - - - - + + + + - + - - - - + + + + - + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - + - - - - - + + + + + - + - - + + - - + + - + - - - - - + + + + + - + + + + + + + + + + - - - - - + + + + + + - - - - - + + + + + - + + + + + + + + + + - - - - - + + + + + + - - - - - + + + + + - + - - - - - - - - - - - - - - + + + + + - + - - - - - + + + + + - + + - - - - - + + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + + - - - - - + + + + + - + - - - - - + + + + + - + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - - - + + + + + - + - - + + - - + + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - - - + + + + + - + - - + + - - + + - - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - - - - - - - - - - + + + + + - + + - - - - - + + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - - + - - + + - - + + + - - - - - + + + + + - + + + + + + + + + + - - - - - + + + + + - + - - + + - - + + - + - - + + - - + + + - - - - - + + + + + - - - - - - + + + + + + + + + + + + + + + - + - - - - - + + + + + - - - - - - + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - - - + + + + + - - + - - - - - + + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - + - - + + - - + + - - + - - - - - + + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - + - - + + - - + + - + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - + + - + + - - - + + - + + - - - + + - - - + + + + - - - + + - + + - - - - - + + + + + - - - - - - - - + + + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + - - + + - - + + - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - + - - - - - + + + + + - + + - - - - - + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + - - + + - - - - + + + + - + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + - + - - + - - + + + - - + - - - - - - - - - - - - - - + + + + + - + - - - - - + + + + + - + + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + + + + - + - - + + + + + + + + + + - - + + + - + + - - - - + + + - - + + + - - - - + + + - + - - - - - - - - - - - + + - - + + - + - - - - - + + + + + - - - - - - + + + + + + - + + - - - - - + + + + + - + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + + + + - + + - - - - - + + + + + + + + + + + + + + - + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + + + + + + + + + + - + - + + - - - + + - + - - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + + - + - - + + - - + + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - - - - - - - - - + + - - - + + - + - - - - - + + + + + - + - + + - - - + + - - - + + - - + + + + + + + + + + + + - - - - - + + + + + - + + + - - - - + + - + - - + + - - + + - - - - - + + + + + - - - - - - + + + + + + - - + - - + + - - + + + - - + + - + - - + + - - + + - - - - - + + + + + - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + - + - - + + - - + + - - - - - + + + + + - - - - + + + + + + + + + + + + + - - + + - + - - - - - + + + + + - - - - - - - - - - - - - - - + + + + + + - + - - + + - - + + - - + - - + + + - - + - - + + + - + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - + + + + + - + - + + - - - + + - + - - - - - + + + + + - - - - - - - - - - - + + - - + + - + - - + + - + - - + + - + - + - + - + - + - + - + - + - + + + + + + + + + + - + - + - + - + + - - - + + - + + - - - + + - + + - + + - - - + + + + + + + + + + + - + + - - - - + + + + - - - - + + + - + - + + - - - + + - + - - - - - + + + + + - - - - - - - - - - - + + - - + + - - - - - + + + + + - - - - - + + + + + - + - + + - - - + + - - - - - - - - - - + + - - - + + - + - - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + + - + - - - - - + + + + + - - - - - + + + + + - + - + - - - + + + - + - - - - - + + + + + - - - - - + + + + + - + - + + - - - + + - + - + - - - + + + - + - - - + + + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - + - + - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - - - - - - - - - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - + + + + + - - + - - - - - - - - - - - + - - + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + - - + + + - - + - - + + + - - + - - - - - - - - - - - + - - + + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - + - + - + - - - + + + - + - - + - - + + + - - + - - + + + - - + - - - - - - - - - - + - - - - - - - - - - - - + + + - + - - + - - + + + - - + - - + + + - - + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + + + - + - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - + + - - - - - + + + + + + + + + + + + + + + - - - - - - + + + + + - + - - + + - - + + - - + + - - + + + + + + + + + + + + - - - - - - + + + + + - + - - - - + + + + - + - - + - - + + + - - + - - + + + - + + + + + + + + + + - + + - - - + + - + + - - - + + - + - - + + - - + + - - + + - - + + - - + - - + + + - - + + + + + + + + + + - - + + + - + - - + + - - + + - - - - - + + + + + - - + + - - - - - - + + + + + - + - + - + - + - + - + - + - + - + - - - + + + - + - + + - - - + + - - - - - - - - - - + + - - - + + - + - - - + + + - + - - - + + + - + - + - - - + + + - + - - - - - + + + + + + - - - - + + + - + + - + + - - - + + + + + + + + + + + + + + + + + + + + + - + + - - - + + - + + - - - + + - + + - + + - - - + + + + + + + + + + + - + - - + - - + + + - - + - - + + + - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - + + + - + - - - + + + - + - + - - - + + + - + - + - - - + + + - + - - - + + + - + - - - - - - - - - - - - + - - + + + - + - - - + + + - + - - - + + + - + - + - - - + + + - + - + - - - + + + - + + + + + + + + + + + - - + + - - - - + + + + + - - - + + + - + - - + - - + + + - - + - - + + + - + + + + + + + + + + - + - - - + + + - + - - - + + + - + - + - - - + + + - + - - - + + + - + - - - + + + - - + - - - - - - - - - - - + - - + + + - - - - - - - - - - - - + - - + + + + + + + + + + + - - + + + - + @@ -3961,7 +3610,7 @@

Total time: 63.22

- + @@ -3970,1238 +3619,1263 @@

Total time: 63.22

- + - - + + + + + + + + + + - - + + + - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + - - + - - - - + + + + - - - - + + + + - - - - - + + + + + + + + + - - - - - - + + + + + + + + - - - - + + + - - - + + + + + + - - - - - - - - - + + + + + + + + - - + - + + - + + + + + + + + + + + - - - - + + + + + - - + + + - + + + + + - - - - - + + - - - + - - - + - - - + + + + + + + + - + + + + + + + - - + + + + + + + - + + - - + - - + + - - - - - - - - - - - - - - + - - + + + - - - + - - - - - - - - + + + + - - - - - - + - + + + + + + + + + + - - - - - - - + + + + + + - - - - - + + + + + + - - - + + + + + + - - - + + + + + + + - - + + + + + + - - - - - + + + - - + + - - + + + + + + + + + + - - - - - - + + + + - + + + - + - - - - - + - - - - - + + - + + + + + + + - - + + + + + + + - - - - - - - + + + + + + + + - - + - - + - + + - - - - - - - + + + + + + - - + - - + + + + + + + - - - + + - + + + + + + + + + + + + - + + + + + + + + - + - + - - - - - + + + + - - - - + + + - - - - - - - - + - - - - + + - + - - + + + + + - - - - + + + - - - + + + + - - - - - + + + + - + + - - + + + + + - + - - - - - + - - - - - - + + + + - + + - + + + + - - - - - - + + + - - + + + + - + + + + + + + + - - - + + - + - - - - + + + + + - + - - - - + + + + + + + + + + + + + - - - + + + + + - + + + - - - - - + - - - - - + - + + - - - + + + + + - - - - - - - - - - + + + - - - - - - - - - - + + + - - - - + + + + + + - - + + + - - - - - - + + - + - + - - - + + + + + + + + - - + + + + - - - - - - + + + - - + - - - + + - - + + + - + - - - + - + + + + - - - - - + - - - + + + + + + + + + + + + - + + - + - - + + + + - - - - + - - - + - + + + + - - - - - - - + + + + - - - + - + + + - + - - - - + + - + + + - - - - - + + + + + + + + - - - + + + + + + + - - + - + - - - - + + + + - - - + + + + - + + + - - + - - + - - - + - + + - + + + - + - - + - + + - + - - - + + - - - - - + + - - - + + - - - - - + + - + + + - + @@ -5209,52 +4883,54 @@

Total time: 63.22

- + + + + + - - - + + + + - - + + + + - - - - - - + @@ -5264,26 +4940,29 @@

Total time: 63.22

+ + - + + + - - + @@ -5298,6 +4977,7 @@

Total time: 63.22

+ @@ -5307,7 +4987,6 @@

Total time: 63.22

- @@ -5315,10 +4994,7 @@

Total time: 63.22

- - - @@ -5327,6 +5003,7 @@

Total time: 63.22

+ @@ -5336,18 +5013,19 @@

Total time: 63.22

+ - - + + @@ -5359,17 +5037,15 @@

Total time: 63.22

- - + - @@ -5377,6 +5053,7 @@

Total time: 63.22

+ @@ -5385,6 +5062,7 @@

Total time: 63.22

+ diff --git a/proto/dynamic_discovery.proto b/proto/dynamic_discovery.proto index dcecca5f..a2301b5a 100644 --- a/proto/dynamic_discovery.proto +++ b/proto/dynamic_discovery.proto @@ -22,6 +22,8 @@ // // Protobufs needed for dynamic discovery zmq server and client. +syntax = "proto2"; + package protobuf.rpc.dynamicDiscovery; enum BeaconType { diff --git a/proto/google/protobuf/compiler/plugin.proto b/proto/google/protobuf/compiler/plugin.proto index 77b888f3..9242aacc 100644 --- a/proto/google/protobuf/compiler/plugin.proto +++ b/proto/google/protobuf/compiler/plugin.proto @@ -1,6 +1,6 @@ // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ +// https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -44,12 +44,26 @@ // plugin should be named "protoc-gen-$NAME", and will then be used when the // flag "--${NAME}_out" is passed to protoc. +syntax = "proto2"; + package google.protobuf.compiler; option java_package = "com.google.protobuf.compiler"; option java_outer_classname = "PluginProtos"; +option go_package = "google.golang.org/protobuf/types/pluginpb"; + import "google/protobuf/descriptor.proto"; +// The version number of protocol compiler. +message Version { + optional int32 major = 1; + optional int32 minor = 2; + optional int32 patch = 3; + // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should + // be empty for mainline stable releases. + optional string suffix = 4; +} + // An encoded CodeGeneratorRequest is written to the plugin's stdin. message CodeGeneratorRequest { // The .proto files that were explicitly listed on the command-line. The @@ -71,7 +85,14 @@ message CodeGeneratorRequest { // the entire set into memory at once. However, as of this writing, this // is not similarly optimized on protoc's end -- it will store all fields in // memory at once before sending them to the plugin. + // + // Type names of fields and extensions in the FileDescriptorProto are always + // fully qualified. repeated FileDescriptorProto proto_file = 15; + + // The version number of protocol compiler. + optional Version compiler_version = 3; + } // The plugin writes an encoded CodeGeneratorResponse to stdout. @@ -86,6 +107,16 @@ message CodeGeneratorResponse { // exiting with a non-zero status code. optional string error = 1; + // A bitmask of supported features that the code generator supports. + // This is a bitwise "or" of values from the Feature enum. + optional uint64 supported_features = 2; + + // Sync with code_generator.h. + enum Feature { + FEATURE_NONE = 0; + FEATURE_PROTO3_OPTIONAL = 1; + } + // Represents a single generated file. message File { // The file name, relative to the output directory. The name must not @@ -142,6 +173,11 @@ message CodeGeneratorResponse { // The file contents. optional string content = 15; + + // Information describing the file content being inserted. If an insertion + // point is used, this information will be appropriately offset and inserted + // into the code generation metadata for the generated files. + optional GeneratedCodeInfo generated_code_info = 16; } repeated File file = 15; } diff --git a/proto/google/protobuf/descriptor.proto b/proto/google/protobuf/descriptor.proto index c59a6022..156e410a 100644 --- a/proto/google/protobuf/descriptor.proto +++ b/proto/google/protobuf/descriptor.proto @@ -40,11 +40,13 @@ syntax = "proto2"; package google.protobuf; -option go_package = "descriptor"; + +option go_package = "google.golang.org/protobuf/types/descriptorpb"; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; +option cc_enable_arenas = true; // descriptor.proto must be optimized for speed because reflection-based // algorithms don't work during bootstrapping. @@ -58,8 +60,8 @@ message FileDescriptorSet { // Describes a complete .proto file. message FileDescriptorProto { - optional string name = 1; // file name, relative to root of source tree - optional string package = 2; // e.g. "foo", "foo.bar", etc. + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. // Names of files imported by this file. repeated string dependency = 3; @@ -99,8 +101,10 @@ message DescriptorProto { repeated EnumDescriptorProto enum_type = 4; message ExtensionRange { - optional int32 start = 1; - optional int32 end = 2; + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + + optional ExtensionRangeOptions options = 3; } repeated ExtensionRange extension_range = 5; @@ -112,8 +116,8 @@ message DescriptorProto { // fields or extension ranges in the same message. Reserved ranges may // not overlap. message ReservedRange { - optional int32 start = 1; // Inclusive. - optional int32 end = 2; // Exclusive. + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. } repeated ReservedRange reserved_range = 9; // Reserved field names, which may not be used by fields in the same message. @@ -121,44 +125,56 @@ message DescriptorProto { repeated string reserved_name = 10; } +message ExtensionRangeOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + // Describes a field within a message. message FieldDescriptorProto { enum Type { // 0 is reserved for errors. // Order is weird for historical reasons. - TYPE_DOUBLE = 1; - TYPE_FLOAT = 2; + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if // negative values are likely. - TYPE_INT64 = 3; - TYPE_UINT64 = 4; + TYPE_INT64 = 3; + TYPE_UINT64 = 4; // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if // negative values are likely. - TYPE_INT32 = 5; - TYPE_FIXED64 = 6; - TYPE_FIXED32 = 7; - TYPE_BOOL = 8; - TYPE_STRING = 9; - TYPE_GROUP = 10; // Tag-delimited aggregate. - TYPE_MESSAGE = 11; // Length-delimited aggregate. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + // Tag-delimited aggregate. + // Group type is deprecated and not supported in proto3. However, Proto3 + // implementations should still be able to parse the group wire format and + // treat group fields as unknown fields. + TYPE_GROUP = 10; + TYPE_MESSAGE = 11; // Length-delimited aggregate. // New in version 2. - TYPE_BYTES = 12; - TYPE_UINT32 = 13; - TYPE_ENUM = 14; - TYPE_SFIXED32 = 15; - TYPE_SFIXED64 = 16; - TYPE_SINT32 = 17; // Uses ZigZag encoding. - TYPE_SINT64 = 18; // Uses ZigZag encoding. - }; + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + } enum Label { // 0 is reserved for errors - LABEL_OPTIONAL = 1; - LABEL_REQUIRED = 2; - LABEL_REPEATED = 3; - // TODO(sanjay): Should we add LABEL_MAP? - }; + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + } optional string name = 1; optional int32 number = 3; @@ -197,11 +213,35 @@ message FieldDescriptorProto { optional string json_name = 10; optional FieldOptions options = 8; + + // If true, this is a proto3 "optional". When a proto3 field is optional, it + // tracks presence regardless of field type. + // + // When proto3_optional is true, this field must be belong to a oneof to + // signal to old proto3 clients that presence is tracked for this field. This + // oneof is known as a "synthetic" oneof, and this field must be its sole + // member (each proto3 optional field gets its own synthetic oneof). Synthetic + // oneofs exist in the descriptor only, and do not generate any API. Synthetic + // oneofs must be ordered after all "real" oneofs. + // + // For message fields, proto3_optional doesn't create any semantic change, + // since non-repeated message fields always track presence. However it still + // indicates the semantic detail of whether the user wrote "optional" or not. + // This can be useful for round-tripping the .proto file. For consistency we + // give message fields a synthetic oneof also, even though it is not required + // to track presence. This is especially important because the parser can't + // tell if a field is a message or an enum, so it must always create a + // synthetic oneof. + // + // Proto2 optional fields do not set this flag, because they already indicate + // optional with `LABEL_OPTIONAL`. + optional bool proto3_optional = 17; } // Describes a oneof. message OneofDescriptorProto { optional string name = 1; + optional OneofOptions options = 2; } // Describes an enum type. @@ -211,6 +251,26 @@ message EnumDescriptorProto { repeated EnumValueDescriptorProto value = 2; optional EnumOptions options = 3; + + // Range of reserved numeric values. Reserved values may not be used by + // entries in the same enum. Reserved ranges may not overlap. + // + // Note that this is distinct from DescriptorProto.ReservedRange in that it + // is inclusive such that it can appropriately represent the entire int32 + // domain. + message EnumReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Inclusive. + } + + // Range of reserved numeric values. Reserved numeric values may not be used + // by enum values in the same enum declaration. Reserved ranges may not + // overlap. + repeated EnumReservedRange reserved_range = 4; + + // Reserved enum value names, which may not be reused. A given name may only + // be reserved once. + repeated string reserved_name = 5; } // Describes a value within an enum. @@ -241,9 +301,9 @@ message MethodDescriptorProto { optional MethodOptions options = 4; // Identifies if client streams multiple client messages - optional bool client_streaming = 5 [default=false]; + optional bool client_streaming = 5 [default = false]; // Identifies if server streams multiple server messages - optional bool server_streaming = 6 [default=false]; + optional bool server_streaming = 6 [default = false]; } @@ -279,7 +339,6 @@ message MethodDescriptorProto { // If this turns out to be popular, a web service will be set up // to automatically assign option numbers. - message FileOptions { // Sets the Java package where classes generated from this .proto will be @@ -289,34 +348,23 @@ message FileOptions { optional string java_package = 1; - // If set, all the classes from the .proto file are wrapped in a single - // outer class with the given name. This applies to both Proto1 - // (equivalent to the old "--one_java_file" option) and Proto2 (where - // a .proto always translates to a single class, but you may want to - // explicitly choose the class name). + // Controls the name of the wrapper Java class generated for the .proto file. + // That class will always contain the .proto file's getDescriptor() method as + // well as any top-level extensions defined in the .proto file. + // If java_multiple_files is disabled, then all the other classes from the + // .proto file will be nested inside the single wrapper outer class. optional string java_outer_classname = 8; - // If set true, then the Java code generator will generate a separate .java + // If enabled, then the Java code generator will generate a separate .java // file for each top-level message, enum, and service defined in the .proto - // file. Thus, these types will *not* be nested inside the outer class - // named by java_outer_classname. However, the outer class will still be + // file. Thus, these types will *not* be nested inside the wrapper class + // named by java_outer_classname. However, the wrapper class will still be // generated to contain the file's getDescriptor() method as well as any // top-level extensions defined in the file. - optional bool java_multiple_files = 10 [default=false]; - - // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. - // This increases generated code size, potentially substantially for large - // protos, which may harm a memory-constrained application. - // - In the full runtime this is a speed optimization, as the - // AbstractMessage base class includes reflection-based implementations of - // these methods. - // - In the lite runtime, setting this option changes the semantics of - // equals() and hashCode() to more closely match those of the full runtime; - // the generated methods compute their results based on field values rather - // than object identity. (Implementations should not assume that hashcodes - // will be consistent across runtimes or versions of the protocol compiler.) - optional bool java_generate_equals_and_hash = 20 [default=false]; + optional bool java_multiple_files = 10 [default = false]; + + // This option does nothing. + optional bool java_generate_equals_and_hash = 20 [deprecated=true]; // If set true, then the Java2 code generator will generate code that // throws an exception whenever an attempt is made to assign a non-UTF-8 @@ -324,17 +372,17 @@ message FileOptions { // Message reflection will do the same. // However, an extension field still accepts non-UTF-8 byte sequences. // This option has no effect on when used with the lite runtime. - optional bool java_string_check_utf8 = 27 [default=false]; + optional bool java_string_check_utf8 = 27 [default = false]; // Generated classes can be optimized for speed or code size. enum OptimizeMode { - SPEED = 1; // Generate complete code for parsing, serialization, - // etc. - CODE_SIZE = 2; // Use ReflectionOps to implement these methods. - LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. } - optional OptimizeMode optimize_for = 9 [default=SPEED]; + optional OptimizeMode optimize_for = 9 [default = SPEED]; // Sets the Go package where structs generated from this .proto will be // placed. If omitted, the Go package will be derived from the following: @@ -345,6 +393,7 @@ message FileOptions { + // Should generic services be generated in each language? "Generic" services // are not specific to any particular RPC system. They are generated by the // main code generators in each language (without additional plugins). @@ -355,19 +404,20 @@ message FileOptions { // that generate code specific to your particular RPC system. Therefore, // these default to false. Old code which depends on generic services should // explicitly set them to true. - optional bool cc_generic_services = 16 [default=false]; - optional bool java_generic_services = 17 [default=false]; - optional bool py_generic_services = 18 [default=false]; + optional bool cc_generic_services = 16 [default = false]; + optional bool java_generic_services = 17 [default = false]; + optional bool py_generic_services = 18 [default = false]; + optional bool php_generic_services = 42 [default = false]; // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations // for everything in the file, or it will be completely ignored; in the very // least, this is a formalization for deprecating files. - optional bool deprecated = 23 [default=false]; + optional bool deprecated = 23 [default = false]; // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. - optional bool cc_enable_arenas = 31 [default=false]; + optional bool cc_enable_arenas = 31 [default = true]; // Sets the objective c class prefix which is prepended to all objective c @@ -377,15 +427,41 @@ message FileOptions { // Namespace for generated classes; defaults to the package. optional string csharp_namespace = 37; - // Whether the nano proto compiler should generate in the deprecated non-nano - // suffixed package. - optional bool javanano_use_deprecated_package = 38; + // By default Swift generators will take the proto package and CamelCase it + // replacing '.' with underscore and use that to prefix the types/symbols + // defined. When this options is provided, they will use this value instead + // to prefix the types/symbols defined. + optional string swift_prefix = 39; - // The parser stores options it doesn't recognize here. See above. + // Sets the php class prefix which is prepended to all php generated classes + // from this .proto. Default is empty. + optional string php_class_prefix = 40; + + // Use this option to change the namespace of php generated classes. Default + // is empty. When this option is empty, the package name will be used for + // determining the namespace. + optional string php_namespace = 41; + + // Use this option to change the namespace of php generated metadata classes. + // Default is empty. When this option is empty, the proto file name will be + // used for determining the namespace. + optional string php_metadata_namespace = 44; + + // Use this option to change the package of ruby generated classes. Default + // is empty. When this option is not set, the package name will be used for + // determining the ruby package. + optional string ruby_package = 45; + + + // The parser stores options it doesn't recognize here. + // See the documentation for the "Options" section above. repeated UninterpretedOption uninterpreted_option = 999; - // Clients can define custom options in extensions of this message. See above. + // Clients can define custom options in extensions of this message. + // See the documentation for the "Options" section above. extensions 1000 to max; + + reserved 38; } message MessageOptions { @@ -407,18 +483,20 @@ message MessageOptions { // // Because this is an option, the above two restrictions are not enforced by // the protocol compiler. - optional bool message_set_wire_format = 1 [default=false]; + optional bool message_set_wire_format = 1 [default = false]; // Disables the generation of the standard "descriptor()" accessor, which can // conflict with a field of the same name. This is meant to make migration // from proto1 easier; new code should avoid fields named "descriptor". - optional bool no_standard_descriptor_accessor = 2 [default=false]; + optional bool no_standard_descriptor_accessor = 2 [default = false]; // Is this message deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the message, or it will be completely ignored; in the very least, // this is a formalization for deprecating messages. - optional bool deprecated = 3 [default=false]; + optional bool deprecated = 3 [default = false]; + + reserved 4, 5, 6; // Whether the message is an automatically generated map entry type for the // maps field. @@ -435,7 +513,7 @@ message MessageOptions { // // Implementations may choose not to generate the map_entry=true message, but // use a native map in the target language to hold the keys and values. - // The reflection APIs in such implementions still need to work as + // The reflection APIs in such implementations still need to work as // if the field is a repeated message field. // // NOTE: Do not set the option in .proto files. Always use the maps syntax @@ -443,6 +521,10 @@ message MessageOptions { // parser. optional bool map_entry = 7; + reserved 8; // javalite_serializable + reserved 9; // javanano_as_lite + + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -471,16 +553,17 @@ message FieldOptions { // false will avoid using packed encoding. optional bool packed = 2; - // The jstype option determines the JavaScript type used for values of the // field. The option is permitted only for 64 bit integral and fixed types - // (int64, uint64, sint64, fixed64, sfixed64). By default these types are - // represented as JavaScript strings. This avoids loss of precision that can - // happen when a large value is converted to a floating point JavaScript - // numbers. Specifying JS_NUMBER for the jstype causes the generated - // JavaScript code to use the JavaScript "number" type instead of strings. - // This option is an enum to permit additional types to be added, - // e.g. goog.math.Integer. + // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING + // is represented as JavaScript string, which avoids loss of precision that + // can happen when a large value is converted to a floating point JavaScript. + // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to + // use the JavaScript "number" type. The behavior of the default option + // JS_NORMAL is implementation dependent. + // + // This option is an enum to permit additional types to be added, e.g. + // goog.math.Integer. optional JSType jstype = 6 [default = JS_NORMAL]; enum JSType { // Use the default type. @@ -512,7 +595,7 @@ message FieldOptions { // // // Note that implementations may choose not to check required fields within - // a lazy sub-message. That is, calling IsInitialized() on the outher message + // a lazy sub-message. That is, calling IsInitialized() on the outer message // may return true even if the inner message has missing required fields. // This is necessary because otherwise the inner message would have to be // parsed in order to perform the check, defeating the purpose of lazy @@ -521,18 +604,28 @@ message FieldOptions { // implementation must either *always* check its required fields, or *never* // check its required fields, regardless of whether or not the message has // been parsed. - optional bool lazy = 5 [default=false]; + optional bool lazy = 5 [default = false]; // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this // is a formalization for deprecating fields. - optional bool deprecated = 3 [default=false]; + optional bool deprecated = 3 [default = false]; // For Google-internal migration only. Do not use. - optional bool weak = 10 [default=false]; + optional bool weak = 10 [default = false]; + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; + + reserved 4; // removed jtype +} + +message OneofOptions { // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -550,7 +643,9 @@ message EnumOptions { // Depending on the target platform, this can emit Deprecated annotations // for the enum, or it will be completely ignored; in the very least, this // is a formalization for deprecating enums. - optional bool deprecated = 3 [default=false]; + optional bool deprecated = 3 [default = false]; + + reserved 5; // javanano_as_lite // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -564,7 +659,7 @@ message EnumValueOptions { // Depending on the target platform, this can emit Deprecated annotations // for the enum value, or it will be completely ignored; in the very least, // this is a formalization for deprecating enum values. - optional bool deprecated = 1 [default=false]; + optional bool deprecated = 1 [default = false]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -584,7 +679,7 @@ message ServiceOptions { // Depending on the target platform, this can emit Deprecated annotations // for the service, or it will be completely ignored; in the very least, // this is a formalization for deprecating services. - optional bool deprecated = 33 [default=false]; + optional bool deprecated = 33 [default = false]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -604,7 +699,18 @@ message MethodOptions { // Depending on the target platform, this can emit Deprecated annotations // for the method, or it will be completely ignored; in the very least, // this is a formalization for deprecating methods. - optional bool deprecated = 33 [default=false]; + optional bool deprecated = 33 [default = false]; + + // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, + // or neither? HTTP based RPC implementation may choose GET verb for safe + // methods, and PUT verb for idempotent methods instead of the default POST. + enum IdempotencyLevel { + IDEMPOTENCY_UNKNOWN = 0; + NO_SIDE_EFFECTS = 1; // implies idempotent + IDEMPOTENT = 2; // idempotent, but may have side effects + } + optional IdempotencyLevel idempotency_level = 34 + [default = IDEMPOTENCY_UNKNOWN]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -685,7 +791,7 @@ message SourceCodeInfo { // beginning of the "extend" block and is shared by all extensions within // the block. // - Just because a location's span is a subset of some other location's span - // does not mean that it is a descendent. For example, a "group" defines + // does not mean that it is a descendant. For example, a "group" defines // both a type and a field in a single declaration. Thus, the locations // corresponding to the type and field and their components will overlap. // - Code which tries to interpret locations should probably be designed to @@ -716,14 +822,14 @@ message SourceCodeInfo { // [ 4, 3, 2, 7 ] // this path refers to the whole field declaration (from the beginning // of the label to the terminating semicolon). - repeated int32 path = 1 [packed=true]; + repeated int32 path = 1 [packed = true]; // Always has exactly three or four elements: start line, start column, // end line (optional, otherwise assumed same as start line), end column. // These are packed into a single field for efficiency. Note that line // and column numbers are zero-based -- typically you will want to add // 1 to each before displaying to a user. - repeated int32 span = 2 [packed=true]; + repeated int32 span = 2 [packed = true]; // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be @@ -777,3 +883,29 @@ message SourceCodeInfo { repeated string leading_detached_comments = 6; } } + +// Describes the relationship between generated code and its original source +// file. A GeneratedCodeInfo message is associated with only one generated +// source file, but may contain references to different source .proto files. +message GeneratedCodeInfo { + // An Annotation connects some span of text in generated code to an element + // of its generating .proto file. + repeated Annotation annotation = 1; + message Annotation { + // Identifies the element in the original source .proto file. This field + // is formatted the same as SourceCodeInfo.Location.path. + repeated int32 path = 1 [packed = true]; + + // Identifies the filesystem path to the original source .proto. + optional string source_file = 2; + + // Identifies the starting offset in bytes in the generated code + // that relates to the identified object. + optional int32 begin = 3; + + // Identifies the ending offset in bytes in the generated code that + // relates to the identified offset. The end offset should be one past + // the last relevant byte (so the length of the text = end - begin). + optional int32 end = 4; + } +} diff --git a/proto/rpc.proto b/proto/rpc.proto index 17a1e350..87fef057 100644 --- a/proto/rpc.proto +++ b/proto/rpc.proto @@ -22,6 +22,8 @@ // // Protobufs needed for socket rpcs. +syntax = "proto2"; + package protobuf.socketrpc; message Request @@ -30,6 +32,7 @@ message Request required string method_name = 2; // Service method to invoke optional bytes request_proto = 3; // Serialized request bytes optional string caller = 4; // Calling hostname or address + repeated Header headers = 5; // General purpose request headers } message Response @@ -41,6 +44,11 @@ message Response optional string server = 5; // Server hostname or address } +message Header { + required string key = 1; + optional string value = 2; +} + // Possible error reasons // The server-side errors are returned in the response from the server. // The client-side errors are returned by the client-side code when it doesn't diff --git a/protobuf.gemspec b/protobuf.gemspec index 2d9330ef..698c434b 100644 --- a/protobuf.gemspec +++ b/protobuf.gemspec @@ -1,4 +1,3 @@ -# encoding: UTF-8 $LOAD_PATH.push ::File.expand_path("../lib", __FILE__) require "protobuf/version" @@ -28,31 +27,10 @@ require "protobuf/version" s.add_development_dependency 'benchmark-ips' s.add_development_dependency 'ffi-rzmq' - s.add_development_dependency 'rake', '< 11.0' # Rake 11.0.1 removes the last_comment method which rspec-core (< 3.4.4) uses - s.add_development_dependency 'rspec', '>= 3.0' - s.add_development_dependency "rubocop", "~> 0.38.0" - s.add_development_dependency "parser", "2.3.0.6" # Locked this down since 2.3.0.7 causes issues. https://github.com/bbatsov/rubocop/pull/2984 + s.add_development_dependency 'rake', '~> 13.0' + s.add_development_dependency 'rspec', '~> 3.5' + s.add_development_dependency "rubocop", "~> 0.81.0" s.add_development_dependency 'simplecov' s.add_development_dependency 'timecop' s.add_development_dependency 'yard' - - # debuggers only work in MRI - if RUBY_ENGINE.to_sym == :ruby - # we don't support MRI < 1.9.3 - pry_debugger = if RUBY_VERSION < '2.0.0' - 'pry-debugger' - else - 'pry-byebug' - end - - s.add_development_dependency pry_debugger - s.add_development_dependency 'pry-stack_explorer' - - s.add_development_dependency 'varint' - s.add_development_dependency 'ruby-prof' - elsif RUBY_PLATFORM =~ /java/i - #s.add_development_dependency 'protobuf_java_helpers' - s.add_development_dependency 'fast_blank_java' - s.add_development_dependency 'pry' - end end diff --git a/spec/encoding/extreme_values_spec.rb b/spec/encoding/extreme_values_spec.rb index 097e8ede..477e695a 100644 Binary files a/spec/encoding/extreme_values_spec.rb and b/spec/encoding/extreme_values_spec.rb differ diff --git a/spec/functional/code_generator_spec.rb b/spec/functional/code_generator_spec.rb index aac45319..3f767b23 100644 --- a/spec/functional/code_generator_spec.rb +++ b/spec/functional/code_generator_spec.rb @@ -17,7 +17,7 @@ end expected_output = - ::Google::Protobuf::Compiler::CodeGeneratorResponse.encode(:file => expected_file_descriptors) + ::Google::Protobuf::Compiler::CodeGeneratorResponse.encode(:file => expected_file_descriptors, :supported_features => 1) code_generator = ::Protobuf::CodeGenerator.new(bytes) code_generator.eval_unknown_extensions! @@ -37,7 +37,7 @@ :name => file_name, :content => file_content) expected_response = - ::Google::Protobuf::Compiler::CodeGeneratorResponse.encode(:file => [expected_file_output]) + ::Google::Protobuf::Compiler::CodeGeneratorResponse.encode(:file => [expected_file_output], :supported_features => 1) code_generator = ::Protobuf::CodeGenerator.new(request.encode) code_generator.eval_unknown_extensions! diff --git a/spec/lib/protobuf/cli_spec.rb b/spec/lib/protobuf/cli_spec.rb index 99fdb960..ea78ed0d 100644 --- a/spec/lib/protobuf/cli_spec.rb +++ b/spec/lib/protobuf/cli_spec.rb @@ -275,6 +275,41 @@ end end + context 'after server bind' do + let(:sock_runner) { double("FakeRunner", :run => nil) } + + before { allow(sock_runner).to receive(:run).and_yield } + + it 'publishes when using the lib/protobuf callback' do + message_after_bind = false + ::Protobuf.after_server_bind do + message_after_bind = true + end + described_class.start(args) + expect(message_after_bind).to eq(true) + end + end + + context 'before server bind' do + it 'publishes a message before the runner runs' do + message_before_bind = false + ::ActiveSupport::Notifications.subscribe('before_server_bind') do + message_before_bind = true + end + described_class.start(args) + expect(message_before_bind).to eq(true) + end + + it 'publishes when using the lib/protobuf callback' do + message_before_bind = false + ::Protobuf.before_server_bind do + message_before_bind = true + end + described_class.start(args) + expect(message_before_bind).to eq(true) + end + end + end end diff --git a/spec/lib/protobuf/code_generator_spec.rb b/spec/lib/protobuf/code_generator_spec.rb index 230029c0..44b8dd16 100644 --- a/spec/lib/protobuf/code_generator_spec.rb +++ b/spec/lib/protobuf/code_generator_spec.rb @@ -23,7 +23,7 @@ end let(:expected_response_bytes) do - COMPILER::CodeGeneratorResponse.encode(:file => [output_file1, output_file2]) + COMPILER::CodeGeneratorResponse.encode(:file => [output_file1, output_file2], :supported_features => 1) end before do diff --git a/spec/lib/protobuf/field/string_field_spec.rb b/spec/lib/protobuf/field/string_field_spec.rb index f666907a..4fe358a3 100644 --- a/spec/lib/protobuf/field/string_field_spec.rb +++ b/spec/lib/protobuf/field/string_field_spec.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'spec_helper' RSpec.describe ::Protobuf::Field::StringField do diff --git a/spec/lib/protobuf/generators/enum_generator_spec.rb b/spec/lib/protobuf/generators/enum_generator_spec.rb index 1c263188..767a5d9d 100644 --- a/spec/lib/protobuf/generators/enum_generator_spec.rb +++ b/spec/lib/protobuf/generators/enum_generator_spec.rb @@ -71,12 +71,23 @@ class TestEnum < ::Protobuf::Enum context 'with PB_UPCASE_ENUMS set' do before { allow(ENV).to receive(:key?).with('PB_UPCASE_ENUMS').and_return(true) } + before { allow(ENV).to receive(:key?).with('PB_CAPITALIZE_ENUMS').and_return(false) } let(:values) { [{ :name => 'boom', :number => 1 }] } it 'returns a string with the given enum name in ALL CAPS' do expect(subject.build_value(enum.value.first)).to eq("define :BOOM, 1") end end + + context 'with PB_CAPITALIZE_ENUMS set' do + before { allow(ENV).to receive(:key?).with('PB_UPCASE_ENUMS').and_return(false) } + before { allow(ENV).to receive(:key?).with('PB_CAPITALIZE_ENUMS').and_return(true) } + let(:values) { [{ :name => 'boom', :number => 1 }] } + + it 'returns a string with the given enum name in ALL CAPS' do + expect(subject.build_value(enum.value.first)).to eq("define :Boom, 1") + end + end end end diff --git a/spec/lib/protobuf/generators/field_generator_spec.rb b/spec/lib/protobuf/generators/field_generator_spec.rb index e4d78ea2..fc7c3def 100644 --- a/spec/lib/protobuf/generators/field_generator_spec.rb +++ b/spec/lib/protobuf/generators/field_generator_spec.rb @@ -67,10 +67,21 @@ let(:type_name) { '.foo.bar.Baz' } let(:default_value) { 'quux' } before { allow(ENV).to receive(:key?).with('PB_UPCASE_ENUMS').and_return(true) } + before { allow(ENV).to receive(:key?).with('PB_CAPITALIZE_ENUMS').and_return(false) } specify { expect(subject).to eq " optional ::Foo::Bar::Baz, :foo_bar, 3, :default => ::Foo::Bar::Baz::QUUX\n" } end + context 'when type is an enum with lowercase default value with PB_CAPITALIZE_ENUMS set' do + let(:type_enum) { :TYPE_ENUM } + let(:type_name) { '.foo.bar.Baz' } + let(:default_value) { 'quux' } + before { allow(ENV).to receive(:key?).with('PB_UPCASE_ENUMS').and_return(false) } + before { allow(ENV).to receive(:key?).with('PB_CAPITALIZE_ENUMS').and_return(true) } + + specify { expect(subject).to eq " optional ::Foo::Bar::Baz, :foo_bar, 3, :default => ::Foo::Bar::Baz::Quux\n" } + end + context 'when the type is a string' do let(:type_enum) { :TYPE_STRING } let(:default_value) { "a default \"string\"" } diff --git a/spec/lib/protobuf/message_spec.rb b/spec/lib/protobuf/message_spec.rb index 96668b67..50513f14 100644 --- a/spec/lib/protobuf/message_spec.rb +++ b/spec/lib/protobuf/message_spec.rb @@ -1,5 +1,3 @@ -# encoding: utf-8 - require 'stringio' require 'spec_helper' require PROTOS_PATH.join('resource.pb') diff --git a/spec/lib/protobuf/rpc/connectors/base_spec.rb b/spec/lib/protobuf/rpc/connectors/base_spec.rb index e5890307..32b8cd8b 100644 --- a/spec/lib/protobuf/rpc/connectors/base_spec.rb +++ b/spec/lib/protobuf/rpc/connectors/base_spec.rb @@ -187,14 +187,14 @@ shared_examples "a ConnectorDisposition" do |meth, cb, *args| it "calls #complete before exit" do - subject.stats = double("Object", :stop => true) + subject.stats = ::Protobuf::Rpc::Stat.new(:stop => true) expect(subject).to receive(:complete) subject.method(meth).call(*args) end it "calls the #{cb} callback when provided" do - stats = double("Object") + stats = ::Protobuf::Rpc::Stat.new allow(stats).to receive(:stop).and_return(true) subject.stats = stats some_cb = double("Object") @@ -205,7 +205,7 @@ end it "calls the complete callback when provided" do - stats = double("Object") + stats = ::Protobuf::Rpc::Stat.new allow(stats).to receive(:stop).and_return(true) subject.stats = stats comp_cb = double("Object") @@ -217,8 +217,8 @@ end - it_behaves_like("a ConnectorDisposition", :failure, "failure_cb", "code", "message") - it_behaves_like("a ConnectorDisposition", :failure, "complete_cb", "code", "message") + it_behaves_like("a ConnectorDisposition", :failure, "failure_cb", :RPC_ERROR, "message") + it_behaves_like("a ConnectorDisposition", :failure, "complete_cb", :RPC_ERROR, "message") it_behaves_like("a ConnectorDisposition", :succeed, "complete_cb", "response") it_behaves_like("a ConnectorDisposition", :succeed, "success_cb", "response") it_behaves_like("a ConnectorDisposition", :complete, "complete_cb") diff --git a/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb b/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb index 0a71e43d..01248f40 100644 --- a/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +++ b/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Protobuf::Rpc::Middleware::ExceptionHandler do let(:app) { proc { |env| env } } - let(:env) { Protobuf::Rpc::Env.new } + let(:env) { Protobuf::Rpc::Env.new("server" => "cooldude") } subject { described_class.new(app) } @@ -17,7 +17,7 @@ end context "when exceptions occur" do - let(:encoded_error) { error.encode } + let(:encoded_error) { error.encode(:server => "cooldude") } let(:error) { Protobuf::Rpc::MethodNotFound.new('Boom!') } before { allow(app).to receive(:call).and_raise(error, 'Boom!') } @@ -42,7 +42,7 @@ end context "when exception is not a Protobuf error" do - let(:encoded_error) { error.encode } + let(:encoded_error) { error.encode(:server => "cooldude") } let(:error) { Protobuf::Rpc::RpcFailed.new('Boom!') } before { allow(app).to receive(:call).and_raise(RuntimeError, 'Boom!') } diff --git a/spec/lib/protobuf/rpc/stat_spec.rb b/spec/lib/protobuf/rpc/stat_spec.rb index 2b6c6011..10015491 100644 --- a/spec/lib/protobuf/rpc/stat_spec.rb +++ b/spec/lib/protobuf/rpc/stat_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' require 'timecop' -require 'active_support/core_ext/numeric/time' +require 'active_support/all' RSpec.describe ::Protobuf::Rpc::Stat do @@ -33,7 +33,7 @@ ::Timecop.freeze(1.62.seconds.from_now) do stats.stop - expect(stats.to_s).to eq "[SRV] - myserver1 - #{stats.trace_id} - BarService#find_bars - 43B/1302B - 1.62s - #{::Time.now.iso8601}" + expect(stats.to_s).to eq "[SRV] - myserver1 - #{stats.trace_id} - BarService#find_bars - 43B/1302B - 1.62s - OK - #{::Time.now.iso8601}" end end end @@ -44,7 +44,7 @@ stats.client = 'myserver1' stats.dispatcher = double('dispatcher', :service => BarService.new(:find_bars)) stats.request_size = 43 - expect(stats.to_s).to eq "[SRV] - myserver1 - #{stats.trace_id} - BarService#find_bars - 43B/-" + expect(stats.to_s).to eq "[SRV] - myserver1 - #{stats.trace_id} - BarService#find_bars - 43B/- - OK" end end end @@ -61,12 +61,31 @@ ::Timecop.freeze(0.832.seconds.from_now) do stats.stop - expect(stats.to_s).to eq "[CLT] - myserver1.myhost.com:30000 - #{stats.trace_id} - Foo::BarService#find_bars - 37B/12345B - 0.832s - #{::Time.now.iso8601}" + expect(stats.to_s).to eq "[CLT] - myserver1.myhost.com:30000 - #{stats.trace_id} - Foo::BarService#find_bars - 37B/12345B - 0.832s - OK - #{::Time.now.iso8601}" end end end + describe 'error log' do + it 'resolves error to a string' do + ::Timecop.freeze(10.minutes.ago) do + stats = ::Protobuf::Rpc::Stat.new(:CLIENT) + stats.server = ['30000', 'myserver1.myhost.com'] + stats.service = 'Foo::BarService' + stats.status = ::Protobuf::Socketrpc::ErrorReason::RPC_ERROR + stats.method_name = 'find_bars' + stats.request_size = 37 + stats.response_size = 12345 + + ::Timecop.freeze(0.832.seconds.from_now) do + stats.stop + expect(stats.to_s).to eq "[CLT] - myserver1.myhost.com:30000 - #{stats.trace_id} - Foo::BarService#find_bars - 37B/12345B - 0.832s - RPC_ERROR - #{::Time.now.iso8601}" + end + end + end + end + context 'when request is still running' do it 'omits response size, duration, and timestamp' do stats = ::Protobuf::Rpc::Stat.new(:CLIENT) @@ -74,7 +93,7 @@ stats.service = 'Foo::BarService' stats.method_name = 'find_bars' stats.request_size = 37 - expect(stats.to_s).to eq "[CLT] - myserver1.myhost.com:30000 - #{stats.trace_id} - Foo::BarService#find_bars - 37B/-" + expect(stats.to_s).to eq "[CLT] - myserver1.myhost.com:30000 - #{stats.trace_id} - Foo::BarService#find_bars - 37B/- - OK" end end end diff --git a/spec/support/google/protobuf/descriptor.pb.rb b/spec/support/google/protobuf/descriptor.pb.rb new file mode 100644 index 00000000..acff3ebd --- /dev/null +++ b/spec/support/google/protobuf/descriptor.pb.rb @@ -0,0 +1,360 @@ +# encoding: utf-8 + +## +# This file is auto-generated. DO NOT EDIT! +# +require 'protobuf' + +module Google + module Protobuf + ::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions } + + ## + # Message Classes + # + class FileDescriptorSet < ::Protobuf::Message; end + class FileDescriptorProto < ::Protobuf::Message; end + class DescriptorProto < ::Protobuf::Message + class ExtensionRange < ::Protobuf::Message; end + class ReservedRange < ::Protobuf::Message; end + + end + + class ExtensionRangeOptions < ::Protobuf::Message; end + class FieldDescriptorProto < ::Protobuf::Message + class Type < ::Protobuf::Enum + define :TYPE_DOUBLE, 1 + define :TYPE_FLOAT, 2 + define :TYPE_INT64, 3 + define :TYPE_UINT64, 4 + define :TYPE_INT32, 5 + define :TYPE_FIXED64, 6 + define :TYPE_FIXED32, 7 + define :TYPE_BOOL, 8 + define :TYPE_STRING, 9 + define :TYPE_GROUP, 10 + define :TYPE_MESSAGE, 11 + define :TYPE_BYTES, 12 + define :TYPE_UINT32, 13 + define :TYPE_ENUM, 14 + define :TYPE_SFIXED32, 15 + define :TYPE_SFIXED64, 16 + define :TYPE_SINT32, 17 + define :TYPE_SINT64, 18 + end + + class Label < ::Protobuf::Enum + define :LABEL_OPTIONAL, 1 + define :LABEL_REQUIRED, 2 + define :LABEL_REPEATED, 3 + end + + end + + class OneofDescriptorProto < ::Protobuf::Message; end + class EnumDescriptorProto < ::Protobuf::Message + class EnumReservedRange < ::Protobuf::Message; end + + end + + class EnumValueDescriptorProto < ::Protobuf::Message; end + class ServiceDescriptorProto < ::Protobuf::Message; end + class MethodDescriptorProto < ::Protobuf::Message; end + class FileOptions < ::Protobuf::Message + class OptimizeMode < ::Protobuf::Enum + define :SPEED, 1 + define :CODE_SIZE, 2 + define :LITE_RUNTIME, 3 + end + + end + + class MessageOptions < ::Protobuf::Message; end + class FieldOptions < ::Protobuf::Message + class CType < ::Protobuf::Enum + define :STRING, 0 + define :CORD, 1 + define :STRING_PIECE, 2 + end + + class JSType < ::Protobuf::Enum + define :JS_NORMAL, 0 + define :JS_STRING, 1 + define :JS_NUMBER, 2 + end + + end + + class OneofOptions < ::Protobuf::Message; end + class EnumOptions < ::Protobuf::Message; end + class EnumValueOptions < ::Protobuf::Message; end + class ServiceOptions < ::Protobuf::Message; end + class MethodOptions < ::Protobuf::Message + class IdempotencyLevel < ::Protobuf::Enum + define :IDEMPOTENCY_UNKNOWN, 0 + define :NO_SIDE_EFFECTS, 1 + define :IDEMPOTENT, 2 + end + + end + + class UninterpretedOption < ::Protobuf::Message + class NamePart < ::Protobuf::Message; end + + end + + class SourceCodeInfo < ::Protobuf::Message + class Location < ::Protobuf::Message; end + + end + + class GeneratedCodeInfo < ::Protobuf::Message + class Annotation < ::Protobuf::Message; end + + end + + + + ## + # File Options + # + set_option :java_package, "com.google.protobuf" + set_option :java_outer_classname, "DescriptorProtos" + set_option :optimize_for, ::Google::Protobuf::FileOptions::OptimizeMode::SPEED + set_option :go_package, "google.golang.org/protobuf/types/descriptorpb" + set_option :cc_enable_arenas, true + set_option :objc_class_prefix, "GPB" + set_option :csharp_namespace, "Google.Protobuf.Reflection" + + + ## + # Message Fields + # + class FileDescriptorSet + repeated ::Google::Protobuf::FileDescriptorProto, :file, 1 + end + + class FileDescriptorProto + optional :string, :name, 1 + optional :string, :package, 2 + repeated :string, :dependency, 3 + repeated :int32, :public_dependency, 10 + repeated :int32, :weak_dependency, 11 + repeated ::Google::Protobuf::DescriptorProto, :message_type, 4 + repeated ::Google::Protobuf::EnumDescriptorProto, :enum_type, 5 + repeated ::Google::Protobuf::ServiceDescriptorProto, :service, 6 + repeated ::Google::Protobuf::FieldDescriptorProto, :extension, 7 + optional ::Google::Protobuf::FileOptions, :options, 8 + optional ::Google::Protobuf::SourceCodeInfo, :source_code_info, 9 + optional :string, :syntax, 12 + end + + class DescriptorProto + class ExtensionRange + optional :int32, :start, 1 + optional :int32, :end, 2 + optional ::Google::Protobuf::ExtensionRangeOptions, :options, 3 + end + + class ReservedRange + optional :int32, :start, 1 + optional :int32, :end, 2 + end + + optional :string, :name, 1 + repeated ::Google::Protobuf::FieldDescriptorProto, :field, 2 + repeated ::Google::Protobuf::FieldDescriptorProto, :extension, 6 + repeated ::Google::Protobuf::DescriptorProto, :nested_type, 3 + repeated ::Google::Protobuf::EnumDescriptorProto, :enum_type, 4 + repeated ::Google::Protobuf::DescriptorProto::ExtensionRange, :extension_range, 5 + repeated ::Google::Protobuf::OneofDescriptorProto, :oneof_decl, 8 + optional ::Google::Protobuf::MessageOptions, :options, 7 + repeated ::Google::Protobuf::DescriptorProto::ReservedRange, :reserved_range, 9 + repeated :string, :reserved_name, 10 + end + + class ExtensionRangeOptions + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class FieldDescriptorProto + optional :string, :name, 1 + optional :int32, :number, 3 + optional ::Google::Protobuf::FieldDescriptorProto::Label, :label, 4 + optional ::Google::Protobuf::FieldDescriptorProto::Type, :type, 5 + optional :string, :type_name, 6 + optional :string, :extendee, 2 + optional :string, :default_value, 7 + optional :int32, :oneof_index, 9 + optional :string, :json_name, 10 + optional ::Google::Protobuf::FieldOptions, :options, 8 + optional :bool, :proto3_optional, 17 + end + + class OneofDescriptorProto + optional :string, :name, 1 + optional ::Google::Protobuf::OneofOptions, :options, 2 + end + + class EnumDescriptorProto + class EnumReservedRange + optional :int32, :start, 1 + optional :int32, :end, 2 + end + + optional :string, :name, 1 + repeated ::Google::Protobuf::EnumValueDescriptorProto, :value, 2 + optional ::Google::Protobuf::EnumOptions, :options, 3 + repeated ::Google::Protobuf::EnumDescriptorProto::EnumReservedRange, :reserved_range, 4 + repeated :string, :reserved_name, 5 + end + + class EnumValueDescriptorProto + optional :string, :name, 1 + optional :int32, :number, 2 + optional ::Google::Protobuf::EnumValueOptions, :options, 3 + end + + class ServiceDescriptorProto + optional :string, :name, 1 + repeated ::Google::Protobuf::MethodDescriptorProto, :method, 2 + optional ::Google::Protobuf::ServiceOptions, :options, 3 + end + + class MethodDescriptorProto + optional :string, :name, 1 + optional :string, :input_type, 2 + optional :string, :output_type, 3 + optional ::Google::Protobuf::MethodOptions, :options, 4 + optional :bool, :client_streaming, 5, :default => false + optional :bool, :server_streaming, 6, :default => false + end + + class FileOptions + optional :string, :java_package, 1 + optional :string, :java_outer_classname, 8 + optional :bool, :java_multiple_files, 10, :default => false + optional :bool, :java_generate_equals_and_hash, 20, :deprecated => true + optional :bool, :java_string_check_utf8, 27, :default => false + optional ::Google::Protobuf::FileOptions::OptimizeMode, :optimize_for, 9, :default => ::Google::Protobuf::FileOptions::OptimizeMode::SPEED + optional :string, :go_package, 11 + optional :bool, :cc_generic_services, 16, :default => false + optional :bool, :java_generic_services, 17, :default => false + optional :bool, :py_generic_services, 18, :default => false + optional :bool, :php_generic_services, 42, :default => false + optional :bool, :deprecated, 23, :default => false + optional :bool, :cc_enable_arenas, 31, :default => true + optional :string, :objc_class_prefix, 36 + optional :string, :csharp_namespace, 37 + optional :string, :swift_prefix, 39 + optional :string, :php_class_prefix, 40 + optional :string, :php_namespace, 41 + optional :string, :php_metadata_namespace, 44 + optional :string, :ruby_package, 45 + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class MessageOptions + optional :bool, :message_set_wire_format, 1, :default => false + optional :bool, :no_standard_descriptor_accessor, 2, :default => false + optional :bool, :deprecated, 3, :default => false + optional :bool, :map_entry, 7 + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class FieldOptions + optional ::Google::Protobuf::FieldOptions::CType, :ctype, 1, :default => ::Google::Protobuf::FieldOptions::CType::STRING + optional :bool, :packed, 2 + optional ::Google::Protobuf::FieldOptions::JSType, :jstype, 6, :default => ::Google::Protobuf::FieldOptions::JSType::JS_NORMAL + optional :bool, :lazy, 5, :default => false + optional :bool, :deprecated, 3, :default => false + optional :bool, :weak, 10, :default => false + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class OneofOptions + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class EnumOptions + optional :bool, :allow_alias, 2 + optional :bool, :deprecated, 3, :default => false + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class EnumValueOptions + optional :bool, :deprecated, 1, :default => false + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class ServiceOptions + optional :bool, :deprecated, 33, :default => false + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class MethodOptions + optional :bool, :deprecated, 33, :default => false + optional ::Google::Protobuf::MethodOptions::IdempotencyLevel, :idempotency_level, 34, :default => ::Google::Protobuf::MethodOptions::IdempotencyLevel::IDEMPOTENCY_UNKNOWN + repeated ::Google::Protobuf::UninterpretedOption, :uninterpreted_option, 999 + # Extension Fields + extensions 1000...536870912 + end + + class UninterpretedOption + class NamePart + required :string, :name_part, 1 + required :bool, :is_extension, 2 + end + + repeated ::Google::Protobuf::UninterpretedOption::NamePart, :name, 2 + optional :string, :identifier_value, 3 + optional :uint64, :positive_int_value, 4 + optional :int64, :negative_int_value, 5 + optional :double, :double_value, 6 + optional :bytes, :string_value, 7 + optional :string, :aggregate_value, 8 + end + + class SourceCodeInfo + class Location + repeated :int32, :path, 1, :packed => true + repeated :int32, :span, 2, :packed => true + optional :string, :leading_comments, 3 + optional :string, :trailing_comments, 4 + repeated :string, :leading_detached_comments, 6 + end + + repeated ::Google::Protobuf::SourceCodeInfo::Location, :location, 1 + end + + class GeneratedCodeInfo + class Annotation + repeated :int32, :path, 1, :packed => true + optional :string, :source_file, 2 + optional :int32, :begin, 3 + optional :int32, :end, 4 + end + + repeated ::Google::Protobuf::GeneratedCodeInfo::Annotation, :annotation, 1 + end + + end + +end + diff --git a/spec/support/protos/map-test.bin b/spec/support/protos/map-test.bin index 5f6e02c3..97ad6500 100644 Binary files a/spec/support/protos/map-test.bin and b/spec/support/protos/map-test.bin differ diff --git a/spec/support/protos/map-test.pb.rb b/spec/support/protos/map-test.pb.rb index bd856360..849bad87 100644 --- a/spec/support/protos/map-test.pb.rb +++ b/spec/support/protos/map-test.pb.rb @@ -12,8 +12,8 @@ module Foo # Enum Classes # class Frobnitz < ::Protobuf::Enum - define :FROB, 1 - define :NITZ, 2 + define :FROB, 0 + define :NITZ, 1 end diff --git a/spec/support/protos/map-test.proto b/spec/support/protos/map-test.proto index 6f7f221d..447c651d 100644 --- a/spec/support/protos/map-test.proto +++ b/spec/support/protos/map-test.proto @@ -1,13 +1,13 @@ // Use protoc v3.0.0 to compile this file into map-test.bin: -// protoc --descriptor_set_out=map-test.bin map-test.proto +// protoc --descriptor_set_out=map-test.bin map-test.proto syntax = "proto2"; package foo; enum Frobnitz { - FROB = 1; - NITZ = 2; + FROB = 0; + NITZ = 1; } message Baz { diff --git a/spec/support/protos/optional_v3_fields.pb.rb b/spec/support/protos/optional_v3_fields.pb.rb new file mode 100644 index 00000000..058f37ff --- /dev/null +++ b/spec/support/protos/optional_v3_fields.pb.rb @@ -0,0 +1,22 @@ +# encoding: utf-8 + +## +# This file is auto-generated. DO NOT EDIT! +# +require 'protobuf' + + +## +# Message Classes +# +class SomethingWithOptionalFields < ::Protobuf::Message; end + + +## +# Message Fields +# +class SomethingWithOptionalFields + optional :string, :i_am_optional, 1 + optional :string, :i_am_not_optional, 2 +end + diff --git a/spec/support/protos/optional_v3_fields.proto b/spec/support/protos/optional_v3_fields.proto new file mode 100644 index 00000000..b145fba2 --- /dev/null +++ b/spec/support/protos/optional_v3_fields.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; + +message SomethingWithOptionalFields { + optional string i_am_optional = 1; + string i_am_not_optional = 2; +} diff --git a/spec/support/server.rb b/spec/support/server.rb index 8a0203b6..16fc5678 100644 --- a/spec/support/server.rb +++ b/spec/support/server.rb @@ -1,5 +1,6 @@ require 'ostruct' +require 'active_support' require 'active_support/core_ext/hash/reverse_merge' require 'spec_helper' diff --git a/varint_prof.rb b/varint_prof.rb index 056a1d96..ddd9abbb 100644 --- a/varint_prof.rb +++ b/varint_prof.rb @@ -52,19 +52,31 @@ printer.printProfile(STDOUT) else TO_HASH = ::Test::Resource.new(:name => "derp", :date_created => 123456789) + ENCODE = ::Test::Resource.new(:name => "derp", :date_created => 123456789) + DECODE = begin + ss = StringIO.new + ::Protobuf::Encoder.encode(ENCODE.to_proto, ss) + ss.rewind + ss.string + end + Benchmark.ips do |x| x.config(:time => 20, :warmup => 10) - x.report("to_hash => true java") do + x.report("to_hash") do TO_HASH.to_hash end - x.report("to_proto => true java") do - t = ::Test::Resource.new(:name => "derp", :date_created => 123456789) - t.status = 3 + x.report("to_hash_with_string_keys") do + TO_HASH.to_hash_with_string_keys + end + + x.report("encode") do ss = StringIO.new - ::Protobuf::Encoder.encode(t.to_proto, ss) - ss.rewind - t2 = ::Test::Resource.decode_from(ss) + ::Protobuf::Encoder.encode(ENCODE.to_proto, ss) + end + + x.report("decode") do + ::Test::Resource.decode_from(::StringIO.new(DECODE.dup)) end end end
%Total
100% 0%63.22123.51 0.0063.22123.51 0 (top)
60.08120.19 0.0060.08120.19 1/1 Benchmark::IPS.ips
1.051.03 0.001.051.02 2/115 Kernel.require
0.910.000.916/1886Kernel.require0.040.871/5##times
0.650.040.611/5##times0.870.000.876/1883Kernel.require
0.520.50 0.060.460.44 17/19 Kernel.load
0.120.000.121/1292879Gem::Specification.each_gemspec0.910.040.871/5(top)
0.23120.19 0.000.2219/1292879Kernel.require120.192/5Benchmark::IPS::Job#run
20.001.7718.241/1292879Benchmark::IPS::Job#run_warmup
98%0%121.120.05121.075##times
40.080.0140.071/129287980.180.0080.181/1 Benchmark::IPS::Job#run_benchmark
96%2%60.851.8159.041292879##each
40.000.0040.001/1Benchmark::IPS::Job#run_warmup
57.023.0653.963681351/3681351Benchmark::IPS::Job::Entry#call_times0.450.010.4410000/2123384Protobuf::Message::Serialization::ClassMethods.decode_from
0.950.470.493681900/3681900Benchmark::Timing.now0.280.010.2710000/4103921Protobuf::Encoder.encode
0.170.170.12 0.003681355/3681355##<0.121/4105546Gem::Specification.each_gemspec
0.140.140.003681365/18790704##+0.250.010.2419/4105546Kernel.require
0.650.040.611/5(top)40.003.5136.491/4105546Benchmark::IPS::Job#run_warmup
60.080.0060.082/5Benchmark::IPS::Job#run80.180.0280.171/4105546Benchmark::IPS::Job#run_benchmark
96%0%60.760.0660.705##times97%2%120.963.56117.404105546##each
40.080.0040.081/1Benchmark::IPS::Job#run_benchmark114.335.40108.926794724/6794724Benchmark::IPS::Job::Entry#call_times
20.000.0020.001/1Benchmark::IPS::Job#run_warmup1.670.810.866795778/6795778Benchmark::Timing.now
0.290.340.34 0.000.2810000/1291320Protobuf::Message::Serialization::ClassMethods.decode_from6794732/6794732##<
0.190.010.1810000/1291320Protobuf::Encoder.encode0.300.300.006794740/46949692##+
60.08120.19 0.0060.08120.19 1/1 (top)
95%97% 0%60.08120.19 0.0060.08120.19 1 Benchmark::IPS.ips
60.08120.19 0.0060.08120.19 1/1 Benchmark::IPS::Job#run
60.08120.19 0.0060.08120.19 1/1 Benchmark::IPS.ips
95%97% 0%60.08120.19 0.0060.08120.19 1 Benchmark::IPS::Job#run
60.08120.19 0.0060.08120.19 2/5##times##times
57.023.0653.963681351/3681351##each114.335.40108.926794724/6794724##each
90%92% 4%57.023.0653.963681351114.335.40108.926794724 Benchmark::IPS::Job::Entry#call_times
52.582.3150.2615108256/15108804106.564.94101.6225271252/25271834 Proc#call
0.710.711.281.28 0.0018789607/18789624##<32065976/32065992##<
0.670.671.081.08 0.0015108256/18790704##+25271252/46949692##+
52.582.3150.2615108256/15108804106.564.94101.6225271252/25271834 Benchmark::IPS::Job::Entry#call_times
83%3%52.612.3250.291510880486%4%106.604.95101.6425271834 Proc#call
22.112.3719.7413826936/13826936Protobuf::Message#to_hash
12.920.3312.591281320/129132027.520.4627.062113384/2123384 Protobuf::Message::Serialization::ClassMethods.decode_from
9.100.358.751281320/129132025.390.8124.584093920/4103921 Protobuf::Encoder.encode
3.530.173.361281320/2584164Class#new23.631.9021.739393746/9393746Protobuf::Message#to_hash_with_string_keys
2.170.311.871281320/1291320Test::Resource#status=23.521.9321.609670202/9670202Protobuf::Message#to_hash
0.280.170.111281320/12913201.060.700.376207304/6217305 StringIO.new
0.110.110.320.32 0.001281320/12913204093920/4103921 Protobuf::Message#to_proto
0.180.180.002113384/4247921Kernel.dup
40.0880.18 0.0040.0880.18 1/1##times##times
63%64% 0%40.0880.18 0.0040.0880.18 1 Benchmark::IPS::Job#run_benchmark
40.080.0140.071/1292879##each
8.231.646.601291320/15118257Protobuf::Message#each_field_for_serialization80.180.0280.171/4105546##each
19.745.9313.8113826936/1511825721.604.5317.069670202/23167870 Protobuf::Message#to_hash
44%11%27.987.5720.4115118257##each_key
5.462.323.1513826936/13826936Protobuf::Field::StringField(singleton)#to_message_hash
5.342.273.0613826936/13826936Protobuf::Field::Int64Field(singleton)#to_message_hash
2.300.741.571291320/1291320Protobuf::Field::StringField(singleton)#encode_to_stream
1.991.990.0031527832/73391217##[]21.734.3317.399393746/23167870Protobuf::Message#to_hash_with_string_keys
1.551.550.0031527832/39275754Test::Resource#_protobuf_message_field22.783.5319.244103921/23167870Protobuf::Message#each_field_for_serialization
1.440.321.121291320/1291320Protobuf::Field::EnumField(singleton)#encode_to_stream
53%10%66.1012.4053.7023167870##each_key
1.180.320.861291320/1291320Protobuf::Field::Int64Field(singleton)#encode_to_stream15.223.2511.9618787492/18787492Protobuf::Field::BaseField#to_message_hash_with_string_key
0.410.110.301291320/16409576Protobuf::Field::StringField(singleton)#value_from_values14.753.3011.4519340404/19340404Protobuf::Field::BaseField#to_message_hash
0.370.110.271291320/2582640Protobuf::Field::EnumField(singleton)#value_from_values14.731.6313.118217842/8217842Protobuf::Field::BaseField#encode_to_stream
0.360.110.261291320/16409576Protobuf::Field::Int64Field(singleton)#value_from_values3.341.691.668217842/8217842Protobuf::Field::BaseField#value_from_values_for_serialization
22.112.3719.7413826936/13826936Proc#call
34%3%22.112.3719.7413826936Protobuf::Message#to_hash3.203.200.0046345738/97013401##[]
19.745.9313.8113826936/15118257##each_key2.462.460.0046345738/50632510Test::Resource#_protobuf_message_field
20.0040.00 0.0020.0040.00 1/1##times##times
31%32% 0%20.0040.00 0.0020.0040.00 1 Benchmark::IPS::Job#run_warmup
20.001.7718.241/1292879##each40.003.5136.491/4105546##each
0.290.000.2810000/1291320##times0.450.010.4410000/2123384##times
12.920.3312.591281320/129132027.520.4627.062113384/2123384 Proc#call
20%22% 0%13.200.3312.87129132027.960.4627.502123384 Protobuf::Message::Serialization::ClassMethods.decode_from
12.110.3211.781291320/129132026.260.4325.832123384/2123384 Protobuf::Message::Serialization.decode_from
0.760.170.591291320/25841641.240.310.942123384/2136384 Class#new
12.110.3211.781291320/129132026.260.4325.832123384/2123384 Protobuf::Message::Serialization::ClassMethods.decode_from
19%21% 0%12.110.3211.78129132026.260.4325.832123384 Protobuf::Message::Serialization.decode_from
11.782.059.741291320/129132025.832.3923.442123384/2123384 Protobuf::Decoder.decode_each_field
11.782.059.741291320/129132025.832.3923.442123384/2123384 Protobuf::Message::Serialization.decode_from
18%3%11.782.059.74129132020%1%25.832.3923.442123384 Protobuf::Decoder.decode_each_field
7.401.166.243873960/3873960Protobuf::Message::Serialization.set_field_bytes11.705.835.888513536/8513536ProtobufJavaHelpers::EncodeDecode.decode
1.420.850.577747920/7747920Protobuf::Varint.decode10.641.419.234256768/4256768Protobuf::Message::Serialization.set_field_bytes
0.240.240.310.31 0.005165280/51652806380152/6380152 StringIO#eof
0.200.200.250.25 0.005165280/5168510##==6380152/6383519##==
0.170.170.230.23 0.003873960/3873960##>>2123384/2123384StringIO#read
0.170.170.180.18 0.003873960/3873960##&4256768/4256768##>>
0.130.130.120.12 0.001291320/1291320StringIO#read4256768/40271449##&
0.190.28 0.010.1810000/1291320##times0.2710000/4103921##times
9.100.358.751281320/129132025.390.8124.584093920/4103921 Proc#call
14%20% 0%9.280.368.93129132025.670.8224.854103921 Protobuf::Encoder.encode
8.930.458.481291320/129132024.851.3223.524103921/4103921 Protobuf::Message#each_field_for_serialization
8.930.458.481291320/129132024.851.3223.524103921/4103921 Protobuf::Encoder.encode
14%0%8.930.458.48129132020%1%24.851.3223.524103921 Protobuf::Message#each_field_for_serialization
8.231.646.601291320/15118257##each_key22.783.5319.244103921/23167870##each_key
0.180.180.560.56 0.001291320/3873961Test::Resource#_protobuf_message_required_field_tags4103921/6237307Test::Resource#_protobuf_message_unset_required_field_tags
0.690.170.521291320/7747922Protobuf::Field::Int64Field(singleton)#set23.631.9021.739393746/9393746Proc#call
19%1%23.631.9021.739393746Protobuf::Message#to_hash_with_string_keys
1.340.191.151291320/7747922Protobuf::Field::StringField(singleton)#set21.734.3317.399393746/23167870##each_key
1.730.161.571291320/7747922Protobuf::Field::EnumField(singleton)#set23.521.9321.609670202/9670202Proc#call
19%1%23.521.9321.609670202Protobuf::Message#to_hash
1.890.311.591291320/7747922Test::Resource#status=21.604.5317.069670202/23167870##each_key
2.570.641.932582642/7747922##each15.223.2511.9618787492/18787492##each_key
13%12% 2%8.221.476.757747922Protobuf::Message#set_field
2.980.602.392582640/2582640Protobuf::Field::EnumField(singleton)#set_field15.223.2511.9618787492Protobuf::Field::BaseField#to_message_hash_with_string_key
2.210.941.272582641/2582641Protobuf::Field::StringField(singleton)#set_field11.963.658.3118787492/18787492Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHashWithStringKey#call
0.970.600.372582641/2582641Protobuf::Field::Int64Field(singleton)#set_field14.753.3011.4519340404/19340404##each_key
0.320.320.003873962/73391217##[]
11%2%14.753.3011.4519340404Protobuf::Field::BaseField#to_message_hash
0.260.260.003873962/39275754Test::Resource#_protobuf_message_field11.453.647.8219340404/19340404Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHash#call
7.401.166.243873960/3873960Protobuf::Decoder.decode_each_field14.731.6313.118217842/8217842##each_key
11% 1%7.401.166.243873960Protobuf::Message::Serialization.set_field_bytes14.731.6313.118217842Protobuf::Field::BaseField#encode_to_stream
2.250.271.971291320/1291320Protobuf::Field::EnumField(singleton)#set7.092.095.004103921/4103921Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
2.120.281.851291320/1291320Protobuf::Field::StringField(singleton)#set6.021.034.994113921/4113921Protobuf::Field::BaseFieldObjectDefinitions::BaseEncodeToStream#call
1.240.270.971291320/1291320Protobuf::Field::Int64Field(singleton)#set6.273.133.1418787492/38127896Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHashWithStringKey#call
0.340.340.003873960/73391217##[]6.453.193.2619340404/38127896Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHash#call
10%5%12.726.326.4038127896Protobuf::Field::BaseField#value_from_values
0.290.290.003873960/39275754Test::Resource#_protobuf_message_field6.404.142.2638127896/38127896Protobuf::Field::BaseFieldObjectDefinitions::BaseFieldValueFromValues#call
5.462.323.1513826936/13826936##each_key11.963.658.3118787492/18787492Protobuf::Field::BaseField#to_message_hash_with_string_key
8%3%5.462.323.1513826936Protobuf::Field::StringField(singleton)#to_message_hash9%2%11.963.658.3118787492Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHashWithStringKey#call
2.341.660.6813826936/16409576Protobuf::Field::StringField(singleton)#value_from_values6.273.133.1418787492/38127896Protobuf::Field::BaseField#value_from_values
0.810.812.042.04 0.0013826936/35406351##[]=18787492/42419312##[]=
5.342.273.0613826936/13826936##each_key11.705.835.888513536/8513536Protobuf::Decoder.decode_each_field
8%3%5.342.273.0613826936Protobuf::Field::Int64Field(singleton)#to_message_hash9%4%11.705.835.888513536ProtobufJavaHelpers::EncodeDecode.decode
2.241.590.6513826936/16409576Protobuf::Field::Int64Field(singleton)#value_from_values2.041.380.6614883688/14883688IO::GenericReadable.readbyte
0.820.821.001.00 0.0013826936/35406351##[]=29767376/40271449##&
0.100.020.0816/2584164Kernel.eval0.590.590.0014883688/17017539Numeric#nonzero?
0.170.010.16153/2584164Protobuf::Field.build0.580.580.0014883688/14883841##<<
0.300.010.291/2584164Bundler::Dsl#to_definition0.560.560.0014883688/46949692##+
0.760.170.591291320/2584164Protobuf::Message::Serialization::ClassMethods.decode_from0.560.560.0014883688/14883841##|
3.530.173.361281320/2584164Proc#call
8%0%5.120.464.662584164Class#new0.540.540.0014883688/14884832##*
4.020.813.212582641/2582641Protobuf::Message#initialize11.453.647.8219340404/19340404Protobuf::Field::BaseField#to_message_hash
0.290.000.291/1Bundler::Definition#initialize
9%2%11.453.647.8219340404Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHash#call
0.160.010.15153/153Protobuf::Field::BaseField#initialize6.453.193.2619340404/38127896Protobuf::Field::BaseField#value_from_values
0.150.151.371.37 0.002582640/73391217Protobuf::Enum.enum_for_tag_integer19340404/42419312##[]=
0.320.320.003873962/73391217Protobuf::Message#set_field10.641.419.234256768/4256768Protobuf::Decoder.decode_each_field
8%1%10.641.419.234256768Protobuf::Message::Serialization.set_field_bytes
0.340.340.003873960/73391217Protobuf::Message::Serialization.set_field_bytes8.480.877.604256768/4256768Protobuf::Field::BaseField#set
0.720.720.420.42 0.0015118256/73391217Protobuf::Field::Int64Field(singleton)#value_from_values4256768/97013401##[]
0.760.760.330.33 0.0015118256/73391217Protobuf::Field::StringField(singleton)#value_from_values4256768/50632510Test::Resource#_protobuf_message_field
1.991.990.0031527832/73391217##each_key8.480.877.604256768/4256768Protobuf::Message::Serialization.set_field_bytes
6%6%4.404.370.0373391217##[]0%8.480.877.604256768Protobuf::Field::BaseField#set
7.601.026.584256768/4256768Protobuf::Field::BaseFieldObjectDefinitions::BaseSetMethod#call
4.020.813.212582641/2582641Class#new7.601.026.584256768/4256768Protobuf::Field::BaseField#set
6%1%4.020.813.212582641Protobuf::Message#initialize0%7.601.026.584256768Protobuf::Field::BaseFieldObjectDefinitions::BaseSetMethod#call
3.000.432.572582641/2582855##each5.010.624.394256768/4286772Protobuf::Message#set_field
0.110.110.002582641/2582814Kernel.block_given?1.080.780.302123384/2123384Protobuf::Field::IntegerField#decode
0.110.110.002582641/2582642##to_hash0.460.300.162123384/2123384Protobuf::Field::StringField#decode
3.000.432.572582641/2582855Protobuf::Message#initialize7.092.095.004103921/4103921Protobuf::Field::BaseField#encode_to_stream
4%0%3.020.442.582582855##each5%1%7.092.095.004103921Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
2.570.641.932582642/7747922Protobuf::Message#set_field2.361.201.1612311763/20539605IO::GenericWritable.<<
2.980.602.392582640/2582640Protobuf::Message#set_field1.410.530.884103921/8217995Protobuf::Field::VarintField.encode
4%0%2.980.602.392582640Protobuf::Field::EnumField(singleton)#set_field
0.580.400.184103921/4104743BasicObject#!=
2.110.491.622582640/2582640Protobuf::Field::EnumField#coerce!0.280.280.004103921/4104065##+
0.170.170.210.21 0.002582640/35406351##[]=4103921/4103921##encoding
0.410.110.301291320/16409576##each_key0.170.170.004103921/4103921##bytesize
2.341.660.6813826936/16409576Protobuf::Field::StringField(singleton)#to_message_hash6.404.142.2638127896/38127896Protobuf::Field::BaseField#value_from_values
4%2%2.751.770.9816409576Protobuf::Field::StringField(singleton)#value_from_values5%3%6.404.142.2638127896Protobuf::Field::BaseFieldObjectDefinitions::BaseFieldValueFromValues#call
0.760.762.262.26 0.0015118256/73391217##[]38127896/97013401##[]
0.360.110.261291320/16409576##each_key0.420.420.004256768/97013401Protobuf::Message::Serialization.set_field_bytes
2.241.590.6513826936/16409576Protobuf::Field::Int64Field(singleton)#to_message_hash
4%2%2.611.700.9116409576Protobuf::Field::Int64Field(singleton)#value_from_values
0.720.720.480.48 0.0015118256/73391217##[]
0.420.030.392/1886Kernel.load8217842/97013401Protobuf::Field::BaseFieldObjectDefinitions::BaseFieldValueFromValuesForSerialization#call
0.912.262.26 0.000.916/1886(top)38127896/97013401Protobuf::Field::BaseFieldObjectDefinitions::BaseFieldValueFromValues#call
1.053.203.20 0.001.05115/1886Kernel.require46345738/97013401##each_key
3%0%2.375%5%6.396.36 0.032.341886Kernel.require97013401##[]
0.880.000.881/1Bundler.setup6.021.034.994113921/4113921Protobuf::Field::BaseField#encode_to_stream
0.230.000.2219/1292879##each
4%0%6.021.034.994113921Protobuf::Field::BaseFieldObjectDefinitions::BaseEncodeToStream#call
0.130.000.131/1Gem::Specification.load_defaults3.351.481.864103921/4103921Protobuf::Field::IntegerField#encode
0.120.000.12109/109Protobuf::Message::Fields::ClassMethods.optional1.610.800.818227842/20539605IO::GenericWritable.<<
2.300.741.571291320/1291320##each_key5.010.624.394256768/4286772Protobuf::Field::BaseFieldObjectDefinitions::BaseSetMethod#call
3%1%2.300.741.571291320Protobuf::Field::StringField(singleton)#encode_to_stream
0.740.350.393873960/9039240IO::GenericWritable.<<
0.340.220.121291320/1291473Protobuf::Field::VarintField.encode
0.240.170.071291320/1292131BasicObject#!=4%0%5.100.634.474286772Protobuf::Message#set_field
0.120.120.001291320/2582782##+4.460.903.564286772/4286772Protobuf::Field::BaseField#set_field
2.250.271.971291320/1291320Protobuf::Message::Serialization.set_field_bytes4.460.903.564286772/4286772Protobuf::Message#set_field
3% 0%2.250.271.971291320Protobuf::Field::EnumField(singleton)#set4.460.903.564286772Protobuf::Field::BaseField#set_field
1.730.161.571291320/7747922Protobuf::Message#set_field1.780.571.212153386/2153386Protobuf::Field::BaseFieldObjectDefinitions::BaseSetField#call
0.240.190.051291320/1291320Protobuf::Field::EnumField#decode1.780.691.092133386/2133386Protobuf::Field::BaseFieldObjectDefinitions::RequiredStringSetField#call
2.170.311.871281320/1291320Proc#call
3%0%2.210.321.891291320Test::Resource#status=
1.890.311.591291320/7747922Protobuf::Message#set_field1.610.800.818227842/20539605Protobuf::Field::BaseFieldObjectDefinitions::BaseEncodeToStream#call
2.210.941.272582641/2582641Protobuf::Message#set_field2.361.201.1612311763/20539605Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
3% 1%2.210.941.272582641Protobuf::Field::StringField(singleton)#set_field
0.680.530.152582641/3873961Test::Resource#_protobuf_message_required_field_tags
0.200.200.002582641/2582825##delete
0.180.180.002582641/35406351##[]=
0.100.100.002582641/7748887Kernel.nil?3.972.001.9720539605IO::GenericWritable.<<
0.100.101.971.97 0.002582641/2583806##to_s20539605/20539605StringIO#write
0.160.160.002582641/35406351Protobuf::Field::Int64Field(singleton)#set_field
0.170.170.180.18 0.002582640/35406351Protobuf::Field::EnumField(singleton)#set_field2153386/42419312Protobuf::Field::BaseFieldObjectDefinitions::BaseSetField#call
0.180.180.200.20 0.002582641/35406351Protobuf::Field::StringField(singleton)#set_field2133386/42419312Protobuf::Field::BaseFieldObjectDefinitions::RequiredStringSetField#call
0.810.811.371.37 0.0013826936/35406351Protobuf::Field::StringField(singleton)#to_message_hash19340404/42419312Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHash#call
0.820.822.042.04 0.0013826936/35406351Protobuf::Field::Int64Field(singleton)#to_message_hash18787492/42419312Protobuf::Field::BaseFieldObjectDefinitions::BaseToMessageHashWithStringKey#call
3% 3%2.152.143.803.79 0.0135406351##[]=42419312##[]=
2.120.281.851291320/1291320Protobuf::Message::Serialization.set_field_bytes3.351.481.864103921/4103921Protobuf::Field::BaseFieldObjectDefinitions::BaseEncodeToStream#call
3%0%2.120.281.851291320Protobuf::Field::StringField(singleton)#set2%1%3.351.481.864103921Protobuf::Field::IntegerField#encode
1.340.191.151291320/7747922Protobuf::Message#set_field1.450.500.954103921/8217995Protobuf::Field::VarintField.encode
0.500.300.201291320/1291320Protobuf::Field::StringField#decode0.410.410.004103921/40271449##&
2.110.491.622582640/2582640Protobuf::Field::EnumField(singleton)#set_field3.341.691.668217842/8217842##each_key
3%0%2.110.491.622582640Protobuf::Field::EnumField#coerce!2%1%3.341.691.668217842Protobuf::Field::BaseField#value_from_values_for_serialization
1.380.460.922582640/2582649Protobuf::Enum.fetch1.661.180.488217842/8217842Protobuf::Field::BaseFieldObjectDefinitions::BaseFieldValueFromValuesForSerialization#call
0.240.240.002582640/2583314Protobuf::Field::BaseField#type_class1.410.530.884103921/8217995Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
0.260.260.003873962/39275754Protobuf::Message#set_field1.450.500.954103921/8217995Protobuf::Field::IntegerField#encode
2%0%2.871.031.848217995Protobuf::Field::VarintField.encode
1.840.930.918217995/8217995ProtobufJavaHelpers::EncodeDecode.encode
0.290.290.330.33 0.003873960/392757544256768/50632510 Protobuf::Message::Serialization.set_field_bytes
1.551.552.462.46 0.0031527832/39275754##each_key46345738/50632510##each_key
3%3%2.092.092%2%2.792.79 0.003927575450632510 Test::Resource#_protobuf_message_field
0.440.230.212582640/9039240Protobuf::Field::EnumField(singleton)#encode_to_stream0.410.030.382/1883Kernel.load
0.480.230.252582640/9039240Protobuf::Field::Int64Field(singleton)#encode_to_stream0.870.000.876/1883(top)
0.740.350.393873960/9039240Protobuf::Field::StringField(singleton)#encode_to_stream1.020.001.02115/1883Kernel.require
2% 1%1.670.820.859039240IO::GenericWritable.<<0%2.300.032.271883Kernel.require
0.850.850.86 0.009039240/9039240StringIO#write0.861/1Bundler.setup
1.440.321.121291320/1291320##each_key
2%0%1.440.321.121291320Protobuf::Field::EnumField(singleton)#encode_to_stream0.250.010.2419/4105546##each
0.680.270.421291320/1291320Protobuf::Field::EnumField#encode0.120.000.121/1Gem::Specification.load_defaults
0.440.230.212582640/9039240IO::GenericWritable.<<0.280.010.271/2136384Bundler::Dsl#to_definition
1.420.850.577747920/7747920Protobuf::Decoder.decode_each_field1.240.310.942123384/2136384Protobuf::Message::Serialization::ClassMethods.decode_from
2% 1%1.420.850.577747920Protobuf::Varint.decode0%2.060.501.562136384Class#new
0.570.571.020.690.342133386/2133386Protobuf::Message#initialize
0.27 0.007747920/7747920ProtobufJavaHelpers::Varinter.read_varint0.271/1Bundler::Definition#initialize
2.04 1.380.460.922582640/2582649Protobuf::Field::EnumField#coerce!0.6614883688/14883688ProtobufJavaHelpers::EncodeDecode.decode
2%0%1%1%2.04 1.380.460.922582649Protobuf::Enum.fetch0.6614883688IO::GenericReadable.readbyte
0.780.510.282582640/2582640Protobuf::Enum.enum_for_tag_integer
0.140.140.660.66 0.002582649/2584139Kernel.kind_of?14883688/14883688StringIO#getbyte
1.240.270.971291320/1291320Protobuf::Message::Serialization.set_field_bytes1.971.970.0020539605/20539605IO::GenericWritable.<<
1%0%1.240.270.971291320Protobuf::Field::Int64Field(singleton)#set1%1.971.970.0020539605StringIO#write
0.690.170.521291320/7747922Protobuf::Message#set_field0.300.300.006794740/46949692##each
0.280.220.061291320/1291320Protobuf::Field::Int64Field#decode0.560.560.0014883688/46949692ProtobufJavaHelpers::EncodeDecode.decode
1.180.320.861291320/1291320##each_key1.081.080.0025271252/46949692Benchmark::IPS::Job::Entry#call_times
1%0%1.180.320.861291320Protobuf::Field::Int64Field(singleton)#encode_to_stream1%1.941.940.0046949692##+
0.480.230.252582640/9039240IO::GenericWritable.<<1.840.930.918217995/8217995Protobuf::Field::VarintField.encode
1%0%1.840.930.918217995ProtobufJavaHelpers::EncodeDecode.encode
0.380.240.141291320/1291320Protobuf::Field::Int64Field#encode0.910.910.008217995/8217995ProtobufJavaHelpers::Varinter.to_varint
1.050.001.052/115(top)1.780.571.212153386/2153386Protobuf::Field::BaseField#set_field
1% 0%1.050.001.05115Kernel.require1.780.571.212153386Protobuf::Field::BaseFieldObjectDefinitions::BaseSetField#call
0.920.630.292133386/2133386Protobuf::Field::VarintField#coerce!
1.050.180.18 0.001.05115/1886Kernel.require2153386/42419312##[]=
0.970.600.372582641/2582641Protobuf::Message#set_field1.780.691.092133386/2133386Protobuf::Field::BaseField#set_field
1% 0%0.970.600.372582641Protobuf::Field::Int64Field(singleton)#set_field1.780.691.092133386Protobuf::Field::BaseFieldObjectDefinitions::RequiredStringSetField#call
0.160.160.002582641/35406351##[]=0.610.430.182133386/6237307Test::Resource#_protobuf_message_unset_required_field_tags
0.110.110.200.20 0.002582641/2582641ProtobufJavaHelpers::Int64ProtobufField.coerce!2133386/42419312##[]=
0.100.100.160.16 0.002582641/7748887Kernel.nil?2133386/2133570##delete
0.950.470.493681900/3681900##each
1%0%0.950.470.493681900Benchmark::Timing.now
0.490.490.120.12 0.003681900/3681901Process.clock_gettime2133386/4298337Kernel.kind_of?
0.880.000.881/1Kernel.require
1%0%0.880.120.12 0.000.881Bundler.setup4256768/40271449Protobuf::Decoder.decode_each_field
0.520.010.511/2Bundler.definition0.210.210.002123384/40271449Protobuf::Field::IntegerField#decode
0.350.410.41 0.000.351/1Bundler::Runtime#setup4103921/40271449Protobuf::Field::IntegerField#encode
0.180.181.001.00 0.001291320/3873961Protobuf::Message#each_field_for_serialization29767376/40271449ProtobufJavaHelpers::EncodeDecode.decode
1%1%1.761.760.0040271449##&
0.680.530.152582641/3873961Protobuf::Field::StringField(singleton)#set_field1.670.810.866795778/6795778##each
1%1%0%1.670.81 0.860.710.153873961Test::Resource#_protobuf_message_required_field_tags6795778Benchmark::Timing.now
0.150.150.860.86 0.002582641/2583673Kernel.dup6795778/6795779Process.clock_gettime
0.850.850.009039240/9039240IO::GenericWritable.<<1.661.180.488217842/8217842Protobuf::Field::BaseField#value_from_values_for_serialization
1%1%0.850.850.009039240StringIO#write0%1.661.180.488217842Protobuf::Field::BaseFieldObjectDefinitions::BaseFieldValueFromValuesForSerialization#call
0.140.140.480.48 0.003681365/18790704##each8217842/97013401##[]
0.670.671.281.28 0.0015108256/1879070432065976/32065992 Benchmark::IPS::Job::Entry#call_times
1% 1%0.810.811.281.28 0.0018790704##+32065992##<
0.780.510.282582640/2582640Protobuf::Enum.fetch0.560.560.004103921/6237307Protobuf::Message#each_field_for_serialization
1%0%0.780.510.282582640Protobuf::Enum.enum_for_tag_integer
0.150.150.002582640/73391217##[]0.610.430.182133386/6237307Protobuf::Field::BaseFieldObjectDefinitions::RequiredStringSetField#call
0%0%1.181.000.186237307Test::Resource#_protobuf_message_unset_required_field_tags
0.130.130.180.18 0.002582640/2583129##first2133386/4247921Kernel.dup
0.710.710.0018789607/18789624Benchmark::IPS::Job::Entry#call_times1.080.780.302123384/2123384Protobuf::Field::BaseFieldObjectDefinitions::BaseSetMethod#call
1%1%0.710.710%0%1.080.780.302123384Protobuf::Field::IntegerField#decode
0.210.21 0.0018789624##<2123384/40271449##&
0.680.270.421291320/1291320Protobuf::Field::EnumField(singleton)#encode_to_stream1.060.700.376207304/6217305Proc#call
1% 0%0.680.270.421291320Protobuf::Field::EnumField#encode
0.310.180.141291320/1291588Protobuf::Enum#to_i0%1.070.700.376217305StringIO.new
0.100.100.370.37 0.001291320/2582640ProtobufJavaHelpers::Varinter.to_varint_646217305/6217305StringIO#initialize
0.570.571.03 0.007747920/7747920Protobuf::Varint.decode1.022/115(top)
0% 0%0.570.571.03 0.007747920ProtobufJavaHelpers::Varinter.read_varint1.02115Kernel.require
1.020.001.02115/1883Kernel.require
0.520.060.4617/19(top)1.020.690.342133386/2133386Class#new
0% 0%0.520.060.4619Kernel.load1.020.690.342133386Protobuf::Message#initialize
0.420.030.392/1886Kernel.require0.160.100.062133386/2133600##each
0.520.010.511/2Bundler.setup0.920.630.292133386/2133386Protobuf::Field::BaseFieldObjectDefinitions::BaseSetField#call
0% 0%0.520.010.512Bundler.definition0.920.630.292133386Protobuf::Field::VarintField#coerce!
0.420.110.11 0.000.421/1Bundler::Definition.build2133386/4298337Kernel.kind_of?
0.500.300.201291320/1291320Protobuf::Field::StringField(singleton)#set0.910.910.008217995/8217995ProtobufJavaHelpers::EncodeDecode.encode
0% 0%0.500.300.201291320Protobuf::Field::StringField#decode
0.130.130.910.91 0.001291320/2582782##+8217995ProtobufJavaHelpers::Varinter.to_varint
0.490.490.860.86 0.003681900/36819016795778/6795779 Benchmark::Timing.now
0% 0%0.490.490.860.86 0.0036819016795779 Process.clock_gettime
0.420.86 0.000.420.86 1/1Bundler.definitionKernel.require
0% 0%0.420.86 0.000.420.86 1Bundler::Definition.buildBundler.setup
0.400.480.010.481/2Bundler.definition
0.37 0.000.400.37 1/1Bundler::Dsl.evaluateBundler::Runtime#setup
0.330.590.59 0.000.331/873Bundler::Runtime#requested_specs14883688/17017539ProtobufJavaHelpers::EncodeDecode.decode
0% 0%0.410.680.68 0.000.41873Kernel.send17017539Numeric#nonzero?
0.330.660.66 0.000.331/1Bundler::Definition#requested_specs14883688/14883688IO::GenericReadable.readbyte
0%0%0.660.660.0014883688StringIO#getbyte
0.58 0.400.000.401/1Bundler::Definition.build0.184103921/4104743Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
0% 0%0.59 0.400.000.401Bundler::Dsl.evaluate0.184104743BasicObject#!=
0.300.180.18 0.000.301/1Bundler::Dsl#to_definition4104167/4104503BasicObject#==
0.380.240.141291320/1291320Protobuf::Field::Int64Field(singleton)#encode_to_stream0.580.580.0014883688/14883841ProtobufJavaHelpers::EncodeDecode.decode
0% 0%0.380.240.141291320Protobuf::Field::Int64Field#encode
0.140.140.580.58 0.001291320/2582640ProtobufJavaHelpers::Varinter.to_varint_6414883841##<<
0.370.110.271291320/2582640##each_key0.560.560.0014883688/14883841ProtobufJavaHelpers::EncodeDecode.decode
0% 0%0.370.110.272582640Protobuf::Field::EnumField(singleton)#value_from_values0.560.560.0014883841##|
0.350.540.54 0.000.351/1Bundler.setup14883688/14884832ProtobufJavaHelpers::EncodeDecode.decode
0% 0%0.350.000.351Bundler::Runtime#setup
0.330.540.54 0.000.331/1Bundler::Runtime#requested_specs14884832##*
0.340.220.121291320/1291473Protobuf::Field::StringField(singleton)#encode_to_stream0.500.060.4417/19(top)
0% 0%0.340.220.121291473Protobuf::Field::VarintField.encode0.500.060.4419Kernel.load
0.120.120.001291473/1291473ProtobufJavaHelpers::Varinter.to_varint0.410.030.382/1883Kernel.require
0.330.000.331/1Bundler::Runtime#setup0.480.010.481/2Bundler.setup
0% 0%0.330.000.331Bundler::Runtime#requested_specs0.480.010.482Bundler.definition
0.330.39 0.000.331/873Kernel.send0.381/1Bundler::Definition.build
0.330.000.331/1Kernel.send0.460.300.162123384/2123384Protobuf::Field::BaseFieldObjectDefinitions::BaseSetMethod#call
0% 0%0.330.000.331Bundler::Definition#requested_specs0.460.300.162123384Protobuf::Field::StringField#decode
0.330.160.16 0.000.331/1Bundler::Definition#specs_for2123384/2123384##force_encoding
0.330.34 0.000.331/1Bundler::Definition#requested_specs0.341/874Bundler::Runtime#requested_specs
0% 0%0.330.42 0.000.331Bundler::Definition#specs_for0.42874Kernel.send
0.320.34 0.000.320.34 1/1Bundler::Definition#specsBundler::Definition#requested_specs
0.320.39 0.000.320.38 1/1Bundler::Definition#specs_forBundler.definition
0% 0%0.320.39 0.000.320.38 1Bundler::Definition#specs
0.200.000.201/1Bundler::SpecSet#materialize
0.100.000.101/1Bundler::Definition#resolve
0.310.180.141291320/1291588Protobuf::Field::EnumField#encode
0%0%0.310.180.141291588Protobuf::Enum#to_i
0.140.140.001291588/1291588Protobuf::Enum#tag
0.100.100.002582641/7748887Protobuf::Field::Int64Field(singleton)#set_field
0.100.100.002582641/7748887Protobuf::Field::StringField(singleton)#set_field
0%0%0.300.300.007748887Kernel.nil?Bundler::Definition.build
0.300.37 0.000.300.37 1/1 Bundler::Dsl.evaluate
0%0%0.300.000.301Bundler::Dsl#to_definition
0.300.010.291/2584164Class#new
0.290.37 0.000.290.37 1/1Class#newBundler::Definition.build
0% 0%0.290.37 0.000.290.37 1Bundler::Definition#initialize
0.110.000.111/1Bundler::Definition#converge_pathsBundler::Dsl.evaluate
0.280.170.111281320/1291320Proc#call
0%0%0.290.170.111291320StringIO.new
0.110.11 0.001291320/1291320StringIO#initialize
0.280.220.061291320/1291320Protobuf::Field::Int64Field(singleton)#set
0%0%0.280.220.061291320Protobuf::Field::Int64Field#decode
0.120.120.001291320/2582782Protobuf::Field::StringField(singleton)#encode_to_stream1/1Bundler::Dsl#to_definition
0.130.130.370.37 0.001291320/2582782Protobuf::Field::StringField#decode6217305/6217305StringIO.new
0% 0%0.250.250.370.37 0.002582782##+6217305StringIO#initialize
0.240.170.071291320/1292131Protobuf::Field::StringField(singleton)#encode_to_stream
0%0%0.240.170.081292131BasicObject#!=
0.240.190.051291320/1291320Protobuf::Field::EnumField(singleton)#set0.370.000.371/1Bundler.setup
0% 0%0.240.190.051291320Protobuf::Field::EnumField#decode0.370.000.371Bundler::Runtime#setup
0.240.240.002582640/2583314Protobuf::Field::EnumField#coerce!
0%0%0.240.240.34 0.002583314Protobuf::Field::BaseField#type_class0.341/1Bundler::Runtime#requested_specs
0.100.100.180.18 0.001291320/2582640Protobuf::Field::EnumField#encode2113384/4247921Proc#call
0.140.140.180.18 0.001291320/2582640Protobuf::Field::Int64Field#encode2133386/4247921Test::Resource#_protobuf_message_unset_required_field_tags
0% 0%0.240.240.360.36 0.002582640ProtobufJavaHelpers::Varinter.to_varint_644247921Kernel.dup
0.240.240.340.34 0.005165280/5165280Protobuf::Decoder.decode_each_field6794732/6794732##each
0% 0%0.240.240.340.34 0.005165280StringIO#eof6794732##<
0.200.200.34 0.005165280/5168510Protobuf::Decoder.decode_each_field0.341/1Bundler::Runtime#setup
0% 0%0.200.200.34 0.005168510##==0.341Bundler::Runtime#requested_specs
0.200.200.002582641/2582825Protobuf::Field::StringField(singleton)#set_field
0%0%0.200.200.34 0.002582825##delete0.341/874Kernel.send
0.200.34 0.000.200.34 1/1Bundler::Definition#specsKernel.send
0% 0%0.200.34 0.000.200.34 1Bundler::SpecSet#materialize
0.120.000.12109/153Protobuf::Message::Fields::ClassMethods.optional
0%0%0.180.000.18153Protobuf::Message::Fields::ClassMethods.define_fieldBundler::Definition#requested_specs
0.170.34 0.000.17153/153Protobuf::Field.build0.341/1Bundler::Definition#specs_for
0.170.170.34 0.003873960/3873960Protobuf::Decoder.decode_each_field0.341/1Bundler::Definition#requested_specs
0% 0%0.170.170.34 0.003873960##>>0.341Bundler::Definition#specs_for
0.170.000.17153/153Protobuf::Message::Fields::ClassMethods.define_field
0%0%0.170.33 0.000.17153Protobuf::Field.build
0.170.010.16153/2584164Class#new0.331/1Bundler::Definition#specs
0.170.170.33 0.003681355/3681355##each0.331/1Bundler::Definition#specs_for
0% 0%0.170.170.33 0.003681355##<0.331Bundler::Definition#specs
0.170.170.003873960/3873960Protobuf::Decoder.decode_each_field
0%0%0.170.170.003873960##&
0%0%0.160.22 0.000.166Bundler::SpecSet#for
0.160.010.166/6Kernel.loop0.221/1Bundler::SpecSet#materialize
0.160.010.166/6Bundler::SpecSet#for
0%0%0.160.010.166Kernel.loop
0.140.320.32 0.000.14215/215Bundler::SpecSet#spec_for_dependency
0.160.010.15153/153Class#new4093920/4103921Proc#call
0% 0%0.160.010.15153Protobuf::Field::BaseField#initialize0.320.320.004103921Protobuf::Message#to_proto
0.310.310.006380152/6380152Protobuf::Decoder.decode_each_field
0% 0%0.150.060.091137BasicObject#instance_eval0.310.310.006380152StringIO#eof
0.150.150.280.28 0.002582641/2583673Test::Resource#_protobuf_message_required_field_tags4103921/4104065Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
0% 0%0.150.150.280.28 0.002583673Kernel.dup4104065##+
0.280.000.281/1Bundler::Dsl.evaluate
0% 0%0.140.030.1161Kernel.eval0.280.000.281Bundler::Dsl#to_definition
0.100.020.0816/25841640.280.010.271/2136384 Class#new
0.140.140.27 0.002582649/2584139Protobuf::Enum.fetch0.271/1Class#new
0% 0%0.140.140.27 0.002584139Kernel.kind_of?0.271Bundler::Definition#initialize
0.100.000.101/1Bundler::Definition#converge_paths
0.140.250.25 0.000.14215/215Kernel.loop6380152/6383519Protobuf::Decoder.decode_each_field
0% 0%0.140.250.25 0.000.14215Bundler::SpecSet#spec_for_dependency6383519##==
0.140.140.230.23 0.001291588/1291588Protobuf::Enum#to_i2123384/2123384Protobuf::Decoder.decode_each_field
0% 0%0.140.140.230.23 0.001291588Protobuf::Enum#tag2123384StringIO#read
0.130.130.19 0.002582640/2583129Protobuf::Enum.enum_for_tag_integer0.191/425Bundler::SpecSet#materialize
0% 0%0.130.130.230.020.21425##map!
0.19 0.002583129##first0.1939/39Bundler::LazySpecification#__materialize__
0.130.130.110.11 0.001291320/1291320Protobuf::Decoder.decode_each_field2133386/4298337Protobuf::Field::VarintField#coerce!
0%0%0.130.13
0.120.12 0.001291320StringIO#read2133386/4298337Protobuf::Field::BaseFieldObjectDefinitions::RequiredStringSetField#call
0% 0%0.130.020.11412##map!0.230.230.004298337Kernel.kind_of?
0.130.22 0.000.130.22 1/1Kernel.requireBundler::Definition#specs
0% 0%0.130.22 0.000.130.22 1Gem::Specification.load_defaultsBundler::SpecSet#materialize
0.120.19 0.000.121/1Gem::Specification.each_spec0.191/425##map!
0.120.210.21 0.000.121/1Gem::Specification.load_defaults4103921/4103921Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
0% 0%0.120.000.121Gem::Specification.each_spec
0.120.210.21 0.000.121/1Gem::Specification.each_gemspec4103921##encoding
0.120.19 0.000.12109/109Kernel.require0.1939/39##map!
0% 0%0.120.19 0.000.12109Protobuf::Message::Fields::ClassMethods.optional0.1939Bundler::LazySpecification#__materialize__
0.120.16 0.000.12109/153Protobuf::Message::Fields::ClassMethods.define_field0.1637/37Bundler::Source::Rubygems#specs
0.120.000.121/1Gem::Specification.each_spec0.160.100.062133386/2133600Protobuf::Message#initialize
0% 0%0.19 0.120.000.121Gem::Specification.each_gemspec0.072133600##each
0.120.180.18 0.000.121/1292879##each4256768/4256768Protobuf::Decoder.decode_each_field
0%0%0.180.180.004256768##>>
0%0%0.180.020.16697##map
0.110.180.18 0.000.111/172Bundler::Definition#converge_paths4104167/4104503BasicObject#!=
0% 0%0.120.180.18 0.000.12172##any?4104503BasicObject#==
0.110.170.17 0.000.112/2Bundler::Definition#specs_changed?4103921/4103921Protobuf::Field::BaseFieldObjectDefinitions::StringEncodeToStream#call
0%0%0.170.170.004103921##bytesize
0.120.120.15 0.001291473/1291473Protobuf::Field::VarintField.encode0.151/2Bundler::Source::Rubygems#installed_specs
0% 0%0.120.120.16 0.001291473ProtobufJavaHelpers::Varinter.to_varint0.162Bundler::Index.build
0.150.000.151/1Bundler::RubygemsIntegration::MoreFuture#all_specs
0.110.110.160.16 0.001291320/1291320StringIO.new2133386/2133570Protobuf::Field::BaseFieldObjectDefinitions::RequiredStringSetField#call
0% 0%0.110.110.160.16 0.001291320StringIO#initialize2133570##delete
0.110.110.160.16 0.002582641/2582641Protobuf::Field::Int64Field(singleton)#set_field2123384/2123384Protobuf::Field::StringField#decode
0% 0%0.110.110.160.16 0.002582641ProtobufJavaHelpers::Int64ProtobufField.coerce!2123384##force_encoding
0.110.16 0.000.111/1Bundler::Definition#initialize0.1637/37Bundler::LazySpecification#__materialize__
0% 0%0.110.16 0.000.111Bundler::Definition#converge_paths0.1637Bundler::Source::Rubygems#specs
0.110.15 0.000.111/172##any?0.151/1Bundler::Source::Rubygems#installed_specs
0.110.15 0.000.112/2##any?0.151/1Bundler::Source::Rubygems#specs
0% 0%0.110.15 0.000.112Bundler::Definition#specs_changed?0.151Bundler::Source::Rubygems#installed_specs
0.110.000.112/2Bundler::Definition#specs_for_source_changed?
0%0%0.110.110.15 0.002582640ProtobufJavaHelpers::IntegerProtobufField.decode_varint_640.151/2Bundler::Index.build
0.100.15 0.000.102/5Bundler::Definition#specs_for_source_changed?0.151/1Bundler::Index.build
0% 0%0.110.15 0.000.115Bundler::Source::Path#specs0.151Bundler::RubygemsIntegration::MoreFuture#all_specs
0.110.14 0.000.115/5Bundler::Source::Path#local_specs0.141/1Gem::Specification.stubs
0.110.14 0.000.112/2Bundler::Definition#specs_changed?0.141/1Bundler::RubygemsIntegration::MoreFuture#all_specs
0% 0%0.110.14 0.000.141Gem::Specification.stubs
0%0%0.140.03 0.112Bundler::Definition#specs_for_source_changed?61Kernel.eval
0.10
0%0%0.13 0.000.102/5Bundler::Source::Path#specs0.133Gem::Specification.gemspec_stubs_in
0.110.110.12 0.002582641/2582814Protobuf::Message#initialize0.121/1Kernel.require
0% 0%0.110.110.12 0.002582814Kernel.block_given?0.121Gem::Specification.load_defaults
0.120.000.121/1Gem::Specification.each_spec
0.110.12 0.000.115/5Bundler::Source::Path#specs0.121/1Gem::Specification.load_defaults
0% 0%0.110.12 0.000.115Bundler::Source::Path#local_specs0.121Gem::Specification.each_spec
0.110.12 0.000.113/3Bundler::Source::Path#load_spec_files0.121/1Gem::Specification.each_gemspec
0.110.12 0.000.113/3Bundler::Source::Path#local_specs0.121/1Gem::Specification.each_spec
0% 0%0.110.12 0.000.113Bundler::Source::Path#load_spec_files0.121Gem::Specification.each_gemspec
0.110.110.001281320/1291320Proc#call
0%0%0.110.110.12 0.001291320Protobuf::Message#to_proto0.121/4105546##each
0%0%0.110.090.02449##reverse_each
0.110.110.10 0.002582641/2582642Protobuf::Message#initialize0.101/178Bundler::Definition#converge_paths
0% 0% 0.110.00 0.11178##any?
0.10 0.002582642##to_hash0.102/2Bundler::Definition#specs_changed?
0.00 0.10 1/1Bundler::Definition#specsBundler::Definition#initialize
0% 0.00 0.10 1Bundler::Definition#resolveBundler::Definition#converge_paths
0.100.000.101/178##any?
0.10 0.002582641/2583806Protobuf::Field::StringField(singleton)#set_field0.102/2##any?
0% 0% 0.100.10 0.002583806##to_s0.102Bundler::Definition#specs_changed?
0% 0% 0.10 0.00 0.1014Gem::Specification.load
153Protobuf::Message::Fields::ClassMethods.define_field