asterism-zenoh 0.2.0 → 0.4.0

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.
@@ -0,0 +1,221 @@
1
+ # The part of Asterism::Zenoh written in Ruby that is the same on every
2
+ # backend: this file is byte for byte the same as mrblib/common.rb of the
3
+ # mruby / PicoRuby binding (picoruby-asterism-zenoh). It runs on CRuby,
4
+ # mruby and PicoRuby, so it keeps to what all three have (no Regexp, no
5
+ # Data, while loops where a block would be called from C).
6
+ #
7
+ # What it adds on top of the C binding:
8
+ # - the deprecation helper (Asterism.deprecated, Asterism.deprecations=),
9
+ # shared by every Asterism gem, and Asterism.warn_once (lost replies);
10
+ # - the time limit in seconds (timeout:) next to milliseconds (timeout_ms:)
11
+ # on get and liveliness_get, and keywords for the positional optionals;
12
+ # - connection_count's old name peers, and the one-argument Query#reply
13
+ # that will change in 1.0, both with a deprecation warning;
14
+ # - Error#code and the readable constant names.
15
+ module Asterism
16
+ # The root of every Asterism error (the binding's C code defines it first).
17
+ class Error < StandardError; end
18
+
19
+ # Raised instead of a warning when Asterism.deprecations is :raise.
20
+ class DeprecationError < Error; end
21
+
22
+ # How a deprecated call is reported: :warn (once per name, the default),
23
+ # :raise (DeprecationError; for CI) or :silent. The environment variable
24
+ # ASTERISM_DEPRECATIONS (warn / raise / silent) sets the default.
25
+ def self.deprecations
26
+ if @deprecations.nil?
27
+ mode = nil
28
+ begin
29
+ mode = ENV["ASTERISM_DEPRECATIONS"] if Object.const_defined?(:ENV)
30
+ rescue StandardError
31
+ mode = nil
32
+ end
33
+ @deprecations = (mode == "raise" || mode == "silent") ? mode.to_sym : :warn
34
+ end
35
+ @deprecations
36
+ end
37
+
38
+ def self.deprecations=(mode)
39
+ m = mode.to_s.to_sym
40
+ raise ArgumentError, "deprecations must be :warn, :raise or :silent" unless m == :warn || m == :raise || m == :silent
41
+ @deprecations = m
42
+ end
43
+
44
+ # Reports that `old` is deprecated in favour of `instead`: warns once per
45
+ # `old` per process (per VM on the boards), raises DeprecationError, or
46
+ # stays silent (Asterism.deprecations). `why` is an optional sentence.
47
+ def self.deprecated(old, instead, why = nil)
48
+ mode = deprecations
49
+ return nil if mode == :silent
50
+ msg = "asterism: #{old} is deprecated and goes away in 1.0; use #{instead}"
51
+ msg = "#{msg} (#{why})" if why
52
+ raise DeprecationError, msg if mode == :raise
53
+ @deprecated_seen ||= {}
54
+ return nil if @deprecated_seen[old]
55
+ @deprecated_seen[old] = true
56
+ if respond_to?(:warn, true)
57
+ warn(msg)
58
+ else
59
+ puts(msg)
60
+ end
61
+ nil
62
+ end
63
+
64
+ # Warns msg once for obj (a Get, a watch, a wrapper): later calls for
65
+ # the same object say nothing. For losses the application did not ask
66
+ # for, such as replies dropped from a full queue. Returns true when it
67
+ # warned. Ruby's warn stays silent with $VERBOSE = nil.
68
+ def self.warn_once(obj, msg)
69
+ # By object_id: not every mruby build has instance_variable_get. The
70
+ # objects warned about are few; the table is emptied past 256.
71
+ @warned_once ||= {}
72
+ id = obj.object_id
73
+ return false if @warned_once[id]
74
+ @warned_once = {} if @warned_once.size >= 256
75
+ @warned_once[id] = true
76
+ if respond_to?(:warn, true)
77
+ warn(msg)
78
+ else
79
+ puts(msg)
80
+ end
81
+ true
82
+ end
83
+
84
+ # The names warned about so far (for tests). @api private
85
+ def self.deprecated_names
86
+ (@deprecated_seen || {}).keys
87
+ end
88
+
89
+ # Forget the names warned about (for tests). @api private
90
+ def self.reset_deprecations
91
+ @deprecated_seen = {}
92
+ nil
93
+ end
94
+
95
+ # A time limit in milliseconds from the ways a call may take it: timeout:
96
+ # (seconds), timeout_ms: or the old positional milliseconds (deprecated).
97
+ # Giving more than one raises ArgumentError. @api private
98
+ def self.time_ms(where, timeout, timeout_ms, positional, default_ms)
99
+ given = 0
100
+ given += 1 unless timeout.nil?
101
+ given += 1 unless timeout_ms.nil?
102
+ given += 1 unless positional.nil?
103
+ raise ArgumentError, "#{where}: give the time limit once (timeout: in seconds, or timeout_ms:)" if given > 1
104
+ unless positional.nil?
105
+ if positional.is_a?(Float)
106
+ deprecated("#{where} with a Float as the positional time limit", "timeout: (seconds)",
107
+ "the positional time limit is milliseconds, so #{positional} waits #{positional.to_i} ms; " \
108
+ "a Float there is usually meant as seconds")
109
+ else
110
+ deprecated("#{where} with the time limit as a positional argument", "timeout: (seconds) or timeout_ms:")
111
+ end
112
+ return positional.to_i
113
+ end
114
+ unless timeout_ms.nil?
115
+ raise TypeError, "#{where}: timeout_ms: must be a number" unless timeout_ms.is_a?(Numeric)
116
+ return timeout_ms.round
117
+ end
118
+ return default_ms if timeout.nil?
119
+ raise TypeError, "#{where}: timeout: must be a number of seconds" unless timeout.is_a?(Numeric)
120
+ ms = (timeout * 1000).round
121
+ raise ArgumentError, "#{where}: timeout: #{timeout} s is less than 1 ms" if ms < 1
122
+ ms
123
+ end
124
+
125
+ # A queue depth given positionally (kept) or as depth: (not both).
126
+ # @api private
127
+ def self.depth_of(where, args, depth, default)
128
+ raise ArgumentError, "#{where}: too many arguments" if args.size > 1
129
+ raise ArgumentError, "#{where}: give the depth once (positional or depth:)" if args.size == 1 && !depth.nil?
130
+ return args[0] if args.size == 1
131
+ depth.nil? ? default : depth
132
+ end
133
+
134
+ module Zenoh
135
+ # The readable name of PEER: whether this build has peer mode.
136
+ PEER_SUPPORTED = PEER
137
+ # The default time limit of get and liveliness_get, in seconds.
138
+ DEFAULT_TIMEOUT = 2.0
139
+
140
+ class Error
141
+ # The result code of zenoh-c / zenoh-pico (a negative Integer) when the
142
+ # failure came with one, else nil.
143
+ attr_reader :code
144
+ end
145
+
146
+ class Session
147
+ alias_method :__asterism_get, :get
148
+ alias_method :__asterism_liveliness_get, :liveliness_get
149
+ alias_method :__asterism_subscribe, :subscribe
150
+ alias_method :__asterism_queryable, :queryable
151
+ alias_method :__asterism_liveliness_watch, :liveliness_watch
152
+
153
+ # get(key, timeout: 2.0, params: nil, payload: nil, attachment: nil,
154
+ # target: :all, consolidation: :none, depth: DEFAULT_GET_DEPTH,
155
+ # ...) -> Get.
156
+ # timeout: seconds; or timeout_ms:. depth: the replies kept until
157
+ # taken (past it the oldest go; Get#dropped counts them). The old
158
+ # positional form get(key, timeout_ms, params, payload) still works
159
+ # (deprecated).
160
+ def get(key, *args, timeout: nil, timeout_ms: nil, params: nil, payload: nil, **opts)
161
+ raise ArgumentError, "get: wrong number of arguments (given #{args.size + 1}, expected 1..4)" if args.size > 3
162
+ raise ArgumentError, "get: params given twice" if args.size > 1 && !params.nil?
163
+ raise ArgumentError, "get: payload given twice" if args.size > 2 && !payload.nil?
164
+ ms = ::Asterism.time_ms("Session#get", timeout, timeout_ms, args[0], 2000)
165
+ params = args[1] if args.size > 1
166
+ payload = args[2] if args.size > 2
167
+ __asterism_get(key, ms, params, payload, **opts)
168
+ end
169
+
170
+ # liveliness_get(key, timeout: 2.0, depth: DEFAULT_GET_DEPTH) -> Get
171
+ # (or timeout_ms:).
172
+ def liveliness_get(key, *args, timeout: nil, timeout_ms: nil, depth: nil)
173
+ raise ArgumentError, "liveliness_get: wrong number of arguments (given #{args.size + 1}, expected 1..2)" if args.size > 1
174
+ ms = ::Asterism.time_ms("Session#liveliness_get", timeout, timeout_ms, args[0], 2000)
175
+ __asterism_liveliness_get(key, ms, depth: depth.nil? ? DEFAULT_GET_DEPTH : depth)
176
+ end
177
+
178
+ # subscribe(key, depth = 16) or subscribe(key, depth: 16).
179
+ def subscribe(key, *args, depth: nil)
180
+ __asterism_subscribe(key, ::Asterism.depth_of("subscribe", args, depth, DEFAULT_DEPTH))
181
+ end
182
+
183
+ # queryable(key, depth = 16, complete: false) or with depth:.
184
+ def queryable(key, *args, depth: nil, **opts)
185
+ __asterism_queryable(key, ::Asterism.depth_of("queryable", args, depth, DEFAULT_DEPTH), **opts)
186
+ end
187
+
188
+ # liveliness_watch(key, depth = DEFAULT_WATCH_DEPTH) or with depth:.
189
+ # The tokens alive when it is declared come in one burst.
190
+ def liveliness_watch(key, *args, depth: nil)
191
+ __asterism_liveliness_watch(key, ::Asterism.depth_of("liveliness_watch", args, depth, DEFAULT_WATCH_DEPTH))
192
+ end
193
+
194
+ # Deprecated: the number of connections is connection_count.
195
+ def peers
196
+ ::Asterism.deprecated("Session#peers", "Session#connection_count",
197
+ "for a client session it counts routers, not peers")
198
+ connection_count
199
+ end
200
+ end
201
+
202
+ class Query
203
+ alias_method :__asterism_reply, :reply
204
+
205
+ # reply(payload) answers on the query's key today. From 1.0 it answers
206
+ # on the queryable's own key when that key has no wildcard (as the
207
+ # CRuby block API does); a reply that would change warns now.
208
+ def reply(*args, **kw)
209
+ if args.size == 1
210
+ own = @asterism_queryable_key
211
+ if own && !own.include?("*") && !own.include?("$") && own != key
212
+ ::Asterism.deprecated("Query#reply(payload) for a query whose key differs from the queryable's",
213
+ "q.reply(key, payload)",
214
+ "from 1.0 a reply with only a payload answers on the queryable's own key")
215
+ end
216
+ end
217
+ __asterism_reply(*args, **kw)
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,128 @@
1
+ # What only the CRuby binding (zenoh-c) adds in Ruby: the backend
2
+ # constants, Session.open with a block and connect_timeout:, seconds and
3
+ # keywords on the CRuby-only calls (querier, advanced subscriber,
4
+ # listeners), the long reply names, and scout's argument check.
5
+ module Asterism
6
+ module Zenoh
7
+ # Which Zenoh implementation is underneath (:zenoh_pico on the boards).
8
+ BACKEND = :zenoh_c
9
+ # Its version (C_VERSION here, PICO_VERSION on the boards).
10
+ BACKEND_VERSION = C_VERSION
11
+
12
+ class Session
13
+ class << self
14
+ alias_method :__asterism_open, :open
15
+
16
+ # Session.open(locator = nil, mode:, listen:, scouting:,
17
+ # timestamping:, config:, config_file:, connect_timeout:) -> Session.
18
+ # connect_timeout: seconds to wait for a router or peer
19
+ # (CONNECT_TIMEOUT_MS by default; zenoh's connect/timeout_ms). With a
20
+ # block: yields the session, closes it when the block ends (also on
21
+ # an exception) and returns the block's value.
22
+ def open(locator = nil, connect_timeout: nil, **opts)
23
+ unless connect_timeout.nil?
24
+ ms = ::Asterism.time_ms("Session.open connect_timeout:", connect_timeout, nil, nil, CONNECT_TIMEOUT_MS)
25
+ cfg = opts[:config]
26
+ if cfg.nil?
27
+ opts[:config] = { "connect/timeout_ms" => ms }
28
+ elsif cfg.is_a?(Hash)
29
+ if cfg.key?("connect/timeout_ms") || cfg.key?(:"connect/timeout_ms")
30
+ raise ArgumentError, "connect_timeout: and config: {\"connect/timeout_ms\" => ...} given together"
31
+ end
32
+ opts[:config] = cfg.merge("connect/timeout_ms" => ms)
33
+ else
34
+ raise ArgumentError, "connect_timeout: cannot be added to a config String; set connect/timeout_ms in it"
35
+ end
36
+ end
37
+ s = __asterism_open(locator, **opts)
38
+ return s unless block_given?
39
+ begin
40
+ yield s
41
+ ensure
42
+ s.close
43
+ end
44
+ end
45
+ end
46
+
47
+ alias_method :__asterism_querier, :querier
48
+ alias_method :__asterism_advanced_subscriber, :advanced_subscriber
49
+ alias_method :__asterism_transport_events, :transport_events
50
+ alias_method :__asterism_link_events, :link_events
51
+
52
+ # querier(key, timeout: 2.0, ...) -> Querier (or timeout_ms:).
53
+ def querier(key, timeout: nil, timeout_ms: nil, **opts)
54
+ ms = ::Asterism.time_ms("Session#querier", timeout, timeout_ms, nil, nil)
55
+ opts[:timeout_ms] = ms unless ms.nil?
56
+ __asterism_querier(key, **opts)
57
+ end
58
+
59
+ # advanced_subscriber(key, depth = 16, query_timeout: seconds, ...)
60
+ # (or depth:, query_timeout_ms:).
61
+ def advanced_subscriber(key, *args, depth: nil, query_timeout: nil, query_timeout_ms: nil, **opts)
62
+ d = ::Asterism.depth_of("advanced_subscriber", args, depth, 16)
63
+ ms = ::Asterism.time_ms("Session#advanced_subscriber query_timeout", query_timeout, query_timeout_ms, nil, nil)
64
+ opts[:query_timeout_ms] = ms unless ms.nil?
65
+ __asterism_advanced_subscriber(key, d, **opts)
66
+ end
67
+
68
+ # transport_events(depth = 16, history: false) or with depth:.
69
+ def transport_events(*args, depth: nil, **opts)
70
+ __asterism_transport_events(::Asterism.depth_of("transport_events", args, depth, 16), **opts)
71
+ end
72
+
73
+ # link_events(depth = 16, history: false) or with depth:.
74
+ def link_events(*args, depth: nil, **opts)
75
+ __asterism_link_events(::Asterism.depth_of("link_events", args, depth, 16), **opts)
76
+ end
77
+ end
78
+
79
+ # matching_listener(depth = 16) or matching_listener(depth: 16).
80
+ module MatchingDepth
81
+ def matching_listener(*args, depth: nil)
82
+ super(::Asterism.depth_of("matching_listener", args, depth, 16))
83
+ end
84
+ end
85
+ Publisher.prepend(MatchingDepth)
86
+ AdvancedPublisher.prepend(MatchingDepth)
87
+
88
+ class Querier
89
+ prepend MatchingDepth
90
+ alias_method :__asterism_get, :get
91
+
92
+ # get(params: nil, payload: nil, attachment:, encoding:, depth:) -> Get; the
93
+ # positional get(params, payload) still works.
94
+ def get(*args, params: nil, payload: nil, **opts)
95
+ raise ArgumentError, "get: wrong number of arguments (given #{args.size}, expected 0..2)" if args.size > 2
96
+ raise ArgumentError, "get: params given twice" if args.size > 0 && !params.nil?
97
+ raise ArgumentError, "get: payload given twice" if args.size > 1 && !payload.nil?
98
+ params = args[0] if args.size > 0
99
+ payload = args[1] if args.size > 1
100
+ __asterism_get(params, payload, **opts)
101
+ end
102
+ end
103
+
104
+ class AdvancedSubscriber
105
+ alias_method :__asterism_miss_listener, :miss_listener
106
+ alias_method :__asterism_detect_publishers, :detect_publishers
107
+
108
+ def miss_listener(*args, depth: nil)
109
+ __asterism_miss_listener(::Asterism.depth_of("miss_listener", args, depth, 16))
110
+ end
111
+
112
+ def detect_publishers(*args, depth: nil, **opts)
113
+ __asterism_detect_publishers(::Asterism.depth_of("detect_publishers", args, depth, 16), **opts)
114
+ end
115
+ end
116
+
117
+ class Query
118
+ # The spelled-out names of reply_err and reply_del (those stay).
119
+ def reply_error(payload, **opts)
120
+ reply_err(payload, **opts)
121
+ end
122
+
123
+ def reply_delete(key = nil, **opts)
124
+ reply_del(key, **opts)
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,112 @@
1
+ # The values the C extension hands out (samples, replies, events), and the
2
+ # Ruby half of scouting. Plain immutable Data objects: they work with
3
+ # pattern matching (case sample in {kind: :delete, key:}).
4
+ module Asterism
5
+ module Zenoh
6
+ # A received sample, from Subscriber#each_sample and
7
+ # AdvancedSubscriber#each_sample. payload and attachment are binary
8
+ # Strings (attachment nil when there was none). kind is :put or
9
+ # :delete; encoding a String such as "application/json"; timestamp an
10
+ # Asterism::Zenoh::Timestamp or nil (zenoh only stamps samples when the
11
+ # sender or a router does); priority, congestion_control and
12
+ # reliability Symbols; source_zid the sender's Zenoh ID when it said.
13
+ # Sample.new(key, payload, attachment) still works (the other fields
14
+ # have defaults).
15
+ Sample = Data.define(:key, :payload, :attachment, :kind, :encoding, :timestamp, :priority,
16
+ :congestion_control, :express, :reliability, :source_zid) do
17
+ def initialize(key:, payload:, attachment: nil, kind: :put, encoding: nil, timestamp: nil, priority: nil,
18
+ congestion_control: nil, express: false, reliability: nil, source_zid: nil)
19
+ super
20
+ end
21
+
22
+ # The payload as UTF-8.
23
+ def text
24
+ payload.dup.force_encoding(Encoding::UTF_8)
25
+ end
26
+
27
+ def put? = kind == :put
28
+ def delete? = kind == :delete
29
+ def express? = express
30
+
31
+ def to_s
32
+ "#{key}: #{payload}"
33
+ end
34
+ end
35
+
36
+ # A reply to a get, from Get#each_result: an answer (error false) with
37
+ # the fields of a sample, or an error reply (error true: payload and
38
+ # encoding of the error, key nil). replier_zid: who answered, when known.
39
+ # Reply.new(key, payload, attachment) still works.
40
+ Reply = Data.define(:key, :payload, :attachment, :kind, :encoding, :timestamp, :error, :replier_zid) do
41
+ def initialize(key:, payload:, attachment: nil, kind: :put, encoding: nil, timestamp: nil, error: false,
42
+ replier_zid: nil)
43
+ super
44
+ end
45
+
46
+ def text
47
+ payload.dup.force_encoding(Encoding::UTF_8)
48
+ end
49
+
50
+ def ok? = !error
51
+ def error? = error
52
+
53
+ def to_s
54
+ error ? "error: #{payload}" : "#{key}: #{payload}"
55
+ end
56
+ end
57
+
58
+ # An answer to scouting: a router or peer (whatami :router / :peer /
59
+ # :client), its Zenoh ID and the locators it can be reached at.
60
+ Hello = Data.define(:zid, :whatami, :locators)
61
+
62
+ # A connection to another peer or router (Session#transports).
63
+ Transport = Data.define(:zid, :whatami, :qos, :multicast) do
64
+ def multicast? = multicast
65
+ end
66
+
67
+ # A transport that appeared (kind :added) or went (:removed), from
68
+ # Session#transport_events.
69
+ TransportEvent = Data.define(:kind, :zid, :whatami, :qos, :multicast) do
70
+ def multicast? = multicast
71
+ def added? = kind == :added
72
+ def removed? = kind == :removed
73
+ end
74
+
75
+ # A link (one connection of a transport; Session#links).
76
+ Link = Data.define(:zid, :src, :dst, :mtu, :streamed, :reliability, :interfaces, :group, :auth_identifier) do
77
+ def streamed? = streamed
78
+ end
79
+
80
+ # A link that opened (kind :added) or closed (:removed), from
81
+ # Session#link_events.
82
+ LinkEvent = Data.define(:kind, :zid, :src, :dst, :mtu, :streamed, :reliability, :interfaces, :group,
83
+ :auth_identifier) do
84
+ def streamed? = streamed
85
+ def added? = kind == :added
86
+ def removed? = kind == :removed
87
+ end
88
+
89
+ # Samples that a publisher sent and that never arrived
90
+ # (AdvancedSubscriber#miss_listener): count of them, from the publisher
91
+ # source_zid / source_eid.
92
+ Miss = Data.define(:source_zid, :source_eid, :count)
93
+
94
+ SCOUT_WHAT = { router: 1, peer: 2, client: 4 }.freeze
95
+
96
+ # Looks for routers and / or peers by multicast scouting for timeout
97
+ # seconds (or timeout_ms milliseconds; not both) and returns what
98
+ # answered, as an Array of Hello. what: :router, :peer, :client, an Array of them, or
99
+ # :all. config: a Hash of zenoh configuration keys, as for
100
+ # Session.open (e.g. {"scouting/multicast/interface" => "eth0"}).
101
+ # Multicast must be allowed on the network (it often is not in
102
+ # containers and VPNs).
103
+ def self.scout(what: %i[router peer], timeout: nil, timeout_ms: nil, config: nil)
104
+ kinds = what == :all ? SCOUT_WHAT.keys : Array(what)
105
+ mask = kinds.sum do |k|
106
+ SCOUT_WHAT.fetch(k.to_sym) { raise ArgumentError, "what must be :router, :peer, :client or :all" }
107
+ end
108
+ ms = ::Asterism.time_ms("Asterism::Zenoh.scout", timeout, timeout_ms, nil, 1000)
109
+ _scout(mask, ms, config)
110
+ end
111
+ end
112
+ end
@@ -1,6 +1,6 @@
1
1
  module Asterism
