krpc 0.4.0.beta2 → 0.4.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ require 'krpc/types'
4
4
  module KRPC
5
5
  module Encoder
6
6
  class << self
7
-
7
+
8
8
  # Given a type object, and ruby object, encode the ruby object
9
9
  def encode(obj, type)
10
10
  if type.is_a?(Types::MessageType) then type.ruby_type.encode(obj)
@@ -38,12 +38,12 @@ module KRPC
38
38
  else raise(RuntimeError, "Cannot encode object #{obj} of type #{type}")
39
39
  end
40
40
  end
41
-
41
+
42
42
  def encode_value(value, type)
43
43
  type_string = type.is_a?(String) ? type : type.protobuf_type.code.to_s.downcase
44
44
  ProtobufUtils::Encoder.encode(value, type_string)
45
45
  end
46
-
46
+
47
47
  def encode_message_with_size(msg)
48
48
  data = msg.class.encode(msg)
49
49
  length = ProtobufUtils::Encoder.encode_nonnegative_varint(data.length)
@@ -2,14 +2,9 @@
2
2
  module KRPC
3
3
 
4
4
  class Error < Exception; end
5
- class UTF8MessageError < Error
6
- def initialize(msg = nil)
7
- super(msg.nil? ? msg : msg.encode(Encoding::UTF_8, invalid: :replace, undef: :replace))
8
- end
9
- end
10
5
 
11
- class ConnectionError < UTF8MessageError; end
12
- class RPCError < UTF8MessageError; end
6
+ class ConnectionError < Error; end
7
+ class RPCError < Error; end
13
8
  class ValueError < Error; end
14
9
  class ProcedureNameParserError < Error; end
15
10
 
@@ -40,7 +35,7 @@ module KRPC
40
35
  def with_arguments_count_incremented_by(args_count_increment)
41
36
  self.class.new(args_count + args_count_increment, (valid_params_count_range.min + args_count_increment)..(valid_params_count_range.max + args_count_increment), signature)
42
37
  end
43
-
38
+
44
39
  def with_signature(sig)
45
40
  self.class.new(args_count, valid_params_count_range, sig)
46
41
  end
@@ -6,10 +6,10 @@ require 'colorize'
6
6
  module KRPC
7
7
  module Gen
8
8
  class << self
9
- def service_gen_module(service_name)
9
+ def service_gen_module(service_name)
10
10
  const_get_or_create(service_name, Module.new)
11
11
  end
12
-
12
+
13
13
  def generate_class(service_name, class_name)
14
14
  mod = service_gen_module(service_name)
15
15
  mod.const_get_or_create(class_name) do
@@ -19,7 +19,7 @@ module KRPC
19
19
  end
20
20
  end
21
21
  end
22
-
22
+
23
23
  def generate_enum(service_name, enum_name, values)
24
24
  mod = service_gen_module(service_name)
25
25
  mod.const_get_or_create(enum_name) do
@@ -54,9 +54,9 @@ module KRPC
54
54
  raise err.with_signature(Doc.docstring_for_method(method_owner, method_name, false))
55
55
  end
56
56
  end
57
-
57
+
58
58
  private #----------------------------------
59
-
59
+
60
60
  def define_static_rpc_method(cls, method_name, param_default, param_names, param_types, prepend_self_to_args, proc, return_type, service_name)
61
61
  cls.instance_eval do
62
62
  define_singleton_method method_name do |*args|
@@ -92,7 +92,7 @@ module KRPC
92
92
  end
93
93
  end
94
94
  end
95
-
95
+
96
96
  def parse_procedure(proc)
97
97
  param_names = proc.parameters.map{|p| p.name.underscore }
98
98
  param_types = proc.parameters.map{|p| TypeStore[p.type] }
@@ -107,29 +107,29 @@ module KRPC
107
107
  [param_names, param_types, param_default, return_type]
108
108
  end
109
109
  end
110
-
110
+
111
111
  module RPCMethodGenerator
112
112
  def include_rpc_method(service_name, procedure_name, params: [], return_type: nil, xmldoc: "", **options)
