interop 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6369ad96be9d4e4a7946a23c56d4a06b96dc23553b2bb602e6708e34154561c7
4
- data.tar.gz: fdf11d65dec06324fc6207c18318b17130a51ddaf580b5069f48710ee12605ed
3
+ metadata.gz: '084751018d90a52509edf5a1c67f864ee9990b95970ef3a5018617c21406fe8f'
4
+ data.tar.gz: 31de67481b086a640eb322088cd06d908813ba1e495de10fbbf122e8596ee59a
5
5
  SHA512:
6
- metadata.gz: 06c118089ef25d6c1f122bacdefd11e7ecdd923fb82ccc3ad853e9782d768e374c43b6a55cd96f4bb9d11f582262facc50f9f2e4c0edf0f601e403b68e278369
7
- data.tar.gz: 70b6a14d430ffb08785a731aec8a0cea4a782faae584b9b9758af5306ba5d4483fee103d3e5ed5c371501dbed5fc0eecfadec8541deef222248f3af7dd22a2f9
6
+ metadata.gz: ae2e8597f69cc61b6a341f95ddcff5547fd99055070ed8ae991975a71f8ebdc555e37a7f4f6503572dfd8840fdad101d44f3739da57ed5c288e7d272b576862e
7
+ data.tar.gz: fbb8c6666a20fed2de479ed56b7db5885a526117c6ba2801c3cdff2d89e30c861ae735d6f0bed0b5c8285bbeedec26fe321388305ee7a6f646c8e2404a956450
data/lib/interop/error.rb CHANGED
@@ -7,6 +7,9 @@ module Hx
7
7
  class InvalidHeader < Fatal
8
8
  end
9
9
 
10
+ class Unexpected < Fatal
11
+ end
12
+
10
13
  class NotDecodable < self
11
14
  end
12
15
  end
@@ -10,6 +10,7 @@ module Hx
10
10
  def initialize(reader, writer = reader)
11
11
  @connection = Connection.build(reader, writer)
12
12
  @dispatcher = Dispatcher.new
13
+ yield self if block_given?
13
14
  @io_thread = Thread.new do
14
15
  run
15
16
  rescue StandardError => e
@@ -15,7 +15,7 @@ module Hx
15
15
  end
16
16
 
17
17
  klass = self
18
- lambda do |message|
18
+ lambda do |message, _message_class|
19
19
  controller = klass.new(message)
20
20
  controller.__send__ action
21
21
  controller.response
@@ -6,8 +6,8 @@ module Hx
6
6
  # Message dispatcher used by Client and Server.
7
7
  class Dispatcher
8
8
  Route = Struct.new :matcher, :handler do
9
- def call(message)
10
- handler[message]
9
+ def call(*args)
10
+ handler.call(*args)
11
11
  end
12
12
 
13
13
  def match?(message)
@@ -43,7 +43,9 @@ module Hx
43
43
 
44
44
  def make_matcher(criteria)
45
45
  case criteria
46
- when Proc
46
+ when Array, Set
47
+ make_array_matcher criteria
48
+ when Proc, Method
47
49
  criteria
48
50
  when String, Regexp
49
51
  -> message { criteria === message.headers[Headers::CLASS] }
@@ -54,6 +56,22 @@ module Hx
54
56
  end
55
57
  end
56
58
 
59
+ def make_array_matcher(array)
60
+ if array.all? { |item| item.is_a?(String) || item.is_a?(Symbol) }
61
+ make_any_class_matcher Set.new(array.map(&:to_s)).freeze
62
+ else
63
+ make_any_matcher array.map(&method(:make_matcher))
64
+ end
65
+ end
66
+
67
+ def make_any_class_matcher(classes)
68
+ -> message { classes.include? message.headers[Headers::CLASS] }
69
+ end
70
+
71
+ def make_any_matcher(matchers)
72
+ -> message { matchers.any? { |c| c.match? message } }
73
+ end
74
+
57
75
  def make_handler(*args, &block)
58
76
  return block if block && args.empty?
59
77
 
@@ -21,7 +21,7 @@ module Hx
21
21
 
22
22
  def run
23
23
  super do |request|
24
- response = make_response(dispatcher.match(request)&.call request)
24
+ response = make_response(dispatcher.match(request)&.call request, request[Headers::CLASS])
25
25
  response[Headers::ID] = request[Headers::ID]
26
26
  write response
27
27
  rescue StandardError => e
@@ -1,3 +1,5 @@
1
+ require 'set'
2
+
1
3
  require 'interop/message'
2
4
  require 'interop/reader'
3
5
 
@@ -21,15 +23,8 @@ module Hx
21
23
  def _read
22
24
  @mutex.synchronize do
23
25
  message = Message.new(read_headers)
24
- length = message.headers[Headers::CONTENT_LENGTH]&.to_i
25
- message.body =
26
- if length&.positive?
27
- @stream.read length
28
- elsif length.nil?
29
- read_paragraph.join
30
- else
31
- ''
32
- end
26
+ length = message.headers[Headers::CONTENT_LENGTH]
27
+ message.body = length.nil? || length.empty? ? read_paragraph.join : read_length(length.to_i)
33
28
  message
34
29
  end
35
30
  end
@@ -39,7 +34,7 @@ module Hx
39
34
  # @return [Hash]
40
35
  def read_headers
41
36
  read_paragraph.to_h do |line|
42
- line.strip.split(/:\s*/).tap do |pair|
37
+ line.strip.split(/:\s*/, 2).tap do |pair|
43
38
  raise Error::InvalidHeader unless pair.length == 2
44
39
  end
45
40
  end
@@ -53,6 +48,15 @@ module Hx
53
48
  lines << line
54
49
  end
55
50
  end
51
+
52
+ def read_length(length)
53
+ result = length.positive? ? @stream.read(length) : ''
54
+ sep = @stream.read(1)
55
+ sep = @stream.read(1) if sep == "\r"
56
+ raise Error::Unexpected, "Expected a newline after #{length} bytes" unless sep == "\n"
57
+
58
+ result
59
+ end
56
60
  end
57
61
  end
58
62
  end
@@ -1,5 +1,5 @@
1
1
  module Hx
2
2
  module Interop
3
- VERSION = '0.1.0'.freeze
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil E. Pearson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-03 00:00:00.000000000 Z
11
+ date: 2021-08-10 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby implementation of hx/interop cross-language interop abstraction
14
14
  email: