ruby_protobuf 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -0
- data/Manifest.txt +32 -0
- data/README.txt +50 -0
- data/Rakefile +18 -0
- data/bin/rprotoc +21 -0
- data/bin/ruby_protobuf +0 -0
- data/lib/protobuf/compiler.rb +90 -0
- data/lib/protobuf/decoder.rb +87 -0
- data/lib/protobuf/encoder.rb +36 -0
- data/lib/protobuf/enum.rb +13 -0
- data/lib/protobuf/extend.rb +8 -0
- data/lib/protobuf/field.rb +547 -0
- data/lib/protobuf/message.rb +133 -0
- data/lib/protobuf/parser.y +138 -0
- data/lib/protobuf/service.rb +7 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/ruby_protobuf.rb +22 -0
- data/test/addressbook.proto +24 -0
- data/test/addressbook.rb +41 -0
- data/test/data/data.bin +3 -0
- data/test/data/data_source.py +14 -0
- data/test/data/types.bin +0 -0
- data/test/data/types_source.py +22 -0
- data/test/test_addressbook.rb +41 -0
- data/test/test_compiler.rb +39 -0
- data/test/test_message.rb +20 -0
- data/test/test_parse.rb +15 -0
- data/test/test_ruby_protobuf.rb +1 -0
- data/test/test_serialize.rb +27 -0
- data/test/test_types.rb +180 -0
- data/test/types.proto +17 -0
- data/test/types.rb +22 -0
- metadata +102 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
bin/rprotoc
|
6
|
+
bin/ruby_protobuf
|
7
|
+
lib/protobuf/compiler.rb
|
8
|
+
lib/protobuf/decoder.rb
|
9
|
+
lib/protobuf/encoder.rb
|
10
|
+
lib/protobuf/enum.rb
|
11
|
+
lib/protobuf/extend.rb
|
12
|
+
lib/protobuf/field.rb
|
13
|
+
lib/protobuf/message.rb
|
14
|
+
lib/protobuf/parser.y
|
15
|
+
lib/protobuf/service.rb
|
16
|
+
lib/protobuf/wire_type.rb
|
17
|
+
lib/ruby_protobuf.rb
|
18
|
+
test/addressbook.proto
|
19
|
+
test/addressbook.rb
|
20
|
+
test/data/data.bin
|
21
|
+
test/data/data_source.py
|
22
|
+
test/data/types.bin
|
23
|
+
test/data/types_source.py
|
24
|
+
test/test_addressbook.rb
|
25
|
+
test/test_compiler.rb
|
26
|
+
test/test_message.rb
|
27
|
+
test/test_parse.rb
|
28
|
+
test/test_ruby_protobuf.rb
|
29
|
+
test/test_serialize.rb
|
30
|
+
test/test_types.rb
|
31
|
+
test/types.proto
|
32
|
+
test/types.rb
|
data/README.txt
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= RubyProtobuf
|
2
|
+
|
3
|
+
* http://code.google.com/p/ruby-protobuf
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Protocol Buffers for Ruby.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* Compile .proto file to ruby script
|
12
|
+
* Parse the binary wire format for protocol buffer
|
13
|
+
* Serialize data to the binary wire format for protocol buffer
|
14
|
+
|
15
|
+
== SYNOPSIS:
|
16
|
+
|
17
|
+
bin/rprotoc -I lib test/addressbook.proto
|
18
|
+
|
19
|
+
== REQUIREMENTS:
|
20
|
+
|
21
|
+
* All you need are included.
|
22
|
+
|
23
|
+
== INSTALL:
|
24
|
+
|
25
|
+
* sudo gem install ruby-protobuf
|
26
|
+
|
27
|
+
== LICENSE:
|
28
|
+
|
29
|
+
(The MIT License)
|
30
|
+
|
31
|
+
Copyright (c) 2008 FIX
|
32
|
+
|
33
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
34
|
+
a copy of this software and associated documentation files (the
|
35
|
+
'Software'), to deal in the Software without restriction, including
|
36
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
37
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
38
|
+
permit persons to whom the Software is furnished to do so, subject to
|
39
|
+
the following conditions:
|
40
|
+
|
41
|
+
The above copyright notice and this permission notice shall be
|
42
|
+
included in all copies or substantial portions of the Software.
|
43
|
+
|
44
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
45
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
46
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
47
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
48
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
49
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
50
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
$:.push(File.dirname(__FILE__) + '/lib')
|
4
|
+
require 'rubygems'
|
5
|
+
require 'hoe'
|
6
|
+
require 'ruby_protobuf'
|
7
|
+
|
8
|
+
Hoe.new('ruby_protobuf', RubyProtobuf::VERSION) do |p|
|
9
|
+
p.rubyforge_name = 'ruby-protobuf'
|
10
|
+
p.author = 'ANDO Yasushi'
|
11
|
+
p.email = 'andyjpn@gmail.com'
|
12
|
+
p.summary = 'Protocol Buffers for Ruby'
|
13
|
+
p.description = p.paragraphs_of('README.txt', 2..5).join("\n\n")
|
14
|
+
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[1..-1]
|
15
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
# vim: syntax=Ruby
|
data/bin/rprotoc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
$: << "#{File.dirname(__FILE__)}/../lib"
|
3
|
+
require 'optparse'
|
4
|
+
require 'ruby_protobuf'
|
5
|
+
|
6
|
+
|
7
|
+
COMMAND_LINE = "#{$0} #{ARGV.join(' ')} PROTO_FILE"
|
8
|
+
OPT = {}
|
9
|
+
opts = OptionParser.new
|
10
|
+
#opts.on('-p', '--proto_path <PATH>', 'Specify the directory in which to search for imports. The current directory is default.'){|v| OPT[:proto_path] = v}
|
11
|
+
opts.on('-o', '--out <OUT_DIR>', 'Specify the directory in which Ruby source file is generated. The current directory is default.'){|v| OPT[:out] = v}
|
12
|
+
opts.on_tail('-v', '--version', 'Show version.'){puts(opts.ver); exit}
|
13
|
+
opts.on_tail('-h', '--help', 'Show this message.'){puts(opts.help); exit}
|
14
|
+
|
15
|
+
::Version = RubyProtobuf::VERSION
|
16
|
+
opts.order! ARGV
|
17
|
+
PROTO_FILE = ARGV.shift
|
18
|
+
|
19
|
+
RubyProtobuf.new.start PROTO_FILE, OPT
|
20
|
+
|
21
|
+
|
data/bin/ruby_protobuf
ADDED
File without changes
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# This is a quite temporary implementation.
|
2
|
+
# I'll create a compiler class using Racc.
|
3
|
+
|
4
|
+
module Protobuf
|
5
|
+
class Compiler
|
6
|
+
INDENT_UNIT = ' '
|
7
|
+
|
8
|
+
def self.compile(filename)
|
9
|
+
self.new.compile filename
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@indent_level = 0
|
14
|
+
@ret = <<-eos
|
15
|
+
require 'protobuf/message'
|
16
|
+
require 'protobuf/enum'
|
17
|
+
require 'protobuf/service'
|
18
|
+
require 'protobuf/extend'
|
19
|
+
|
20
|
+
eos
|
21
|
+
end
|
22
|
+
|
23
|
+
def indent
|
24
|
+
INDENT_UNIT * @indent_level
|
25
|
+
end
|
26
|
+
|
27
|
+
def puts_with_indent(string)
|
28
|
+
#puts "#{indent}#{string}"
|
29
|
+
@ret += "#{indent}#{string}\n"
|
30
|
+
end
|
31
|
+
alias putswi puts_with_indent
|
32
|
+
|
33
|
+
def compile(filename)
|
34
|
+
File.open filename, 'r' do |file|
|
35
|
+
file.each_line do |line|
|
36
|
+
line.sub! /^(.*)\/\/.*/, '\1'
|
37
|
+
line.strip!
|
38
|
+
case line
|
39
|
+
when /^package\s+(\w+(\.\w+)?)\s*;$/
|
40
|
+
$1.split('.').each do |path|
|
41
|
+
putswi "module #{path.capitalize}"
|
42
|
+
@indent_level += 1
|
43
|
+
end
|
44
|
+
when /^message\s+(\w+)\s*\{$/
|
45
|
+
putswi "class #{$1} < Protobuf::Message"
|
46
|
+
@indent_level += 1
|
47
|
+
when /^(required|optional|repeated)\s+(\w+(\.\w+)?)\s+(\w+)\s*=\s*(\d+)\s*(\[\s*default\s*=\s*(\w+)\s*\])?\s*;$/
|
48
|
+
rule, type, name, tag, default = $1, $2, $4, $5, $7
|
49
|
+
if default
|
50
|
+
default = default =~ /\d+(\.\d+)/ \
|
51
|
+
? ", {:default => #{default}}" \
|
52
|
+
: ", {:default => :#{default}}"
|
53
|
+
end
|
54
|
+
putswi "#{rule} :#{type}, :#{name}, #{tag}#{default}"
|
55
|
+
when /^enum\s+(\w+)\s*\{$/
|
56
|
+
putswi "class #{$1} < Protobuf::Enum"
|
57
|
+
@indent_level += 1
|
58
|
+
when /^(\w+)\s*=\s*(\w+)\s*;$/
|
59
|
+
putswi "#{$1} = #{$2}"
|
60
|
+
when /^extensions\s+(\w+)\s+to\s+(\w+)\s*;/
|
61
|
+
low, high = $1, $2
|
62
|
+
low = 'Protobuf::Extend.MIN' if low == 'min'
|
63
|
+
high = 'Protobuf::Extend.MAX' if high == 'max'
|
64
|
+
putswi "extensions #{min}..#{max}"
|
65
|
+
when /^extend\s+(\w+)\s*\{/
|
66
|
+
putswi "class #{$1} < Protobuf::Extend"
|
67
|
+
@indent_level += 1
|
68
|
+
when /^service\s+(\w+)\s*\{/
|
69
|
+
putswi "class #{$1} < Protobuf::Service"
|
70
|
+
@indent_level += 1
|
71
|
+
when /^rpc\s+(\w+)\s+\(\s*(\w+)\s*\)\s+returns\s+\(\s*(\w+)\s*\)\s*;/
|
72
|
+
putswi "rpc :#{$1} => :#{$2}, :#{$3} => :#{$4}"
|
73
|
+
when /^option\s+(\w+)\s*=\s*(.+)\s*;/
|
74
|
+
putswi "Protobuf::OPTIONS[:#{$1}] = :#{$2}"
|
75
|
+
when /^\}$/
|
76
|
+
@indent_level -= 1
|
77
|
+
putswi "end"
|
78
|
+
when ''
|
79
|
+
putswi ''
|
80
|
+
end
|
81
|
+
end
|
82
|
+
while 0 < @indent_level
|
83
|
+
@indent_level -= 1
|
84
|
+
putswi "end"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
@ret
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'protobuf/wire_type'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
class InvalidWireType < StandardError; end
|
5
|
+
|
6
|
+
class Decoder
|
7
|
+
class <<self
|
8
|
+
def decode(stream, message)
|
9
|
+
self.new(stream, message).decode
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(stream=nil, message=nil)
|
14
|
+
@stream, @message = stream, message
|
15
|
+
end
|
16
|
+
|
17
|
+
def decode(stream=@stream, message=@message)
|
18
|
+
until stream.eof?
|
19
|
+
tag, wire_type = read_key stream
|
20
|
+
bytes =
|
21
|
+
case wire_type
|
22
|
+
when WireType::VARINT
|
23
|
+
read_varint stream
|
24
|
+
when WireType::FIXED64
|
25
|
+
read_fixed64 stream
|
26
|
+
when WireType::LENGTH_DELIMITED
|
27
|
+
read_length_delimited stream
|
28
|
+
when WireType::START_GROUP
|
29
|
+
read_start_group stream
|
30
|
+
when WireType::END_GROUP
|
31
|
+
read_end_group stream
|
32
|
+
when WireType::FIXED32
|
33
|
+
read_fixed32 stream
|
34
|
+
else
|
35
|
+
raise InvalidWireType.new(wire_type)
|
36
|
+
end
|
37
|
+
message.set_field tag, bytes
|
38
|
+
end
|
39
|
+
message
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def read_key(stream)
|
45
|
+
bytes = read_varint stream
|
46
|
+
#TODO 1 < bytes.size のときエラー
|
47
|
+
wire_type = bytes[0] & 0b00000111
|
48
|
+
tag = bytes[0] >> 3 # TODO
|
49
|
+
[tag, wire_type]
|
50
|
+
end
|
51
|
+
|
52
|
+
def read_varint(stream)
|
53
|
+
bytes = []
|
54
|
+
begin
|
55
|
+
byte = stream.readchar
|
56
|
+
bytes << (byte & 0b01111111)
|
57
|
+
end while byte >> 7 == 1
|
58
|
+
bytes
|
59
|
+
end
|
60
|
+
|
61
|
+
def read_fixed64(stream)
|
62
|
+
stream.read(8)
|
63
|
+
end
|
64
|
+
|
65
|
+
def read_length_delimited(stream)
|
66
|
+
bytes = read_varint stream
|
67
|
+
value_length = 0
|
68
|
+
bytes.each_with_index do |byte, index|
|
69
|
+
value_length |= byte << (7 * index)
|
70
|
+
end
|
71
|
+
value = stream.read value_length
|
72
|
+
value.unpack('c*')
|
73
|
+
end
|
74
|
+
|
75
|
+
def read_start_group(stream)
|
76
|
+
raise NotImplementedError.new('Group is duplecated.')
|
77
|
+
end
|
78
|
+
|
79
|
+
def read_end_group(stream)
|
80
|
+
raise NotImplementedError.new('Group is duplecated.')
|
81
|
+
end
|
82
|
+
|
83
|
+
def read_fixed32(stream)
|
84
|
+
stream.read(4)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'protobuf/wire_type'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
class Encoder
|
5
|
+
class <<self
|
6
|
+
def encode(stream, message)
|
7
|
+
self.new(stream, message).encode
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(stream=nil, message=nil)
|
12
|
+
@stream, @message = stream, message
|
13
|
+
end
|
14
|
+
|
15
|
+
def encode(stream=@stream, message=@message)
|
16
|
+
message.each_field do |field, value|
|
17
|
+
key = (field.tag << 3) | field.wire_type
|
18
|
+
key_bytes = Protobuf::Field::Int.get_bytes key
|
19
|
+
#stream.write key_bytes.pack('C*')
|
20
|
+
stream.write key_bytes
|
21
|
+
|
22
|
+
if field.repeated?
|
23
|
+
value.each do |val|
|
24
|
+
bytes = field.get val
|
25
|
+
#stream.write bytes.pack('C*')
|
26
|
+
stream.write bytes
|
27
|
+
end
|
28
|
+
else
|
29
|
+
bytes = field.get value
|
30
|
+
#stream.write bytes.pack('C*')
|
31
|
+
stream.write bytes
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,547 @@
|
|
1
|
+
require 'protobuf/wire_type'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Field
|
5
|
+
def self.build(message_class, rule, type, name, tag, opts={})
|
6
|
+
Base.build message_class, rule, type, name, tag, opts
|
7
|
+
end
|
8
|
+
|
9
|
+
class InvalidRuleError < StandardError; end
|
10
|
+
|
11
|
+
class Base
|
12
|
+
class <<self
|
13
|
+
def build(message_class, rule, type, name, tag, opts={})
|
14
|
+
field_class = nil
|
15
|
+
begin
|
16
|
+
field_class = eval "Protobuf::Field::#{type.to_s.capitalize}Field"
|
17
|
+
rescue NameError
|
18
|
+
type = typename_to_class message_class, type
|
19
|
+
field_class =
|
20
|
+
if type.superclass == Protobuf::Enum
|
21
|
+
Protobuf::Field::Enum
|
22
|
+
elsif type.superclass == Protobuf::Message
|
23
|
+
Protobuf::Field::Message
|
24
|
+
else
|
25
|
+
raise $!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
field_class.new message_class, rule, type, name, tag, opts
|
29
|
+
end
|
30
|
+
|
31
|
+
def typename_to_class(message_class, type)
|
32
|
+
modules = message_class.to_s.split('::')
|
33
|
+
while
|
34
|
+
begin
|
35
|
+
type = eval((modules | [type.to_s]).join('::'))
|
36
|
+
break
|
37
|
+
rescue NameError
|
38
|
+
modules.empty? ? raise($!) : modules.pop
|
39
|
+
end
|
40
|
+
end
|
41
|
+
type
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_accessor :message_class, :rule, :type, :name, :tag, :default
|
46
|
+
|
47
|
+
def initialize(message_class, rule, type, name, tag, opts={})
|
48
|
+
@message_class, @rule, @type, @name, @tag, @default =
|
49
|
+
message_class, rule, type, name, tag, opts[:default]
|
50
|
+
@error_message = 'Type invalid'
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_value
|
54
|
+
case rule
|
55
|
+
when :repeated
|
56
|
+
FieldArray.new self
|
57
|
+
when :required, :optional
|
58
|
+
typed_default_value default
|
59
|
+
else
|
60
|
+
raise InvalidRuleError
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def typed_default_value(default=nil)
|
65
|
+
default
|
66
|
+
end
|
67
|
+
|
68
|
+
def define_accessor(message_instance)
|
69
|
+
message_instance.instance_variable_set "@#{name}", default_value
|
70
|
+
define_getter message_instance
|
71
|
+
define_setter message_instance unless rule == :repeated
|
72
|
+
end
|
73
|
+
|
74
|
+
def define_getter(message_instance)
|
75
|
+
message_instance.instance_eval %Q{
|
76
|
+
def #{name}
|
77
|
+
@#{name}
|
78
|
+
end
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def define_setter(message_instance)
|
83
|
+
message_instance.instance_eval %Q{
|
84
|
+
def #{name}=(val)
|
85
|
+
field = get_field_by_name #{name.inspect}
|
86
|
+
if field.acceptable? val
|
87
|
+
@#{name} = val
|
88
|
+
end
|
89
|
+
end
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def set(message_instance, bytes)
|
94
|
+
if repeated?
|
95
|
+
set_array message_instance, bytes
|
96
|
+
else
|
97
|
+
set_bytes message_instance, bytes
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def set_array(message_instance, bytes)
|
102
|
+
raise NotImplementedError
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_bytes(message_instance, bytes)
|
106
|
+
raise NotImplementedError
|
107
|
+
end
|
108
|
+
|
109
|
+
def get(value)
|
110
|
+
get_bytes value
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_bytes(value)
|
114
|
+
raise NotImplementedError
|
115
|
+
end
|
116
|
+
|
117
|
+
def merge(message_instance, bytes)
|
118
|
+
if repeated?
|
119
|
+
merge_array method_instance, bytes
|
120
|
+
else
|
121
|
+
merge_value method_instance, bytes
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def merge_array(message_instance, bytes)
|
126
|
+
raise NotImplementedError
|
127
|
+
end
|
128
|
+
|
129
|
+
def merge_value(message_instance, bytes)
|
130
|
+
raise NotImplementedError
|
131
|
+
end
|
132
|
+
|
133
|
+
def repeated?; rule == :repeated end
|
134
|
+
def required?; rule == :required end
|
135
|
+
def optional?; rule == :optional end
|
136
|
+
|
137
|
+
def max; self.class.max end
|
138
|
+
def min; self.class.min end
|
139
|
+
|
140
|
+
def acceptable?(val)
|
141
|
+
true
|
142
|
+
end
|
143
|
+
|
144
|
+
def error_message
|
145
|
+
@error_message
|
146
|
+
end
|
147
|
+
|
148
|
+
def to_s
|
149
|
+
"#{rule} #{type} #{name} = #{tag} #{default ? "[default=#{default}]" : ''}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
class FieldArray < Array
|
154
|
+
def initialize(field)
|
155
|
+
@field = field
|
156
|
+
end
|
157
|
+
|
158
|
+
def []=(nth, val)
|
159
|
+
if @field.acceptable? val
|
160
|
+
super
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def <<(val)
|
165
|
+
if @field.acceptable? val
|
166
|
+
super
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def push(val)
|
171
|
+
if @field.acceptable? val
|
172
|
+
super
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def unshift(val)
|
177
|
+
if @field.acceptable? val
|
178
|
+
super
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def to_s
|
183
|
+
"[#{@field.name}]"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class StringField < Base
|
188
|
+
def wire_type
|
189
|
+
Protobuf::WireType::LENGTH_DELIMITED
|
190
|
+
end
|
191
|
+
|
192
|
+
def typed_default_value(default=nil)
|
193
|
+
default or ''
|
194
|
+
end
|
195
|
+
|
196
|
+
def acceptable?(val)
|
197
|
+
raise TypeError unless val.instance_of? String
|
198
|
+
true
|
199
|
+
end
|
200
|
+
|
201
|
+
def set_bytes(method_instance, bytes)
|
202
|
+
method_instance.send("#{name}=", bytes.pack('U*'))
|
203
|
+
end
|
204
|
+
|
205
|
+
def get_bytes(value)
|
206
|
+
bytes = value.unpack('U*')
|
207
|
+
string_size = Int.get_bytes bytes.size
|
208
|
+
#(string_size + bytes).pack('C*')
|
209
|
+
string_size + bytes.pack('C*')
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class BytesField < Base
|
214
|
+
def wire_type
|
215
|
+
Protobuf::WireType::VARINT
|
216
|
+
end
|
217
|
+
|
218
|
+
def typed_default_value(default=nil)
|
219
|
+
default or []
|
220
|
+
end
|
221
|
+
|
222
|
+
def set_bytes(method_instance, bytes)
|
223
|
+
method_instance.send("#{name}=", bytes)
|
224
|
+
end
|
225
|
+
|
226
|
+
def get_bytes(value)
|
227
|
+
string_size = Int.get_bytes value.size
|
228
|
+
string_size + value.pack('C*')
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class Int < Base
|
233
|
+
def wire_type
|
234
|
+
Protobuf::WireType::VARINT
|
235
|
+
end
|
236
|
+
|
237
|
+
def typed_default_value(default=nil)
|
238
|
+
default or 0
|
239
|
+
end
|
240
|
+
|
241
|
+
def set_bytes(method_instance, bytes)
|
242
|
+
# TODO should refactor using pack('w*')
|
243
|
+
value = 0
|
244
|
+
bytes.each_with_index do |byte, index|
|
245
|
+
value |= byte << (7 * index)
|
246
|
+
end
|
247
|
+
method_instance.send("#{name}=", value)
|
248
|
+
end
|
249
|
+
|
250
|
+
def self.get_bytes(value)
|
251
|
+
# TODO should refactor using unpack('w*')
|
252
|
+
#return [value].pack('w*').unpack('C*')
|
253
|
+
return [0].pack('C') if value == 0
|
254
|
+
bytes = []
|
255
|
+
until value == 0
|
256
|
+
byte = 0
|
257
|
+
7.times do |i|
|
258
|
+
byte |= (value & 1) << i
|
259
|
+
value >>= 1
|
260
|
+
end
|
261
|
+
byte |= 0b10000000
|
262
|
+
bytes << byte
|
263
|
+
end
|
264
|
+
#bytes[0] &= 0b01111111
|
265
|
+
#bytes
|
266
|
+
bytes[bytes.size - 1] &= 0b01111111
|
267
|
+
bytes.pack('C*')
|
268
|
+
end
|
269
|
+
|
270
|
+
def get_bytes(value)
|
271
|
+
self.class.get_bytes value
|
272
|
+
end
|
273
|
+
|
274
|
+
def acceptable?(val)
|
275
|
+
raise TypeError.new(val.class.name) unless val.is_a? Integer
|
276
|
+
raise RangeError.new(val) if val < min or max < val
|
277
|
+
true
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
class Int32Field < Int
|
282
|
+
def self.max; 1.0/0.0 end
|
283
|
+
def self.min; -1.0/0.0 end
|
284
|
+
end
|
285
|
+
|
286
|
+
class Int64Field < Int
|
287
|
+
def self.max; 1.0/0.0 end
|
288
|
+
def self.min; -1.0/0.0 end
|
289
|
+
end
|
290
|
+
|
291
|
+
class Uint32Field < Int
|
292
|
+
def self.max; 1.0/0.0 end
|
293
|
+
def self.min; 0 end
|
294
|
+
end
|
295
|
+
|
296
|
+
class Uint64Field < Int
|
297
|
+
def self.max; 1.0/0.0 end
|
298
|
+
def self.min; 0 end
|
299
|
+
end
|
300
|
+
|
301
|
+
class Sint32Field < Int
|
302
|
+
def self.max; 1.0/0.0 end
|
303
|
+
def self.min; -1.0/0.0 end
|
304
|
+
|
305
|
+
def set_bytes(method_instance, bytes)
|
306
|
+
# TODO use only bit-operations
|
307
|
+
byte = bytes.first
|
308
|
+
value =
|
309
|
+
if byte % 2 == 0
|
310
|
+
byte / 2
|
311
|
+
else
|
312
|
+
-(byte + 1) / 2
|
313
|
+
end
|
314
|
+
method_instance.send("#{name}=", value)
|
315
|
+
end
|
316
|
+
|
317
|
+
def get_bytes(value)
|
318
|
+
#(value << 1) ^ (value >> 31)
|
319
|
+
[(value << 1) ^ (value >> 31)].pack('C*')
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
class Sint64Field < Int
|
324
|
+
def self.max; 1.0/0.0 end
|
325
|
+
def self.min; -1.0/0.0 end
|
326
|
+
|
327
|
+
def set_bytes(method_instance, bytes)
|
328
|
+
# TODO use only bit-operations
|
329
|
+
byte = bytes.first
|
330
|
+
value =
|
331
|
+
if byte % 2 == 0
|
332
|
+
byte / 2
|
333
|
+
else
|
334
|
+
-(byte + 1) / 2
|
335
|
+
end
|
336
|
+
method_instance.send("#{name}=", value)
|
337
|
+
end
|
338
|
+
|
339
|
+
def get_bytes(value)
|
340
|
+
#(value << 1) ^ (value >> 63)
|
341
|
+
[(value << 1) ^ (value >> 63)].pack('C*')
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
class DoubleField < Int
|
346
|
+
def wire_type
|
347
|
+
Protobuf::WireType::FIXED64
|
348
|
+
end
|
349
|
+
|
350
|
+
#TODO
|
351
|
+
def self.max
|
352
|
+
'0x7fefffffffffffff'.unpack('d').first
|
353
|
+
end
|
354
|
+
|
355
|
+
#TODO
|
356
|
+
def self.min
|
357
|
+
-(2**(64/2) - 1)
|
358
|
+
end
|
359
|
+
|
360
|
+
def set_bytes(method_instance, bytes)
|
361
|
+
method_instance.send("#{name}=", bytes.unpack('E').first)
|
362
|
+
end
|
363
|
+
|
364
|
+
def get_bytes(value)
|
365
|
+
[value].pack('E')
|
366
|
+
end
|
367
|
+
|
368
|
+
def acceptable?(val)
|
369
|
+
raise TypeError.new(val.class.name) unless val.is_a? Numeric
|
370
|
+
raise RangeError.new(val) if val < min or max < val
|
371
|
+
true
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
class FloatField < Int
|
376
|
+
def wire_type
|
377
|
+
Protobuf::WireType::FIXED32
|
378
|
+
end
|
379
|
+
|
380
|
+
#TODO
|
381
|
+
def self.max
|
382
|
+
'0x7fefffffffffffff'.unpack('e').first
|
383
|
+
end
|
384
|
+
|
385
|
+
#TODO
|
386
|
+
def self.min
|
387
|
+
-(2**(32/2) - 1)
|
388
|
+
end
|
389
|
+
|
390
|
+
def set_bytes(method_instance, bytes)
|
391
|
+
method_instance.send("#{name}=", bytes.unpack('e').first)
|
392
|
+
end
|
393
|
+
|
394
|
+
def get_bytes(value)
|
395
|
+
[value].pack('e')
|
396
|
+
end
|
397
|
+
|
398
|
+
def acceptable?(val)
|
399
|
+
raise TypeError unless val.is_a? Numeric
|
400
|
+
raise RangeError if val < min or max < val
|
401
|
+
true
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
class Fixed32Field < Int
|
406
|
+
def wire_type
|
407
|
+
Protobuf::WireType::FIXED32
|
408
|
+
end
|
409
|
+
|
410
|
+
def self.max
|
411
|
+
2**32
|
412
|
+
end
|
413
|
+
|
414
|
+
def self.min
|
415
|
+
0
|
416
|
+
end
|
417
|
+
|
418
|
+
def set_bytes(method_instance, bytes)
|
419
|
+
method_instance.send("#{name}=", bytes.unpack('L').first)
|
420
|
+
end
|
421
|
+
|
422
|
+
def get_bytes(value)
|
423
|
+
[value].pack('L')
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
class Fixed64Field < Int
|
428
|
+
def wire_type
|
429
|
+
Protobuf::WireType::FIXED64
|
430
|
+
end
|
431
|
+
|
432
|
+
def self.max
|
433
|
+
2**64
|
434
|
+
end
|
435
|
+
|
436
|
+
def self.min
|
437
|
+
0
|
438
|
+
end
|
439
|
+
|
440
|
+
def set_bytes(method_instance, bytes)
|
441
|
+
method_instance.send("#{name}=", bytes.unpack('l').first)
|
442
|
+
end
|
443
|
+
|
444
|
+
def get_bytes(value)
|
445
|
+
[value].pack('Q')
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
class Sfinxed32Field < Int
|
450
|
+
def wire_type
|
451
|
+
Protobuf::WireType::FIXED32
|
452
|
+
end
|
453
|
+
|
454
|
+
def self.max
|
455
|
+
2**(32/2)
|
456
|
+
end
|
457
|
+
|
458
|
+
def self.min
|
459
|
+
-(2**(32/2) - 1)
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
class Sfixed64Field < Int
|
464
|
+
def wire_type
|
465
|
+
Protobuf::WireType::FIXED64
|
466
|
+
end
|
467
|
+
|
468
|
+
def self.max
|
469
|
+
2**(64/2)
|
470
|
+
end
|
471
|
+
|
472
|
+
def self.min
|
473
|
+
-(2**(64/2) - 1)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
class BoolField < Int
|
478
|
+
def typed_default_value(default=nil)
|
479
|
+
default or false
|
480
|
+
end
|
481
|
+
|
482
|
+
def acceptable?(val)
|
483
|
+
raise TypeError unless [TrueClass, FalseClass].include? val.class
|
484
|
+
true
|
485
|
+
end
|
486
|
+
|
487
|
+
def set_bytes(method_instance, bytes)
|
488
|
+
method_instance.send("#{name}=", bytes.first == 1)
|
489
|
+
end
|
490
|
+
|
491
|
+
def get_bytes(value)
|
492
|
+
[value ? 1 : 0].pack('C')
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
class Message < Base
|
497
|
+
def wire_type
|
498
|
+
Protobuf::WireType::LENGTH_DELIMITED
|
499
|
+
end
|
500
|
+
|
501
|
+
def typed_default_value(default=nil)
|
502
|
+
if default.is_a? Symbol
|
503
|
+
type.module_eval default.to_s
|
504
|
+
else
|
505
|
+
default
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
def acceptable?(val)
|
510
|
+
raise TypeError unless val.instance_of? type
|
511
|
+
true
|
512
|
+
end
|
513
|
+
|
514
|
+
def set_bytes(method_instance, bytes)
|
515
|
+
message = type.new
|
516
|
+
#message.parse_from bytes
|
517
|
+
message.parse_from_string bytes.pack('U*') # TODO
|
518
|
+
method_instance.send("#{name}=", message)
|
519
|
+
end
|
520
|
+
|
521
|
+
def set_array(method_instance, bytes)
|
522
|
+
message = type.new
|
523
|
+
#message.parse_from bytes
|
524
|
+
message.parse_from_string bytes.pack('U*')
|
525
|
+
arr = method_instance.send name
|
526
|
+
arr << message
|
527
|
+
end
|
528
|
+
|
529
|
+
def get_bytes(value)
|
530
|
+
stringio = StringIO.new ''
|
531
|
+
value.serialize_to stringio
|
532
|
+
bytes = stringio.string.unpack 'C*'
|
533
|
+
string_size = Int.get_bytes bytes.size
|
534
|
+
#(string_size + bytes).pack('C*')
|
535
|
+
#bytes + string_size
|
536
|
+
string_size + bytes.pack('C*')
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
class Enum < Int
|
541
|
+
def acceptable?(val)
|
542
|
+
raise TypeError unless type.valid_tag? val
|
543
|
+
true
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
547
|
+
end
|