113
113
  Gen.add_rpc_method(self.class, service_name, PB::Procedure.new(name: procedure_name, parameters: params, return_type: return_type, documentation: xmldoc), **options)
114
114
  end
115
115
  end
116
-
116
+
117
117
  ##
118
118
  # Base class for service-defined class types.
119
119
  class ClassBase
120
120
  include Doc::SuffixMethods
121
121
  include Streaming::StreamConstructors
122
-
122
+
123
123
  attr_reader :client, :remote_oid
124
-
124
+
125
125
  def self.krpc_name
126
126
  name[11..-1]
127
127
  end
128
-
128
+
129
129
  def initialize(client, remote_oid)
130
130
  @client, @remote_oid = client, remote_oid
131
131
  end
132
-
132
+
133
133
  alias_method :eql?, :==
134
134
  def ==(other)
135
135
  other.class == self.class and other.remote_oid == remote_oid
@@ -137,15 +137,15 @@ module KRPC
137
137
  def hash
138
138
  remote_oid.hash
139
139
  end
140
-
140
+
141
141
  def to_s
142
142
  "#<#{self.class} @remote_oid=#{remote_oid}>"
143
143
  end
144
-
144
+
145
145
  def inspect
146
146
  "#<#{self.class} ".green + "@remote_oid" + "=".green + remote_oid.to_s.bold.blue + ">".green
147
147
  end
148
148
  end
149
-
150
- end
149
+
150
+ end
151
151
  end
@@ -37,13 +37,19 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
37
37
  optional :value, :bytes, 2
38
38
  end
39
39
  add_message "krpc.schema.Response" do
40
- optional :error, :string, 1
40
+ optional :error, :message, 1, "krpc.schema.Error"
41
41
  repeated :results, :message, 2, "krpc.schema.ProcedureResult"
42
42
  end
43
43
  add_message "krpc.schema.ProcedureResult" do
44
- optional :error, :string, 1
44
+ optional :error, :message, 1, "krpc.schema.Error"
45
45
  optional :value, :bytes, 2
46
46
  end
47
+ add_message "krpc.schema.Error" do
48
+ optional :service, :string, 1
49
+ optional :name, :string, 2
50
+ optional :description, :string, 3
51
+ optional :stack_trace, :string, 4
52
+ end
47
53
  add_message "krpc.schema.StreamUpdate" do
48
54
  repeated :results, :message, 1, "krpc.schema.StreamResult"
49
55
  end
@@ -59,13 +65,15 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
59
65
  repeated :procedures, :message, 2, "krpc.schema.Procedure"
60
66
  repeated :classes, :message, 3, "krpc.schema.Class"
61
67
  repeated :enumerations, :message, 4, "krpc.schema.Enumeration"
62
- optional :documentation, :string, 5
68
+ repeated :exceptions, :message, 5, "krpc.schema.Exception"
69
+ optional :documentation, :string, 6
63
70
  end
64
71
  add_message "krpc.schema.Procedure" do
65
72
  optional :name, :string, 1
66
73
  repeated :parameters, :message, 2, "krpc.schema.Parameter"
67
74
  optional :return_type, :message, 3, "krpc.schema.Type"
68
- optional :documentation, :string, 4
75
+ optional :return_is_nullable, :bool, 4
76
+ optional :documentation, :string, 5
69
77
  end
70
78
  add_message "krpc.schema.Parameter" do
71
79
  optional :name, :string, 1
@@ -86,6 +94,10 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
86
94
  optional :value, :int32, 2
87
95
  optional :documentation, :string, 3
88
96
  end
97
+ add_message "krpc.schema.Exception" do
98
+ optional :name, :string, 1
99
+ optional :documentation, :string, 2
100
+ end
89
101
  add_message "krpc.schema.Type" do
90
102
  optional :code, :enum, 1, "krpc.schema.Type.TypeCode"
91
103
  optional :service, :string, 2
@@ -167,6 +179,7 @@ module KRPC
167
179
  Argument = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Argument").msgclass
168
180
  Response = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Response").msgclass
169
181
  ProcedureResult = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.ProcedureResult").msgclass
182
+ Error = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Error").msgclass
170
183
  StreamUpdate = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.StreamUpdate").msgclass
