krpc 0.4.0.beta2 → 0.4.0.beta3

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.
@@ -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