macks-ruby_protobuf 0.3.2.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 +14 -0
- data/Manifest.txt +74 -0
- data/README.txt +58 -0
- data/Rakefile +18 -0
- data/bin/mk_parser +2 -0
- data/bin/rprotoc +36 -0
- data/examples/addressbook.pb.rb +56 -0
- data/examples/addressbook.proto +24 -0
- data/examples/reading_a_message.rb +32 -0
- data/examples/writing_a_message.rb +46 -0
- data/lib/protobuf/common/wire_type.rb +10 -0
- data/lib/protobuf/compiler/compiler.rb +54 -0
- data/lib/protobuf/compiler/nodes.rb +319 -0
- data/lib/protobuf/compiler/proto.y +203 -0
- data/lib/protobuf/compiler/proto2.ebnf +79 -0
- data/lib/protobuf/compiler/proto_parser.rb +1394 -0
- data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
- data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
- data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
- data/lib/protobuf/compiler/visitors.rb +288 -0
- data/lib/protobuf/descriptor/descriptor.proto +286 -0
- data/lib/protobuf/descriptor/descriptor.rb +54 -0
- data/lib/protobuf/descriptor/descriptor_builder.rb +144 -0
- data/lib/protobuf/descriptor/descriptor_proto.rb +119 -0
- data/lib/protobuf/descriptor/enum_descriptor.rb +33 -0
- data/lib/protobuf/descriptor/field_descriptor.rb +50 -0
- data/lib/protobuf/descriptor/file_descriptor.rb +38 -0
- data/lib/protobuf/message/decoder.rb +93 -0
- data/lib/protobuf/message/encoder.rb +37 -0
- data/lib/protobuf/message/enum.rb +28 -0
- data/lib/protobuf/message/extend.rb +8 -0
- data/lib/protobuf/message/field.rb +654 -0
- data/lib/protobuf/message/message.rb +308 -0
- data/lib/protobuf/message/protoable.rb +37 -0
- data/lib/protobuf/message/service.rb +9 -0
- data/lib/protobuf/rpc/client.rb +19 -0
- data/lib/protobuf/rpc/handler.rb +17 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/ruby_protobuf.rb +3 -0
- data/test/addressbook.rb +98 -0
- data/test/addressbook_base.rb +62 -0
- data/test/addressbook_ext.rb +12 -0
- data/test/check_unbuild.rb +30 -0
- data/test/collision.rb +18 -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/data/unk.png +0 -0
- data/test/ext_collision.rb +25 -0
- data/test/ext_range.rb +23 -0
- data/test/merge.rb +40 -0
- data/test/nested.rb +25 -0
- data/test/proto/addressbook.proto +31 -0
- data/test/proto/addressbook_base.proto +26 -0
- data/test/proto/addressbook_ext.proto +6 -0
- data/test/proto/collision.proto +5 -0
- data/test/proto/ext_collision.proto +8 -0
- data/test/proto/ext_range.proto +7 -0
- data/test/proto/merge.proto +15 -0
- data/test/proto/nested.proto +7 -0
- data/test/proto/rpc.proto +6 -0
- data/test/proto/types.proto +17 -0
- data/test/test_addressbook.rb +43 -0
- data/test/test_compiler.rb +313 -0
- data/test/test_descriptor.rb +122 -0
- data/test/test_extension.rb +40 -0
- data/test/test_message.rb +106 -0
- data/test/test_optional_field.rb +68 -0
- data/test/test_parse.rb +15 -0
- data/test/test_ruby_protobuf.rb +1 -0
- data/test/test_serialize.rb +42 -0
- data/test/test_standard_message.rb +96 -0
- data/test/test_types.rb +181 -0
- data/test/types.rb +22 -0
- metadata +150 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'protobuf/descriptor/file_descriptor'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Descriptor
|
5
|
+
def self.id2type(type_id)
|
6
|
+
require 'protobuf/descriptor/descriptor_proto'
|
7
|
+
case type_id
|
8
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_DOUBLE
|
9
|
+
:double
|
10
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FLOAT
|
11
|
+
:float
|
12
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
|
13
|
+
:int64
|
14
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT64
|
15
|
+
:unit64
|
16
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32
|
17
|
+
:int64
|
18
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED64
|
19
|
+
:fixed64
|
20
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED32
|
21
|
+
:fixed32
|
22
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BOOL
|
23
|
+
:bool
|
24
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
|
25
|
+
:string
|
26
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_GROUP
|
27
|
+
:group
|
28
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
|
29
|
+
:message
|
30
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BYTES
|
31
|
+
:bytes
|
32
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT32
|
33
|
+
:uint32
|
34
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM
|
35
|
+
:enum
|
36
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED32
|
37
|
+
:sfixed32
|
38
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED64
|
39
|
+
:sfixed64
|
40
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT32
|
41
|
+
:sint32
|
42
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT64
|
43
|
+
:sint64
|
44
|
+
else
|
45
|
+
raise ArgumentError.new("Invalid type: #{proto.type}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.type2id(type)
|
50
|
+
require 'protobuf/descriptor/descriptor_proto'
|
51
|
+
case type
|
52
|
+
when :double
|
53
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_DOUBLE
|
54
|
+
when :float
|
55
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_FLOAT
|
56
|
+
when :int64
|
57
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
|
58
|
+
when :unit64
|
59
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT64
|
60
|
+
when :int64
|
61
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32
|
62
|
+
when :fixed64
|
63
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED64
|
64
|
+
when :fixed32
|
65
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED32
|
66
|
+
when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BOOL
|
67
|
+
:bool
|
68
|
+
when :string
|
69
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
|
70
|
+
when :group
|
71
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_GROUP
|
72
|
+
when :message
|
73
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
|
74
|
+
when :bytes
|
75
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_BYTES
|
76
|
+
when :uint32
|
77
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT32
|
78
|
+
when :enum
|
79
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM
|
80
|
+
when :sfixed32
|
81
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED32
|
82
|
+
when :sfixed64
|
83
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED64
|
84
|
+
when :sint32
|
85
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT32
|
86
|
+
when :sint64
|
87
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT64
|
88
|
+
else
|
89
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.id2label(label_id)
|
94
|
+
require 'protobuf/descriptor/descriptor_proto'
|
95
|
+
case label_id
|
96
|
+
when Google::Protobuf::FieldDescriptorProto::Label::LABEL_REQUIRED
|
97
|
+
:required
|
98
|
+
when Google::Protobuf::FieldDescriptorProto::Label::LABEL_OPTIONAL
|
99
|
+
:optional
|
100
|
+
when Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED
|
101
|
+
:repeated
|
102
|
+
else
|
103
|
+
raise ArgumentError.new("Invalid label: #{proto.label}")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.label2id(label)
|
108
|
+
require 'protobuf/descriptor/descriptor_proto'
|
109
|
+
case label
|
110
|
+
when :required
|
111
|
+
Google::Protobuf::FieldDescriptorProto::Label::LABEL_REQUIRED
|
112
|
+
when :optional
|
113
|
+
Google::Protobuf::FieldDescriptorProto::Label::LABEL_OPTIONAL
|
114
|
+
when :repeated
|
115
|
+
Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED
|
116
|
+
else
|
117
|
+
raise ArgumentError.new("Invalid label: #{label}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class DescriptorBuilder
|
122
|
+
class <<self
|
123
|
+
|
124
|
+
def proto_type
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
|
128
|
+
def build(proto, opt={})
|
129
|
+
acceptable_descriptor(proto).build proto
|
130
|
+
end
|
131
|
+
|
132
|
+
def acceptable_descriptor(proto)
|
133
|
+
Protobuf::Descriptor.constants.each do |class_name|
|
134
|
+
descriptor_class = Protobuf::Descriptor.const_get class_name
|
135
|
+
if descriptor_class.respond_to?(:proto_type) and
|
136
|
+
descriptor_class.proto_type == proto.class.name
|
137
|
+
return descriptor_class
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'protobuf/message/message'
|
2
|
+
require 'protobuf/message/enum'
|
3
|
+
require 'protobuf/message/service'
|
4
|
+
require 'protobuf/message/extend'
|
5
|
+
module Google
|
6
|
+
module Protobuf
|
7
|
+
::Protobuf::OPTIONS[:java_package] = :"com.google.protobuf"
|
8
|
+
::Protobuf::OPTIONS[:java_outer_classname] = :"DescriptorProtos"
|
9
|
+
::Protobuf::OPTIONS[:optimize_for] = :SPEED
|
10
|
+
class FileDescriptorProto < ::Protobuf::Message
|
11
|
+
optional :string, :name, 1
|
12
|
+
optional :string, :package, 2
|
13
|
+
repeated :string, :dependency, 3
|
14
|
+
repeated :DescriptorProto, :message_type, 4
|
15
|
+
repeated :EnumDescriptorProto, :enum_type, 5
|
16
|
+
repeated :ServiceDescriptorProto, :service, 6
|
17
|
+
repeated :FieldDescriptorProto, :extension, 7
|
18
|
+
optional :FileOptions, :options, 8
|
19
|
+
end
|
20
|
+
class DescriptorProto < ::Protobuf::Message
|
21
|
+
optional :string, :name, 1
|
22
|
+
repeated :FieldDescriptorProto, :field, 2
|
23
|
+
repeated :FieldDescriptorProto, :extension, 6
|
24
|
+
repeated :DescriptorProto, :nested_type, 3
|
25
|
+
repeated :EnumDescriptorProto, :enum_type, 4
|
26
|
+
class ExtensionRange < ::Protobuf::Message
|
27
|
+
optional :int32, :start, 1
|
28
|
+
optional :int32, :end, 2
|
29
|
+
end
|
30
|
+
repeated :ExtensionRange, :extension_range, 5
|
31
|
+
optional :MessageOptions, :options, 7
|
32
|
+
end
|
33
|
+
class FieldDescriptorProto < ::Protobuf::Message
|
34
|
+
class Type < ::Protobuf::Enum
|
35
|
+
TYPE_DOUBLE = 1
|
36
|
+
TYPE_FLOAT = 2
|
37
|
+
TYPE_INT64 = 3
|
38
|
+
TYPE_UINT64 = 4
|
39
|
+
TYPE_INT32 = 5
|
40
|
+
TYPE_FIXED64 = 6
|
41
|
+
TYPE_FIXED32 = 7
|
42
|
+
TYPE_BOOL = 8
|
43
|
+
TYPE_STRING = 9
|
44
|
+
TYPE_GROUP = 10
|
45
|
+
TYPE_MESSAGE = 11
|
46
|
+
TYPE_BYTES = 12
|
47
|
+
TYPE_UINT32 = 13
|
48
|
+
TYPE_ENUM = 14
|
49
|
+
TYPE_SFIXED32 = 15
|
50
|
+
TYPE_SFIXED64 = 16
|
51
|
+
TYPE_SINT32 = 17
|
52
|
+
TYPE_SINT64 = 18
|
53
|
+
end
|
54
|
+
class Label < ::Protobuf::Enum
|
55
|
+
LABEL_OPTIONAL = 1
|
56
|
+
LABEL_REQUIRED = 2
|
57
|
+
LABEL_REPEATED = 3
|
58
|
+
end
|
59
|
+
optional :string, :name, 1
|
60
|
+
optional :int32, :number, 3
|
61
|
+
optional :Label, :label, 4
|
62
|
+
optional :Type, :type, 5
|
63
|
+
optional :string, :type_name, 6
|
64
|
+
optional :string, :extendee, 2
|
65
|
+
optional :string, :default_value, 7
|
66
|
+
optional :FieldOptions, :options, 8
|
67
|
+
end
|
68
|
+
class EnumDescriptorProto < ::Protobuf::Message
|
69
|
+
optional :string, :name, 1
|
70
|
+
repeated :EnumValueDescriptorProto, :value, 2
|
71
|
+
optional :EnumOptions, :options, 3
|
72
|
+
end
|
73
|
+
class EnumValueDescriptorProto < ::Protobuf::Message
|
74
|
+
optional :string, :name, 1
|
75
|
+
optional :int32, :number, 2
|
76
|
+
optional :EnumValueOptions, :options, 3
|
77
|
+
end
|
78
|
+
class ServiceDescriptorProto < ::Protobuf::Message
|
79
|
+
optional :string, :name, 1
|
80
|
+
repeated :MethodDescriptorProto, :method, 2
|
81
|
+
optional :ServiceOptions, :options, 3
|
82
|
+
end
|
83
|
+
class MethodDescriptorProto < ::Protobuf::Message
|
84
|
+
optional :string, :name, 1
|
85
|
+
optional :string, :input_type, 2
|
86
|
+
optional :string, :output_type, 3
|
87
|
+
optional :MethodOptions, :options, 4
|
88
|
+
end
|
89
|
+
class FileOptions < ::Protobuf::Message
|
90
|
+
optional :string, :java_package, 1
|
91
|
+
optional :string, :java_outer_classname, 8
|
92
|
+
optional :bool, :java_multiple_files, 10, {:default => :false}
|
93
|
+
class OptimizeMode < ::Protobuf::Enum
|
94
|
+
SPEED = 1
|
95
|
+
CODE_SIZE = 2
|
96
|
+
end
|
97
|
+
optional :OptimizeMode, :optimize_for, 9, {:default => :CODE_SIZE}
|
98
|
+
end
|
99
|
+
class MessageOptions < ::Protobuf::Message
|
100
|
+
optional :bool, :message_set_wire_format, 1, {:default => :false}
|
101
|
+
end
|
102
|
+
class FieldOptions < ::Protobuf::Message
|
103
|
+
optional :CType, :ctype, 1
|
104
|
+
class CType < ::Protobuf::Enum
|
105
|
+
CORD = 1
|
106
|
+
STRING_PIECE = 2
|
107
|
+
end
|
108
|
+
optional :string, :experimental_map_key, 9
|
109
|
+
end
|
110
|
+
class EnumOptions < ::Protobuf::Message
|
111
|
+
end
|
112
|
+
class EnumValueOptions < ::Protobuf::Message
|
113
|
+
end
|
114
|
+
class ServiceOptions < ::Protobuf::Message
|
115
|
+
end
|
116
|
+
class MethodOptions < ::Protobuf::Message
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Descriptor
|
3
|
+
class EnumDescriptor
|
4
|
+
def initialize(enum_class)
|
5
|
+
@enum_class = enum_class
|
6
|
+
end
|
7
|
+
|
8
|
+
def proto_type
|
9
|
+
Google::Protobuf::EnumDescriptorProto
|
10
|
+
end
|
11
|
+
|
12
|
+
def build(proto, opt)
|
13
|
+
mod = opt[:module]
|
14
|
+
cls = mod.const_set proto.name, Class.new(Protobuf::Enum)
|
15
|
+
proto.value.each do |value_proto|
|
16
|
+
cls.const_set value_proto.name, value_proto.number
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def unbuild(parent_proto)
|
21
|
+
enum_proto = Google::Protobuf::EnumDescriptorProto.new
|
22
|
+
enum_proto.name = @enum_class.name.split('::').last
|
23
|
+
@enum_class.constants.each do |const|
|
24
|
+
enum_value_proto = Google::Protobuf::EnumValueDescriptorProto.new
|
25
|
+
enum_value_proto.name = const.to_s
|
26
|
+
enum_value_proto.number = @enum_class.const_get const
|
27
|
+
enum_proto.value << enum_value_proto
|
28
|
+
end
|
29
|
+
parent_proto.enum_type << enum_proto
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Descriptor
|
3
|
+
class FieldDescriptor
|
4
|
+
def initialize(field_instance=nil)
|
5
|
+
@field_instance = field_instance
|
6
|
+
end
|
7
|
+
|
8
|
+
def proto_type
|
9
|
+
'Google::Protobuf::FieldDescriptorProto'
|
10
|
+
end
|
11
|
+
|
12
|
+
def build(proto, opt={})
|
13
|
+
cls = opt[:class]
|
14
|
+
rule = Protobuf::Descriptor.id2label proto.label
|
15
|
+
type = Protobuf::Descriptor.id2type proto.type
|
16
|
+
type = proto.type_name.to_sym if [:message, :enum].include? type
|
17
|
+
opts = {}
|
18
|
+
opts[:default] = proto.default_value if proto.default_value
|
19
|
+
cls.define_field rule, type, proto.name, proto.number, opts
|
20
|
+
end
|
21
|
+
|
22
|
+
def unbuild(parent_proto, extension=false)
|
23
|
+
field_proto = Google::Protobuf::FieldDescriptorProto.new
|
24
|
+
field_proto.name = @field_instance.name.to_s
|
25
|
+
field_proto.number = @field_instance.tag
|
26
|
+
field_proto.label = Protobuf::Descriptor.label2id @field_instance.rule
|
27
|
+
field_proto.type = Protobuf::Descriptor.type2id @field_instance.type
|
28
|
+
if [Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE,
|
29
|
+
Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM].include? field_proto.type
|
30
|
+
field_proto.type_name = @field_instance.type.to_s.split('::').last
|
31
|
+
end
|
32
|
+
field_proto.default_value = @field_instance.default.to_s if @field_instance.default
|
33
|
+
|
34
|
+
case parent_proto
|
35
|
+
when Google::Protobuf::FileDescriptorProto
|
36
|
+
parent_proto.extension << field_proto
|
37
|
+
when Google::Protobuf::DescriptorProto
|
38
|
+
if extension
|
39
|
+
parent_proto.extension << field_proto
|
40
|
+
else
|
41
|
+
parent_proto.field << field_proto
|
42
|
+
end
|
43
|
+
else
|
44
|
+
raise TypeError.new(parent_proto.class.name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Descriptor
|
3
|
+
class FileDescriptor
|
4
|
+
class <<self
|
5
|
+
def proto_type
|
6
|
+
'Google::Protobuf::FileDescriptorProto'
|
7
|
+
end
|
8
|
+
|
9
|
+
def build(proto, opt={})
|
10
|
+
mod = Object
|
11
|
+
if package = proto.package and not package.empty?
|
12
|
+
module_names = package.split '::'
|
13
|
+
module_names.each do |module_name|
|
14
|
+
mod = mod.const_set module_name, Module.new
|
15
|
+
end
|
16
|
+
end
|
17
|
+
proto.message_type.each do |message_proto|
|
18
|
+
Protobuf::Message.descriptor.build message_proto, :module => mod
|
19
|
+
end
|
20
|
+
proto.enum_type.each do |enum_proto|
|
21
|
+
Protobuf::Enum.descriptor.build enum_proto, :module => mod
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def unbuild(messages)
|
26
|
+
messages = [messages] unless messages.is_a? Array
|
27
|
+
proto = Google::Protobuf::FileDescriptorProto.new
|
28
|
+
proto.package = messages.first.to_s.split('::')[0..-2].join('::') if messages.first.to_s =~ /::/
|
29
|
+
messages.each do |message|
|
30
|
+
message.descriptor.unbuild proto
|
31
|
+
end
|
32
|
+
proto
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'protobuf/common/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
|
+
# TODO is there more clear way to do this?
|
46
|
+
bits = 0
|
47
|
+
bytes = read_varint stream
|
48
|
+
bytes.each_with_index do |byte, index|
|
49
|
+
byte &= 0b01111111
|
50
|
+
bits |= byte << (7 * index)
|
51
|
+
end
|
52
|
+
wire_type = bits & 0b00000111
|
53
|
+
tag = bits >> 3
|
54
|
+
[tag, wire_type]
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_varint(stream)
|
58
|
+
read_method = stream.respond_to?(:readbyte) ? :readbyte : :readchar
|
59
|
+
bytes = []
|
60
|
+
begin
|
61
|
+
byte = stream.send(read_method)
|
62
|
+
bytes << (byte & 0b01111111)
|
63
|
+
end while byte >> 7 == 1
|
64
|
+
bytes
|
65
|
+
end
|
66
|
+
|
67
|
+
def read_fixed64(stream)
|
68
|
+
stream.read(8)
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_length_delimited(stream)
|
72
|
+
bytes = read_varint stream
|
73
|
+
value_length = 0
|
74
|
+
bytes.each_with_index do |byte, index|
|
75
|
+
value_length |= byte << (7 * index)
|
76
|
+
end
|
77
|
+
value = stream.read value_length
|
78
|
+
value.unpack('C*')
|
79
|
+
end
|
80
|
+
|
81
|
+
def read_start_group(stream)
|
82
|
+
raise NotImplementedError.new('Group is duplecated.')
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_end_group(stream)
|
86
|
+
raise NotImplementedError.new('Group is duplecated.')
|
87
|
+
end
|
88
|
+
|
89
|
+
def read_fixed32(stream)
|
90
|
+
stream.read(4)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'protobuf/common/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
|
+
next unless message.has_field?(field.name)
|
18
|
+
|
19
|
+
if field.repeated?
|
20
|
+
value.each do |val|
|
21
|
+
write_pair field, val, stream
|
22
|
+
end
|
23
|
+
else
|
24
|
+
write_pair field, value, stream
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def write_pair(field, value, stream)
|
30
|
+
key = (field.tag << 3) | field.wire_type
|
31
|
+
key_bytes = Protobuf::Field::VarintField.get_bytes key
|
32
|
+
stream.write key_bytes
|
33
|
+
bytes = field.get value
|
34
|
+
stream.write bytes
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'protobuf/descriptor/enum_descriptor'
|
2
|
+
require 'protobuf/message/protoable'
|
3
|
+
|
4
|
+
module Protobuf
|
5
|
+
class Enum
|
6
|
+
class <<self
|
7
|
+
include Protobuf::Protoable
|
8
|
+
|
9
|
+
def get_name_by_tag(tag)
|
10
|
+
constants.find do |name|
|
11
|
+
const_get(name) == tag
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_tag?(tag)
|
16
|
+
not get_name_by_tag(tag).nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
def name_by_value(value)
|
20
|
+
constants.find {|c| const_get(c) == value}
|
21
|
+
end
|
22
|
+
|
23
|
+
def descriptor
|
24
|
+
@descriptor ||= Protobuf::Descriptor::EnumDescriptor.new(self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|