2
2
  module Zenoh
3
3
  # The gem's version.
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
6
6
  end
@@ -1,6 +1,12 @@
1
1
  # Asterism::Zenoh for CRuby: the Zenoh binding of Asterism, over zenoh-c.
2
2
  # The same Ruby API as the mruby / PicoRuby gem (picoruby-asterism-zenoh):
3
3
  # see README.md. Receiving is polled (each_pending / each_reply) from the
4
- # application's own thread; nothing calls into Ruby behind its back.
4
+ # application's own thread; nothing calls into Ruby behind its back. The
5
+ # calls added in 0.3.0 (configuration, publishers, queriers, the advanced
6
+ # publisher / subscriber, events, key expressions, timestamps) are CRuby
7
+ # only: see docs/feature_coverage.md.
5
8
  require_relative "zenoh/version"
6
9
  require_relative "asterism_zenoh"
10
+ require_relative "zenoh/values"
11
+ require_relative "zenoh/common"
12
+ require_relative "zenoh/cruby"
metadata CHANGED
@@ -1,33 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asterism-zenoh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katsuhiko Kageyama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-08 00:00:00.000000000 Z
11
+ date: 2026-10-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Sessions, put / subscribe, get / queryable, liveliness and attachments,
14
- received by polling. The same Ruby API as Asterism's mruby / PicoRuby binding. The
15
- C extension is compiled at install time against the official prebuilt zenoh-c release
16
- for the machine, downloaded and checked against a pinned sha256.
14
+ received by polling. The same Ruby API as Asterism's mruby / PicoRuby binding, plus
15
+ (CRuby only) configuration and TLS, scouting, publishers, queriers, the advanced
16
+ publisher / subscriber, events, key expressions and timestamps. The C extension
17
+ is compiled at install time against the official prebuilt zenoh-c release for the
18
+ machine, downloaded and checked against a pinned sha256.
17
19
  email:
18
20
  executables: []
19
21
  extensions:
20
22
  - ext/asterism_zenoh/extconf.rb
21
23
  extra_rdoc_files: []
22
24
  files:
25
+ - CHANGELOG.md
23
26
  - LICENSE
24
27
  - README.md
25
28
  - ZENOH_C_PIN
29
+ - docs/feature_coverage.md
26
30
  - ext/asterism_zenoh/extconf.rb
27
31
  - ext/asterism_zenoh/zenoh.c
28
32
  - ext/asterism_zenoh/zenoh_c.rb
29
33
  - lib/asterism/zenoh.rb
34
+ - lib/asterism/zenoh/common.rb
35
+ - lib/asterism/zenoh/cruby.rb
30
36
  - lib/asterism/zenoh/global.rb
37
+ - lib/asterism/zenoh/values.rb
31
38
  - lib/asterism/zenoh/version.rb
32
39
  - licenses/zenoh-c/LICENSE-APACHE
33
40
  - licenses/zenoh-c/NOTICE.md