171
184
  StreamResult = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.StreamResult").msgclass
172
185
  Services = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Services").msgclass
@@ -176,6 +189,7 @@ module KRPC
176
189
  Class = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Class").msgclass
177
190
  Enumeration = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Enumeration").msgclass
178
191
  EnumerationValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.EnumerationValue").msgclass
192
+ Exception = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Exception").msgclass
179
193
  Type = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Type").msgclass
180
194
  Type::TypeCode = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Type.TypeCode").enummodule
181
195
  Tuple = Google::Protobuf::DescriptorPool.generated_pool.lookup("krpc.schema.Tuple").msgclass
@@ -4,14 +4,14 @@ module KRPC
4
4
  module ProtobufUtils
5
5
  module Decoder
6
6
  class << self
7
-
7
+
8
8
  def decode(bytes, type)
9
9
  meth_name = "decode_" + type
10
10
  raise RuntimeError.new("Unsupported type #{type}") unless respond_to?(meth_name)
11
11
  send(meth_name, bytes)
12
12
  end
13
13
 
14
- # based on: https://developers.google.com/protocol-buffers/docs/encoding#varints & http://www.rubydoc.info/gems/ruby-protocol-buffers/1.0.1/ProtocolBuffers/Varint#decode-class_method & https://github.com/google/protobuf/blob/master/python/google/protobuf/internal/decoder.py#L136
14
+ # based on: https://developers.google.com/protocol-buffers/docs/encoding#varints & http://www.rubydoc.info/gems/ruby-protocol-buffers/1.0.1/ProtocolBuffers/Varint#decode-class_method & https://github.com/google/protobuf/blob/master/python/google/protobuf/internal/decoder.py#L136
15
15
  def decode_varint(bytes)
16
16
  decode_varint_pos(bytes)[0]
17
17
  end
@@ -33,12 +33,12 @@ module KRPC
33
33
  zigzaged = decode_varint(bytes)
34
34
  (zigzaged >> 1) ^ -(zigzaged & 1)
35
35
  end
36
-
36
+
37
37
  alias_method :decode_sint32, :decode_zigzaged_varint
38
38
  alias_method :decode_sint64, :decode_zigzaged_varint
39
39
  alias_method :decode_uint32, :decode_varint
40
40
  alias_method :decode_uint64, :decode_varint
41
-
41
+
42
42
  # based on: https://github.com/ruby-protobuf/protobuf/search?q=pack
43
43
  def decode_float(bytes)
44
44
  bytes.unpack('e').first
@@ -57,19 +57,19 @@ module KRPC
57
57
  size, pos = decode_varint_pos(bytes)
58
58
  bytes[pos..(pos+size)].bytes
59
59
  end
60
-
60
+
61
61
  end
62
62
  end
63
-
63
+
64
64
  module Encoder
65
65
  class << self
66
-
66
+
67
67
  def encode(value, type)
68
68
  meth_name = "encode_" + type
69
69
  raise(RuntimeError, "Unsupported type #{type}") unless respond_to?(meth_name)
70
70
  send(meth_name, value)
71
71
  end
72
-
72
+
73
73
  # based on: http://www.rubydoc.info/gems/ruby-protocol-buffers/1.0.1/ProtocolBuffers/Varint#decode-class_method & https://github.com/google/protobuf/blob/master/python/google/protobuf/internal/encoder.py#L390
74
74
  def encode_varint(value)
75
75
  return [value].pack('C') if value < 0b1000_0000
@@ -96,12 +96,12 @@ module KRPC
96
96
  zigzaged = (value << 1) ^ (value >> 63)
97
97
  encode_varint(zigzaged)
98
98
  end
99
-
99
+
100
100
  alias_method :encode_sint32, :encode_zigzaged_varint_32
101
101
  alias_method :encode_sint64, :encode_zigzaged_varint_64
102
102
  alias_method :encode_uint32, :encode_nonnegative_varint
103
103
  alias_method :encode_uint64, :encode_nonnegative_varint
104
-
104
+
105
105
  def encode_float(value)
106
106
  [value].pack('e')
107
107
  end
@@ -112,16 +112,17 @@ module KRPC
112
112
  encode_varint(value ? 1 : 0)
