proto-convert 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/proto-convert +193 -0
  3. metadata +81 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8dbe2b80d8695940e2103d5739243437284cf4f3ebebff33f101a0381a8ac364
4
+ data.tar.gz: de4f6515ec0ccc6249887969dd5e75f5045c93bf6ad4121426e2058aca91fc06
5
+ SHA512:
6
+ metadata.gz: 5ebe5839f579e94d492137a599060aa05607a9c8166b57126a78dbbd397cb460b260aa19ea0c02697cf8a1d2786377a606c5b76de01dfc81b0561c5bf73bb5ee
7
+ data.tar.gz: e6c4f8a87eff97289c0d4583544c6cbd57b616b9a548a4617e53a60b84394e42c3880ed34bdd68bffc65c8ca7484949224b83955c8b337af7214c2e5d227e816
@@ -0,0 +1,193 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # MIT License
5
+ #
6
+ # Copyright (c) 2020 Azeem Sajid
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files (the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be included in all
16
+ # copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ # SOFTWARE.
25
+
26
+ # proto-convert
27
+ # A command-line tool to convert protobuf messages from binary to JSON and vice versa
28
+ # GitHub: https://github.com/iamAzeem/proto-convert
29
+ #
30
+ # Developed by Azeem Sajid <azeem.sajid@gmail.com>
31
+
32
+ require 'optparse'
33
+ require 'English'
34
+
35
+ VERSION = "#{$PROGRAM_NAME} 0.1.0"
36
+ AUTHOR_NAME = 'Azeem Sajid'
37
+ AUTHOR_EMAIL = 'azeem.sajid@gmail.com'
38
+ AUTHOR_INFO = "Developed by #{AUTHOR_NAME} <#{AUTHOR_EMAIL}>"
39
+ REPO_URL = 'https://github.com/iamAzeem/proto-convert'
40
+
41
+ def compile_proto(filename)
42
+ file_path = File.expand_path(filename)
43
+ file_dir = File.dirname(file_path)
44
+
45
+ `protoc --ruby_out.=#{file_dir} --proto_path=#{file_dir} #{file_path}`
46
+ raise StandardError, "Invalid schema! [#{filename}] Resolve error(s)." unless $CHILD_STATUS.success?
47
+
48
+ compiled_proto = file_dir + '/' + File.basename(file_path, '.proto') + '_pb.rb'
49
+ raise StandardError, "Compiled schema not found! [#{compiled_proto}]" unless File.file?(compiled_proto)
50
+
51
+ compiled_proto
52
+ end
53
+
54
+ def valid_msgtype?(compiled_proto, msg_type)
55
+ msg_types = []
56
+ File.foreach(compiled_proto) do |line|
57
+ if line.lstrip.start_with?('add_message')
58
+ extracted_msg_type = line[/"([^"]*)"/, 1].freeze # regex: <add_message> 'msg_type' <do>
59
+ msg_types.push(extracted_msg_type) unless extracted_msg_type.nil?
60
+ end
61
+ end
62
+
63
+ msg_types.include?(msg_type)
64
+ end
65
+
66
+ def msg_class(compiled_proto, msg_type)
67
+ require compiled_proto
68
+ msg = Google::Protobuf::DescriptorPool.generated_pool.lookup(msg_type)
69
+ msg.msgclass
70
+ end
71
+
72
+ def convert(compiled_proto, msg_type, conversion_mode, input_file, output_file)
73
+ pb_msg_class = msg_class(compiled_proto, msg_type)
74
+ raise StandardError, "Message type ['#{msg_type}'] not registered!'" if pb_msg_class.nil?
75
+
76
+ begin
77
+ case conversion_mode
78
+ when :binary2json
79
+ input_msg = File.open(input_file, 'rb').read
80
+ puts ">> [B] #{input_file} (#{input_msg.length} bytes)"
81
+
82
+ decoded_msg = pb_msg_class.decode(input_msg)
83
+ output_msg = pb_msg_class.encode_json(decoded_msg)
84
+
85
+ File.open(output_file, 'w').write(output_msg)
86
+ puts "<< [J] #{output_file} (#{output_msg.length} bytes)"
87
+ when :json2binary
88
+ input_msg = File.open(input_file, 'r').read
89
+ puts ">> [J] #{input_file} (#{input_msg.length} bytes)"
90
+
91
+ decoded_msg = pb_msg_class.decode_json(input_msg)
92
+ output_msg = pb_msg_class.encode(decoded_msg)
93
+
94
+ File.open(output_file, 'wb').write(output_msg)
95
+ puts "<< [B] #{output_file} (#{output_msg.length} bytes)"
96
+ end
97
+ rescue Google::Protobuf::ParseError
98
+ raise StandardError, "Incompatible input message! [msgtype: #{msg_type}] #{$ERROR_INFO}"
99
+ rescue StandardError
100
+ raise StandardError, "Conversion failed! #{$ERROR_INFO}"
101
+ end
102
+ end
103
+
104
+ def start
105
+ mandatory_args = %i[mode proto msgtype input output].freeze
106
+
107
+ options = {}
108
+ mandatory_args.each { |arg| options[arg] = nil }
109
+
110
+ parser = OptionParser.new do |opts|
111
+ opts.banner = "Usage: #{$PROGRAM_NAME} -m [mode] -p [proto] -t [msgtype] -i [input] -o [output]"
112
+ opts.separator ''
113
+
114
+ modes = %i[binary2json b2j json2binary j2b].freeze
115
+ opts.on('-m', '--mode [MODE]', modes, "conversion mode #{modes.map(&:to_s)}") do |mode|
116
+ raise OptionParser::InvalidArgument unless modes.include?(mode)
117
+
118
+ if mode == :b2j
119
+ mode = :binary2json
120
+ elsif mode == :j2b
121
+ mode = :json2binary
122
+ end
123
+
124
+ options[:mode] = mode
125
+ end
126
+
127
+ opts.on('-p', '--proto [FILENAME]', 'protobuf schema (.proto)') do |filename|
128
+ raise StandardError, "Protobuf schema not found! [#{filename}]" unless File.file?(filename)
129
+
130
+ options[:proto] = filename
131
+ end
132
+
133
+ opts.on('-t', '--msgtype [TYPE]', 'fully-qualified message type') do |msgtype|
134
+ options[:msgtype] = msgtype
135
+ end
136
+
137
+ opts.on('-i', '--input [FILENAME]', 'source file (JSON/binary)') do |filename|
138
+ raise StandardError, "Source/input file not found! [#{filename}]" unless File.file?(filename)
139
+
140
+ options[:input] = filename
141
+ end
142
+
143
+ opts.on('-o', '--output [FILENAME]', 'destination file (binary/JSON)') do |filename|
144
+ options[:output] = filename
145
+ end
146
+
147
+ opts.on('-v', '--version', 'prints version information') do
148
+ puts "#{VERSION}\n#{AUTHOR_INFO}"
149
+ puts "GitHub URL: #{REPO_URL}"
150
+ exit
151
+ end
152
+
153
+ opts.on('-h', '--help', 'prints help') do
154
+ puts "#{VERSION}\n\n#{opts}\n#{AUTHOR_INFO}"
155
+ puts "GitHub URL: #{REPO_URL}"
156
+ exit
157
+ end
158
+ end
159
+
160
+ begin
161
+ parser.parse!
162
+
163
+ # Validate missing mandatory arguments
164
+ missing_args = mandatory_args.select { |arg| options[arg].nil? }
165
+ raise OptionParser::MissingArgument, 'No arguments provided!' if missing_args.length == mandatory_args.length
166
+ raise OptionParser::MissingArgument, "--#{missing_args.join(', --')}" unless missing_args.empty?
167
+
168
+ # Compile and validate proto and msgtype
169
+ compiled_proto = compile_proto(options[:proto])
170
+ msg_type = options[:msgtype]
171
+ raise OptionParser::InvalidArgument, "--msgtype #{msg_type}" unless valid_msgtype?(compiled_proto, msg_type)
172
+
173
+ # Convert and write to output file
174
+ conversion_mode = options[:mode]
175
+ input_file = options[:input]
176
+ output_file = options[:output]
177
+ convert(compiled_proto, msg_type, conversion_mode, input_file, output_file)
178
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument
179
+ puts $ERROR_INFO
180
+ puts "\n#{VERSION}\n\n#{parser}\n#{AUTHOR_INFO}"
181
+ exit 1
182
+ rescue LoadError
183
+ puts "Possible 'import' issue! Use a single self-contianed .proto file! #{$ERROR_INFO}"
184
+ exit 1
185
+ rescue StandardError
186
+ puts "ERROR: #{$ERROR_INFO}"
187
+ exit 1
188
+ ensure
189
+ File.delete(compiled_proto) if !compiled_proto.nil? && File.file?(compiled_proto)
190
+ end
191
+ end
192
+
193
+ start
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: proto-convert
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Azeem Sajid
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: google-protobuf
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.12'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 3.12.2
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.12'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 3.12.2
47
+ description: A command line tool to convert protobuf messages from binary to JSON
48
+ and vice versa
49
+ email:
50
+ - azeem.sajid@gmail.com
51
+ executables:
52
+ - proto-convert
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - bin/proto-convert
57
+ homepage: https://github.com/iamAzeem/proto-convert
58
+ licenses:
59
+ - MIT
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.7.6
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Protobuf Message Converter [Binary <-> JSON]
81
+ test_files: []