Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

descriptor bytes and fully qualified name helpers #397

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,20 @@ before_install:
- sudo make install
# Retrun to project directory
- cd ..
- sudo -E ./install-protobuf.sh
- curl -SsfL -O https://github.com/protocolbuffers/protobuf/releases/download/v3.8.0/protoc-3.8.0-linux-x86_64.zip
- sudo -E unzip -d /usr protoc-3.8.0-linux-x86_64.zip
- java -Xmx1g -version
- javac -J-Xmx1g -version
- export JRUBY_OPTS=-J-Xmx1g
- gem update bundler
language: ruby
rvm:
- 1.9.3
- 2.0.0
- 2.1
- 2.2
- 2.3
- 2.4
- 2.5
- 2.6
- jruby-9.1.17.0
- jruby-9.2.5.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
- jruby-9.2.7.0
notifications:
webhooks:
urls:
Expand Down
6 changes: 3 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ task :default => ['compile:spec', 'compile:rpc', :spec, :rubocop]
desc 'Run specs'
namespace :compile do

desc 'Compile spec protos in spec/supprt/ directory'
desc 'Compile spec protos in spec/support/ directory'
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(' ')})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to: #345

cmd = %(protoc --plugin=protoc-gen-ruby-protobuf=./bin/protoc-gen-ruby --ruby-protobuf_out=#{proto_path} -I #{proto_path} #{proto_files.join(' ')})

puts cmd
system(cmd)
Expand All @@ -35,7 +35,7 @@ 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)
Expand Down
28 changes: 0 additions & 28 deletions install-protobuf.sh

This file was deleted.

13 changes: 11 additions & 2 deletions lib/protobuf/code_generator.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
require 'active_support/core_ext/module/aliasing'
require 'protobuf/generators/file_generator'

::Google::Protobuf::FieldDescriptorProto.module_eval do
attr_writer :fully_qualified_name

def fully_qualified_name
@fully_qualified_name || name
end
end

module Protobuf
class CodeGenerator

Expand Down Expand Up @@ -28,17 +36,18 @@ def self.warn(message)
def initialize(request_bytes)
@request_bytes = request_bytes
self.request = ::Google::Protobuf::Compiler::CodeGeneratorRequest.decode(request_bytes)
@proto_file_to_descriptor = request.proto_file.map { |file_descriptor| [file_descriptor.name, file_descriptor] }.to_h.freeze
end

def eval_unknown_extensions!
request.proto_file.each do |file_descriptor|
::Protobuf::Generators::FileGenerator.new(file_descriptor).eval_unknown_extensions!
::Protobuf::Generators::FileGenerator.new(file_descriptor, @proto_file_to_descriptor).eval_unknown_extensions!
end
self.request = ::Google::Protobuf::Compiler::CodeGeneratorRequest.decode(@request_bytes)
end

def generate_file(file_descriptor)
::Protobuf::Generators::FileGenerator.new(file_descriptor).generate_output_file
::Protobuf::Generators::FileGenerator.new(file_descriptor, @proto_file_to_descriptor).generate_output_file
end

def response_bytes
Expand Down
206 changes: 206 additions & 0 deletions lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# encoding: utf-8
# frozen_string_literal: true

##
# This file is auto-generated. DO NOT EDIT!
#
require 'base64'
require 'set'
require 'protobuf'


Expand All @@ -14,6 +17,28 @@
module Google
module Protobuf
module Compiler
FULLY_QUALIFIED_NAME = 'google.protobuf.compiler' unless defined?(self::FULLY_QUALIFIED_NAME)

@descriptors = [] unless instance_variable_defined?(:@descriptors)
@descriptors << lambda do
bytes = File.read(__FILE__, mode: 'rb').split(/^__END__$/, 2).last
::Google::Protobuf::FileDescriptorProto.decode(Base64.decode64(bytes))
end

@descriptor_dependencies = Set.new unless instance_variable_defined?(:@descriptor_dependencies)
@descriptor_dependencies |= [Google::Protobuf]