113
113
  end
114
114
  def encode_string(value)
115
- size = encode_varint(value.bytesize)
116
- size + value.bytes.map(&:chr).join.b
115
+ data = value.encode(Encoding::UTF_8).b
116
+ size = encode_varint(data.bytesize)
117
+ size + data
117
118
  end
118
119
  def encode_bytes(value)
119
120
  size = encode_varint(value.size)
120
121
  size + value.map(&:chr).join.b
121
122
  end
122
-
123
+
123
124
  end
124
125
  end
125
-
126
+
126
127
  end
127
128
  end
@@ -5,27 +5,27 @@ require 'krpc/streaming'
5
5
  module KRPC
6
6
  module Services
7
7
  class << self
8
-
8
+
9
9
  # Generate classes and methods for the service - see documentation for Client#generate_services_api!
10
10
  def create_service(service_msg)
11
11
  service_name = service_msg.name
12
-
12
+
13
13
  # Create service class
14
14
  service_class = Class.new(ServiceBase)
15
15
  const_set(service_name, service_class)
16
-
16
+
17
17
  # Create service' classes
18
18
  class_types_by_name = Hash.new do |h,k|
19
19
  TypeStore[PB::Type.new(code: :CLASS, service: service_name, name: k)]
20
20
  end
21
21
  service_msg.classes.map(&:name).each {|cn| class_types_by_name[cn] }
22
-
22
+
23
23
  # Create service' enums
24
24
  service_msg.enumerations.each do |enum|
25
25
  enum_type = TypeStore[PB::Type.new(code: :ENUMERATION, service: service_name, name: enum.name)]
26
26
  enum_type.set_values(enum.values)
27
27
  end
28
-
28
+
29
29
  # Create service' procedures
30
30
  service_msg.procedures.each do |proc|
31
31
  cls = if proc.class_member?
@@ -35,26 +35,26 @@ module KRPC
35
35
  end
36
36
  Gen.add_rpc_method(cls, service_name, proc)
37
37
  end
38
-
38
+
39
39
  # Return service class
40
40
  service_class
41
41
  end
42
-
42
+
43
43
  end
44
-
44
+
45
45
  ##
46
46
  # Base class for service objects, created at runtime using information received from the server.
47
47
  class ServiceBase
48
48
  include Doc::SuffixMethods
49
49
  include Streaming::StreamConstructors
50
-
50
+
51
51
  attr_reader :client
52
-
52
+
53
53
  def initialize(client)
54
54
  @client = client
55
55
  end
56
56
  end
57
-
57
+
58
58
  ##
59
59
  # Hardcoded version of `krpc` service - The core kRPC service, e.g. for querying for the available services.
60
60
  class Core < ServiceBase
@@ -98,6 +98,14 @@ module KRPC
98
98
  return_type: PB::Type.new(code: :ENUMERATION, service: 'Core', name: 'GameScene'),
99
99
  xmldoc: "<doc><summary>Get the current game scene.</summary></doc>",
100
100
  **opts
101
+ include_rpc_method 'KRPC', 'GetClientID',
102
+ return_type: PB::Type.new(code: :BYTES),
103
+ xmldoc: "<doc>\n<summary>\nReturns the identifier for the current client.\n</summary>\n</doc>",
104
+ **opts
105
+ include_rpc_method 'KRPC', 'GetClientName',
106
+ return_type: PB::Type.new(code: :STRING),
107
+ xmldoc: "<doc>\n<summary>\nReturns the name of the current client.\nThis is an empty string if the client has no name.\n</summary>\n</doc>",
108
+ **opts
101
109
  end
102
110
  end
103
111
  end
@@ -6,14 +6,14 @@ module KRPC
6
6
 
7
7
  class StreamsManager
8
8
  attr_reader :client
9
-
9
+
10
10
  def initialize(client)
11
11
  @client = client
12
12
  @streams = {}
13
13
  @streams_mutex = Mutex.new
14
14
  @streaming_thread = Thread.new {}
15
15
  end
16
-
16
+
17
17
  # Send the streaming request, create related Stream object and return it. If identical Stream
18
18
  # already exists, doesn't create new Stream and return the existing one.
19
19
  def create_stream(call, return_type, method, *args, **kwargs)
@@ -29,7 +29,7 @@ module KRPC
29
29
  end
30
30
  end
31
31
  end
32
-
32
+
33
33
  # Remove the streaming request and deactivate the Stream object. Returns `true` if the
34
34
  # streaming request has been removed or `false` if passed Stream object is already inactive.
35
35
  def remove_stream(stream)
@@ -48,7 +48,7 @@ module KRPC
48
48
  def remove_all_streams
49
49
  @streams.each {|_,stream| remove_stream(stream)}
50
50
  end
51
-
51
+
52
52
  # Start streaming thread. It receives stream data, and updates Stream object's `value` attribute.
53
53
  def start_streaming_thread
54
54
  stop_streaming_thread
@@ -65,24 +65,24 @@ module KRPC
65
65
  if result.result.field_empty? :error
66
66
  stream.value = Decoder.decode(result.result.value, stream.return_type, client)
67
67
  else
68
- stream.value = RPCError.new(result.result.error)
68
+ stream.value = client.build_exception(result.result.error)
69
69
  end
70
70
  end
71
71
  end
72
72
  end
73
73
  end
74
74
  end
75
-
75
+
76
76
  # Stop streaming thread.
77
77
  def stop_streaming_thread
78
78
  @streaming_thread.terminate
79
79
  end
80
80
  end
81
-
81
+
82
82
  class Stream
83
83
  attr_reader :id, :method, :args, :kwargs, :return_type, :manager
84
84
  attr_writer :value
85
-
85
+
86
86
  def initialize(manager, id, return_type, value, method, *args, **kwargs)
87
87
  @manager = manager
88
88
  @id = id
@@ -90,7 +90,7 @@ module KRPC
90
90
  @method, @args, @kwargs = method, args, kwargs
91
91
  @active = true
92
92
  end
93
-
93
+
94
94
  # Get the current stream value. Has alias method `value`.
95
95
  def get
96
96
  raise @value if @value.is_a?(Exception)
@@ -103,18 +103,18 @@ module KRPC
103
103
  manager.remove_stream self
104
104
  end
105
105
  alias_method :close, :remove
106
-
106
+
107
107
  # Check if stream is active (i.e. not removed).
108
108
  def active?; @active end
109
109
 
110
110
  # Mark stream as inactive.
111
111
  # WARNING: This method does not remove the stream. To remove the stream call Stream#remove instead.
112
112
  def mark_as_inactive; @active = false end
113
-
113
+
114
114
  def to_s
115
115
  inspect.gsub(/\n|\t/," ").squeeze(" ").uncolorize
116
116
  end
117
-
117
+
118
118
  def inspect
119
119
  def coderay(x)
120
120
  require 'coderay'
@@ -134,11 +134,11 @@ module KRPC
134
134
  ">".green
135
135
  end
136
136
  end
137
-
137
+
138
138
  module StreamConstructors
139
139
  STREAM_METHOD_SUFFIX = "_stream"
140
140
  STREAM_METHOD_REGEX = /^(.+)(?:#{STREAM_METHOD_SUFFIX})$/
141
-
141
+
142
142
  module ClassMethods
143
143
  def stream_constructors
144
144
  @stream_constructors ||= {}
@@ -149,7 +149,7 @@ module KRPC
149
149
  base.extend ClassMethods
150
150
  base.extend self
151
151
  end
152
-
152
+
153
153
  def method_missing(method, *args, **kwargs, &block)
154
154
  if STREAM_METHOD_REGEX =~ method.to_s
155
155
  if respond_to? $1.to_sym
@@ -159,7 +159,7 @@ module KRPC
159
159
  end
160
160
  super
161
161
  end
162
-
162
+
163
163
  def respond_to_missing?(method, *)
164
164
  if STREAM_METHOD_REGEX =~ method.to_s
165
165
  if respond_to? $1.to_sym
@@ -169,8 +169,8 @@ module KRPC
169
169
  end
170
170
  super
171
171
  end
172
-
172
+
173
173
  end
174
-
174
+
175
175
  end
176
176
  end