unless respond_to?(:descriptor_set)
def self.descriptor_set
::Google::Protobuf::FileDescriptorSet.new(:file => @descriptors.map(&:call))
end
end

unless respond_to?(:descriptor_dependencies)
def self.descriptor_dependencies
@descriptor_dependencies
end
end
::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }

##
Expand All @@ -38,13 +63,16 @@ class File < ::Protobuf::Message; end
# Message Fields
#
class CodeGeneratorRequest
FULLY_QUALIFIED_NAME = FULLY_QUALIFIED_NAME + '.CodeGeneratorRequest'
repeated :string, :file_to_generate, 1
optional :string, :parameter, 2
repeated ::Google::Protobuf::FileDescriptorProto, :proto_file, 15
end

class CodeGeneratorResponse
FULLY_QUALIFIED_NAME = FULLY_QUALIFIED_NAME + '.CodeGeneratorResponse'
class File
FULLY_QUALIFIED_NAME = FULLY_QUALIFIED_NAME + '.File'
optional :string, :name, 1
optional :string, :insertion_point, 2
optional :string, :content, 15
Expand All @@ -60,3 +88,181 @@ class File

end


# Raw descriptor bytes below
__END__
CiVnb29nbGUvcHJvdG9idWYvY29tcGlsZXIvcGx1Z2luLnByb3RvEhhnb29n
bGUucHJvdG9idWYuY29tcGlsZXIaIGdvb2dsZS9wcm90b2J1Zi9kZXNjcmlw
dG9yLnByb3RvIqMBChRDb2RlR2VuZXJhdG9yUmVxdWVzdBIoChBmaWxlX3Rv
X2dlbmVyYXRlGAEgAygJUg5maWxlVG9HZW5lcmF0ZRIcCglwYXJhbWV0ZXIY
AiABKAlSCXBhcmFtZXRlchJDCgpwcm90b19maWxlGA8gAygLMiQuZ29vZ2xl
LnByb3RvYnVmLkZpbGVEZXNjcmlwdG9yUHJvdG9SCXByb3RvRmlsZSLWAQoV
Q29kZUdlbmVyYXRvclJlc3BvbnNlEhQKBWVycm9yGAEgASgJUgVlcnJvchJI
CgRmaWxlGA8gAygLMjQuZ29vZ2xlLnByb3RvYnVmLmNvbXBpbGVyLkNvZGVH
ZW5lcmF0b3JSZXNwb25zZS5GaWxlUgRmaWxlGl0KBEZpbGUSEgoEbmFtZRgB
IAEoCVIEbmFtZRInCg9pbnNlcnRpb25fcG9pbnQYAiABKAlSDmluc2VydGlv
blBvaW50EhgKB2NvbnRlbnQYDyABKAlSB2NvbnRlbnRCLAocY29tLmdvb2ds
ZS5wcm90b2J1Zi5jb21waWxlckIMUGx1Z2luUHJvdG9zSqY5CgcSBS4AkgEB
Cr0RCgECEgMuACEytAwgUHJvdG9jb2wgQnVmZmVycyAtIEdvb2dsZSdzIGRh
dGEgaW50ZXJjaGFuZ2UgZm9ybWF0CiBDb3B5cmlnaHQgMjAwOCBHb29nbGUg
SW5jLiAgQWxsIHJpZ2h0cyByZXNlcnZlZC4KIGh0dHA6Ly9jb2RlLmdvb2ds
ZS5jb20vcC9wcm90b2J1Zi8KCiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGlu
IHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQKIG1v
ZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBm
b2xsb3dpbmcgY29uZGl0aW9ucyBhcmUKIG1ldDoKCiAgICAgKiBSZWRpc3Ry
aWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3Zl
IGNvcHlyaWdodAogbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBh
bmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLgogICAgICogUmVkaXN0cmli
dXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92
ZQogY29weXJpZ2h0IG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMg
YW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lcgogaW4gdGhlIGRvY3VtZW50
YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRo
ZQogZGlzdHJpYnV0aW9uLgogICAgICogTmVpdGhlciB0aGUgbmFtZSBvZiBH
b29nbGUgSW5jLiBub3IgdGhlIG5hbWVzIG9mIGl0cwogY29udHJpYnV0b3Jz
IG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBk
ZXJpdmVkIGZyb20KIHRoaXMgc29mdHdhcmUgd2l0aG91dCBzcGVjaWZpYyBw
cmlvciB3cml0dGVuIHBlcm1pc3Npb24uCgogVEhJUyBTT0ZUV0FSRSBJUyBQ
Uk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJV
VE9SUwogIkFTIElTIiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJS
QU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QKIExJTUlURUQgVE8sIFRIRSBJ
TVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRO
RVNTIEZPUgogQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQu
IElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQKIE9XTkVSIE9SIENP
TlRSSUJVVE9SUyBCRSBMSUFCTEUgRk9SIEFOWSBESVJFQ1QsIElORElSRUNU
LCBJTkNJREVOVEFMLAogU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFV
RU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVAogTElNSVRFRCBU
TywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNF
UzsgTE9TUyBPRiBVU0UsCiBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVT
UyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkKIFRI
RU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklD
VCBMSUFCSUxJVFksIE9SIFRPUlQKIChJTkNMVURJTkcgTkVHTElHRU5DRSBP
UiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVT
RQogT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQ
T1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS4KMvsEIEF1dGhvcjoga2VudG9u
QGdvb2dsZS5jb20gKEtlbnRvbiBWYXJkYSkKCiBXQVJOSU5HOiAgVGhlIHBs
dWdpbiBpbnRlcmZhY2UgaXMgY3VycmVudGx5IEVYUEVSSU1FTlRBTCBhbmQg
aXMgc3ViamVjdCB0bwogICBjaGFuZ2UuCgogcHJvdG9jIChha2EgdGhlIFBy
b3RvY29sIENvbXBpbGVyKSBjYW4gYmUgZXh0ZW5kZWQgdmlhIHBsdWdpbnMu
ICBBIHBsdWdpbiBpcwoganVzdCBhIHByb2dyYW0gdGhhdCByZWFkcyBhIENv
ZGVHZW5lcmF0b3JSZXF1ZXN0IGZyb20gc3RkaW4gYW5kIHdyaXRlcyBhCiBD
b2RlR2VuZXJhdG9yUmVzcG9uc2UgdG8gc3Rkb3V0LgoKIFBsdWdpbnMgd3Jp
dHRlbiB1c2luZyBDKysgY2FuIHVzZSBnb29nbGUvcHJvdG9idWYvY29tcGls
ZXIvcGx1Z2luLmggaW5zdGVhZAogb2YgZGVhbGluZyB3aXRoIHRoZSByYXcg
cHJvdG9jb2wgZGVmaW5lZCBoZXJlLgoKIEEgcGx1Z2luIGV4ZWN1dGFibGUg
bmVlZHMgb25seSB0byBiZSBwbGFjZWQgc29tZXdoZXJlIGluIHRoZSBwYXRo
LiAgVGhlCiBwbHVnaW4gc2hvdWxkIGJlIG5hbWVkICJwcm90b2MtZ2VuLSRO
QU1FIiwgYW5kIHdpbGwgdGhlbiBiZSB1c2VkIHdoZW4gdGhlCiBmbGFnICIt
LSR7TkFNRX1fb3V0IiBpcyBwYXNzZWQgdG8gcHJvdG9jLgoKCAoBCBIDLwA1
CgkKAggBEgMvADUKCAoBCBIDMAAtCgkKAggIEgMwAC0KCQoCAwASAzIAKgpP
CgIEABIENQBKARpDIEFuIGVuY29kZWQgQ29kZUdlbmVyYXRvclJlcXVlc3Qg
aXMgd3JpdHRlbiB0byB0aGUgcGx1Z2luJ3Mgc3RkaW4uCgoKCgMEAAESAzUI
HArRAQoEBAACABIDOQInGsMBIFRoZSAucHJvdG8gZmlsZXMgdGhhdCB3ZXJl
IGV4cGxpY2l0bHkgbGlzdGVkIG9uIHRoZSBjb21tYW5kLWxpbmUuICBUaGUK
IGNvZGUgZ2VuZXJhdG9yIHNob3VsZCBnZW5lcmF0ZSBjb2RlIG9ubHkgZm9y
IHRoZXNlIGZpbGVzLiAgRWFjaCBmaWxlJ3MKIGRlc2NyaXB0b3Igd2lsbCBi
ZSBpbmNsdWRlZCBpbiBwcm90b19maWxlLCBiZWxvdy4KCgwKBQQAAgAEEgM5
AgoKDAoFBAACAAUSAzkLEQoMCgUEAAIAARIDORIiCgwKBQQAAgADEgM5JSYK
QgoEBAACARIDPAIgGjUgVGhlIGdlbmVyYXRvciBwYXJhbWV0ZXIgcGFzc2Vk
IG9uIHRoZSBjb21tYW5kLWxpbmUuCgoMCgUEAAIBBBIDPAIKCgwKBQQAAgEF
EgM8CxEKDAoFBAACAQESAzwSGwoMCgUEAAIBAxIDPB4fCqkFCgQEAAICEgNJ
Ai8amwUgRmlsZURlc2NyaXB0b3JQcm90b3MgZm9yIGFsbCBmaWxlcyBpbiBm
aWxlc190b19nZW5lcmF0ZSBhbmQgZXZlcnl0aGluZwogdGhleSBpbXBvcnQu
ICBUaGUgZmlsZXMgd2lsbCBhcHBlYXIgaW4gdG9wb2xvZ2ljYWwgb3JkZXIs
IHNvIGVhY2ggZmlsZQogYXBwZWFycyBiZWZvcmUgYW55IGZpbGUgdGhhdCBp
bXBvcnRzIGl0LgoKIHByb3RvYyBndWFyYW50ZWVzIHRoYXQgYWxsIHByb3Rv
X2ZpbGVzIHdpbGwgYmUgd3JpdHRlbiBhZnRlcgogdGhlIGZpZWxkcyBhYm92
ZSwgZXZlbiB0aG91Z2ggdGhpcyBpcyBub3QgdGVjaG5pY2FsbHkgZ3VhcmFu
dGVlZCBieSB0aGUKIHByb3RvYnVmIHdpcmUgZm9ybWF0LiAgVGhpcyB0aGVv
cmV0aWNhbGx5IGNvdWxkIGFsbG93IGEgcGx1Z2luIHRvIHN0cmVhbQogaW4g
dGhlIEZpbGVEZXNjcmlwdG9yUHJvdG9zIGFuZCBoYW5kbGUgdGhlbSBvbmUg
Ynkgb25lIHJhdGhlciB0aGFuIHJlYWQKIHRoZSBlbnRpcmUgc2V0IGludG8g
bWVtb3J5IGF0IG9uY2UuICBIb3dldmVyLCBhcyBvZiB0aGlzIHdyaXRpbmcs
IHRoaXMKIGlzIG5vdCBzaW1pbGFybHkgb3B0aW1pemVkIG9uIHByb3RvYydz
IGVuZCAtLSBpdCB3aWxsIHN0b3JlIGFsbCBmaWVsZHMgaW4KIG1lbW9yeSBh
dCBvbmNlIGJlZm9yZSBzZW5kaW5nIHRoZW0gdG8gdGhlIHBsdWdpbi4KCgwK
BQQAAgIEEgNJAgoKDAoFBAACAgYSA0kLHgoMCgUEAAICARIDSR8pCgwKBQQA
AgIDEgNJLC4KTAoCBAESBU0AkgEBGj8gVGhlIHBsdWdpbiB3cml0ZXMgYW4g
ZW5jb2RlZCBDb2RlR2VuZXJhdG9yUmVzcG9uc2UgdG8gc3Rkb3V0LgoKCgoD
BAEBEgNNCB0K7QMKBAQBAgASA1YCHBrfAyBFcnJvciBtZXNzYWdlLiAgSWYg
bm9uLWVtcHR5LCBjb2RlIGdlbmVyYXRpb24gZmFpbGVkLiAgVGhlIHBsdWdp
biBwcm9jZXNzCiBzaG91bGQgZXhpdCB3aXRoIHN0YXR1cyBjb2RlIHplcm8g
ZXZlbiBpZiBpdCByZXBvcnRzIGFuIGVycm9yIGluIHRoaXMgd2F5LgoKIFRo
aXMgc2hvdWxkIGJlIHVzZWQgdG8gaW5kaWNhdGUgZXJyb3JzIGluIC5wcm90
byBmaWxlcyB3aGljaCBwcmV2ZW50IHRoZQogY29kZSBnZW5lcmF0b3IgZnJv
bSBnZW5lcmF0aW5nIGNvcnJlY3QgY29kZS4gIEVycm9ycyB3aGljaCBpbmRp
Y2F0ZSBhCiBwcm9ibGVtIGluIHByb3RvYyBpdHNlbGYgLS0gc3VjaCBhcyB0
aGUgaW5wdXQgQ29kZUdlbmVyYXRvclJlcXVlc3QgYmVpbmcKIHVucGFyc2Vh
YmxlIC0tIHNob3VsZCBiZSByZXBvcnRlZCBieSB3cml0aW5nIGEgbWVzc2Fn
ZSB0byBzdGRlcnIgYW5kCiBleGl0aW5nIHdpdGggYSBub24temVybyBzdGF0
dXMgY29kZS4KCgwKBQQBAgAEEgNWAgoKDAoFBAECAAUSA1YLEQoMCgUEAQIA
ARIDVhIXCgwKBQQBAgADEgNWGhsKNAoEBAEDABIFWQKQAQMaJSBSZXByZXNl
bnRzIGEgc2luZ2xlIGdlbmVyYXRlZCBmaWxlLgoKDAoFBAEDAAESA1kKDgqt
BQoGBAEDAAIAEgNlBB0anQUgVGhlIGZpbGUgbmFtZSwgcmVsYXRpdmUgdG8g
dGhlIG91dHB1dCBkaXJlY3RvcnkuICBUaGUgbmFtZSBtdXN0IG5vdAogY29u
dGFpbiAiLiIgb3IgIi4uIiBjb21wb25lbnRzIGFuZCBtdXN0IGJlIHJlbGF0
aXZlLCBub3QgYmUgYWJzb2x1dGUgKHNvLAogdGhlIGZpbGUgY2Fubm90IGxp
ZSBvdXRzaWRlIHRoZSBvdXRwdXQgZGlyZWN0b3J5KS4gICIvIiBtdXN0IGJl
IHVzZWQgYXMKIHRoZSBwYXRoIHNlcGFyYXRvciwgbm90ICJcIi4KCiBJZiB0
aGUgbmFtZSBpcyBvbWl0dGVkLCB0aGUgY29udGVudCB3aWxsIGJlIGFwcGVu
ZGVkIHRvIHRoZSBwcmV2aW91cwogZmlsZS4gIFRoaXMgYWxsb3dzIHRoZSBn
ZW5lcmF0b3IgdG8gYnJlYWsgbGFyZ2UgZmlsZXMgaW50byBzbWFsbCBjaHVu
a3MsCiBhbmQgYWxsb3dzIHRoZSBnZW5lcmF0ZWQgdGV4dCB0byBiZSBzdHJl
YW1lZCBiYWNrIHRvIHByb3RvYyBzbyB0aGF0IGxhcmdlCiBmaWxlcyBuZWVk
IG5vdCByZXNpZGUgY29tcGxldGVseSBpbiBtZW1vcnkgYXQgb25lIHRpbWUu
ICBOb3RlIHRoYXQgYXMgb2YKIHRoaXMgd3JpdGluZyBwcm90b2MgZG9lcyBu
b3Qgb3B0aW1pemUgZm9yIHRoaXMgLS0gaXQgd2lsbCByZWFkIHRoZSBlbnRp
cmUKIENvZGVHZW5lcmF0b3JSZXNwb25zZSBiZWZvcmUgd3JpdGluZyBmaWxl
cyB0byBkaXNrLgoKDgoHBAEDAAIABBIDZQQMCg4KBwQBAwACAAUSA2UNEwoO
CgcEAQMAAgABEgNlFBgKDgoHBAEDAAIAAxIDZRscCq4QCgYEAQMAAgESBIwB
BCganRAgSWYgbm9uLWVtcHR5LCBpbmRpY2F0ZXMgdGhhdCB0aGUgbmFtZWQg
ZmlsZSBzaG91bGQgYWxyZWFkeSBleGlzdCwgYW5kIHRoZQogY29udGVudCBo
ZXJlIGlzIHRvIGJlIGluc2VydGVkIGludG8gdGhhdCBmaWxlIGF0IGEgZGVm
aW5lZCBpbnNlcnRpb24KIHBvaW50LiAgVGhpcyBmZWF0dXJlIGFsbG93cyBh
IGNvZGUgZ2VuZXJhdG9yIHRvIGV4dGVuZCB0aGUgb3V0cHV0CiBwcm9kdWNl
ZCBieSBhbm90aGVyIGNvZGUgZ2VuZXJhdG9yLiAgVGhlIG9yaWdpbmFsIGdl
bmVyYXRvciBtYXkgcHJvdmlkZQogaW5zZXJ0aW9uIHBvaW50cyBieSBwbGFj
aW5nIHNwZWNpYWwgYW5ub3RhdGlvbnMgaW4gdGhlIGZpbGUgdGhhdCBsb29r
CiBsaWtlOgogICBAQHByb3RvY19pbnNlcnRpb25fcG9pbnQoTkFNRSkKIFRo
ZSBhbm5vdGF0aW9uIGNhbiBoYXZlIGFyYml0cmFyeSB0ZXh0IGJlZm9yZSBh
bmQgYWZ0ZXIgaXQgb24gdGhlIGxpbmUsCiB3aGljaCBhbGxvd3MgaXQgdG8g
YmUgcGxhY2VkIGluIGEgY29tbWVudC4gIE5BTUUgc2hvdWxkIGJlIHJlcGxh
Y2VkIHdpdGgKIGFuIGlkZW50aWZpZXIgbmFtaW5nIHRoZSBwb2ludCAtLSB0
aGlzIGlzIHdoYXQgb3RoZXIgZ2VuZXJhdG9ycyB3aWxsIHVzZQogYXMgdGhl
IGluc2VydGlvbl9wb2ludC4gIENvZGUgaW5zZXJ0ZWQgYXQgdGhpcyBwb2lu
dCB3aWxsIGJlIHBsYWNlZAogaW1tZWRpYXRlbHkgYWJvdmUgdGhlIGxpbmUg
Y29udGFpbmluZyB0aGUgaW5zZXJ0aW9uIHBvaW50ICh0aHVzIG11bHRpcGxl
CiBpbnNlcnRpb25zIHRvIHRoZSBzYW1lIHBvaW50IHdpbGwgY29tZSBvdXQg
aW4gdGhlIG9yZGVyIHRoZXkgd2VyZSBhZGRlZCkuCiBUaGUgZG91YmxlLUAg
aXMgaW50ZW5kZWQgdG8gbWFrZSBpdCB1bmxpa2VseSB0aGF0IHRoZSBnZW5l
cmF0ZWQgY29kZQogY291bGQgY29udGFpbiB0aGluZ3MgdGhhdCBsb29rIGxp
a2UgaW5zZXJ0aW9uIHBvaW50cyBieSBhY2NpZGVudC4KCiBGb3IgZXhhbXBs
ZSwgdGhlIEMrKyBjb2RlIGdlbmVyYXRvciBwbGFjZXMgdGhlIGZvbGxvd2lu
ZyBsaW5lIGluIHRoZQogLnBiLmggZmlsZXMgdGhhdCBpdCBnZW5lcmF0ZXM6
CiAgIC8vIEBAcHJvdG9jX2luc2VydGlvbl9wb2ludChuYW1lc3BhY2Vfc2Nv
cGUpCiBUaGlzIGxpbmUgYXBwZWFycyB3aXRoaW4gdGhlIHNjb3BlIG9mIHRo
ZSBmaWxlJ3MgcGFja2FnZSBuYW1lc3BhY2UsIGJ1dAogb3V0c2lkZSBvZiBh
bnkgcGFydGljdWxhciBjbGFzcy4gIEFub3RoZXIgcGx1Z2luIGNhbiB0aGVu
IHNwZWNpZnkgdGhlCiBpbnNlcnRpb25fcG9pbnQgIm5hbWVzcGFjZV9zY29w
ZSIgdG8gZ2VuZXJhdGUgYWRkaXRpb25hbCBjbGFzc2VzIG9yCiBvdGhlciBk
ZWNsYXJhdGlvbnMgdGhhdCBzaG91bGQgYmUgcGxhY2VkIGluIHRoaXMgc2Nv
cGUuCgogTm90ZSB0aGF0IGlmIHRoZSBsaW5lIGNvbnRhaW5pbmcgdGhlIGlu
c2VydGlvbiBwb2ludCBiZWdpbnMgd2l0aAogd2hpdGVzcGFjZSwgdGhlIHNh
bWUgd2hpdGVzcGFjZSB3aWxsIGJlIGFkZGVkIHRvIGV2ZXJ5IGxpbmUgb2Yg
dGhlCiBpbnNlcnRlZCB0ZXh0LiAgVGhpcyBpcyB1c2VmdWwgZm9yIGxhbmd1
YWdlcyBsaWtlIFB5dGhvbiwgd2hlcmUKIGluZGVudGF0aW9uIG1hdHRlcnMu
ICBJbiB0aGVzZSBsYW5ndWFnZXMsIHRoZSBpbnNlcnRpb24gcG9pbnQgY29t
bWVudAogc2hvdWxkIGJlIGluZGVudGVkIHRoZSBzYW1lIGFtb3VudCBhcyBh
bnkgaW5zZXJ0ZWQgY29kZSB3aWxsIG5lZWQgdG8gYmUKIGluIG9yZGVyIHRv
IHdvcmsgY29ycmVjdGx5IGluIHRoYXQgY29udGV4dC4KCiBUaGUgY29kZSBn
ZW5lcmF0b3IgdGhhdCBnZW5lcmF0ZXMgdGhlIGluaXRpYWwgZmlsZSBhbmQg
dGhlIG9uZSB3aGljaAogaW5zZXJ0cyBpbnRvIGl0IG11c3QgYm90aCBydW4g
YXMgcGFydCBvZiBhIHNpbmdsZSBpbnZvY2F0aW9uIG9mIHByb3RvYy4KIENv
ZGUgZ2VuZXJhdG9ycyBhcmUgZXhlY3V0ZWQgaW4gdGhlIG9yZGVyIGluIHdo
aWNoIHRoZXkgYXBwZWFyIG9uIHRoZQogY29tbWFuZCBsaW5lLgoKIElmIHxp
bnNlcnRpb25fcG9pbnR8IGlzIHByZXNlbnQsIHxuYW1lfCBtdXN0IGFsc28g
YmUgcHJlc2VudC4KCg8KBwQBAwACAQQSBIwBBAwKDwoHBAEDAAIBBRIEjAEN
EwoPCgcEAQMAAgEBEgSMARQjCg8KBwQBAwACAQMSBIwBJicKJAoGBAEDAAIC
EgSPAQQhGhQgVGhlIGZpbGUgY29udGVudHMuCgoPCgcEAQMAAgIEEgSPAQQM
Cg8KBwQBAwACAgUSBI8BDRMKDwoHBAEDAAICARIEjwEUGwoPCgcEAQMAAgID
EgSPAR4gCgwKBAQBAgESBJEBAhoKDQoFBAECAQQSBJEBAgoKDQoFBAECAQYS
BJEBCw8KDQoFBAECAQESBJEBEBQKDQoFBAECAQMSBJEBFxk=
Loading