cztop 1.0.0 → 1.1.0.pre1

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/coverage.yml +20 -0
  3. data/.github/workflows/draft_api.yml +27 -0
  4. data/.github/workflows/{main.yml → stable_api.yml} +6 -6
  5. data/.rubocop.yml +175 -0
  6. data/CHANGES.md +8 -1
  7. data/Gemfile +5 -0
  8. data/README.md +3 -1
  9. data/ci/install-libczmq +22 -0
  10. data/ci/install-libzmq +22 -0
  11. data/cztop.gemspec +3 -2
  12. data/lib/cztop/actor.rb +55 -26
  13. data/lib/cztop/authenticator.rb +18 -9
  14. data/lib/cztop/beacon.rb +22 -10
  15. data/lib/cztop/cert_store.rb +8 -2
  16. data/lib/cztop/certificate.rb +47 -18
  17. data/lib/cztop/config/comments.rb +14 -3
  18. data/lib/cztop/config/serialization.rb +25 -5
  19. data/lib/cztop/config/traversing.rb +44 -13
  20. data/lib/cztop/config.rb +23 -9
  21. data/lib/cztop/frame.rb +23 -10
  22. data/lib/cztop/has_ffi_delegate.rb +11 -1
  23. data/lib/cztop/message/frames.rb +16 -2
  24. data/lib/cztop/message.rb +36 -22
  25. data/lib/cztop/metadata.rb +35 -24
  26. data/lib/cztop/monitor.rb +14 -5
  27. data/lib/cztop/poller/aggregated.rb +31 -15
  28. data/lib/cztop/poller/zmq.rb +25 -22
  29. data/lib/cztop/poller/zpoller.rb +18 -6
  30. data/lib/cztop/poller.rb +43 -18
  31. data/lib/cztop/polymorphic_zsock_methods.rb +6 -1
  32. data/lib/cztop/proxy.rb +34 -19
  33. data/lib/cztop/send_receive_methods.rb +5 -1
  34. data/lib/cztop/socket/types.rb +128 -22
  35. data/lib/cztop/socket.rb +23 -18
  36. data/lib/cztop/version.rb +5 -1
  37. data/lib/cztop/z85/padded.rb +12 -3
  38. data/lib/cztop/z85/pipe.rb +40 -17
  39. data/lib/cztop/z85.rb +17 -6
  40. data/lib/cztop/zap.rb +57 -32
  41. data/lib/cztop/zsock_options.rb +155 -122
  42. data/lib/cztop.rb +2 -1
  43. metadata +28 -10
  44. data/.ruby-version +0 -1
@@ -1,16 +1,18 @@
1
- module CZTop
1
+ # frozen_string_literal: true
2
2
 
3
+ module CZTop
3
4
  # Authentication for ZeroMQ security mechanisms.
4
5
  #
5
6
  # This is implemented using an {Actor}.
6
7
  #
7
8
  # @see http://api.zeromq.org/czmq3-0:zauth
8
9
  class Authenticator
10
+
9
11
  include ::CZMQ::FFI
10
12
 
11
13
  # function pointer to the +zauth()+ function
12
14
  ZAUTH_FPTR = ::CZMQ::FFI.ffi_libraries.each do |dl|
13
- fptr = dl.find_function("zauth")
15
+ fptr = dl.find_function('zauth')
14
16
  break fptr if fptr
15
17
  end
16
18
  raise LoadError, "couldn't find zauth()" if ZAUTH_FPTR.nil?
@@ -23,6 +25,7 @@ module CZTop
23
25
  def initialize(cert_store = nil)
24
26
  if cert_store
25
27
  raise ArgumentError unless cert_store.is_a?(CertStore)
28
+
26
29
  cert_store = cert_store.ffi_delegate
27
30
  cert_store.__undef_finalizer # native object is now owned by zauth() actor
28
31
  end
@@ -38,13 +41,15 @@ module CZTop
38
41
  @actor.terminate
39
42
  end
40
43
 
44
+
41
45
  # Enable verbose logging of commands and activity.
42
46
  # @return [void]
43
47
  def verbose!
44
- @actor << "VERBOSE"
48
+ @actor << 'VERBOSE'
45
49
  @actor.wait
46
50
  end
47
51
 
52
+
48
53
  # Add a list of IP addresses to the whitelist. For _NULL_, all clients
49
54
  # from these addresses will be accepted. For _PLAIN_ and _CURVE_, they
50
55
  # will be allowed to continue with authentication.
@@ -52,10 +57,11 @@ module CZTop
52
57
  # @param addrs [String] IP address(es) to allow
53
58
  # @return [void]
54
59
  def allow(*addrs)
55
- @actor << ["ALLOW", *addrs]
60
+ @actor << ['ALLOW', *addrs]
56
61
  @actor.wait
57
62
  end
58
63
 
64
+
59
65
  # Add a list of IP addresses to the blacklist. For all security
60
66
  # mechanisms, this rejects the connection without any further
61
67
  # authentication. Use either a whitelist, or a blacklist, not not both. If
@@ -65,22 +71,23 @@ module CZTop
65
71
  # @param addrs [String] IP address(es) to deny
66
72
  # @return [void]
67
73
  def deny(*addrs)
68
- @actor << ["DENY", *addrs]
74
+ @actor << ['DENY', *addrs]
69
75
  @actor.wait
70
76
  end
71
77
 
78
+
72
79
  # Configure PLAIN security mechanism using a plain-text password file. The
73
80
  # password file will be reloaded automatically if modified externally.
74
81
  #
75
82
  # @param filename [String] path to the password file
76
83
  # @return [void]
77
84
  def plain(filename)
78
- @actor << ["PLAIN", *filename]
85
+ @actor << ['PLAIN', *filename]
79
86
  @actor.wait
80
87
  end
81
88
 
82
89
  # used to allow any CURVE client
83
- ALLOW_ANY = "*"
90
+ ALLOW_ANY = '*'
84
91
 
85
92
  # Configure CURVE authentication, using a directory that holds all public
86
93
  # client certificates, i.e. their public keys. The certificates must have been
@@ -90,15 +97,17 @@ module CZTop
90
97
  # @param directory [String] the directory to take the keys from
91
98
  # @return [void]
92
99
  def curve(directory = ALLOW_ANY)
93
- @actor << ["CURVE", directory]
100
+ @actor << ['CURVE', directory]
94
101
  @actor.wait
95
102
  end
96
103
 
104
+
97
105
  # Configure GSSAPI authentication.
98
106
  # @return [void]
99
107
  def gssapi
100
- @actor << "GSSAPI"
108
+ @actor << 'GSSAPI'
101
109
  @actor.wait
102
110
  end
111
+
103
112
  end
104
113
  end
data/lib/cztop/beacon.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  # Used for LAN discovery and presence.
3
5
  #
@@ -5,11 +7,12 @@ module CZTop
5
7
  #
6
8
  # @see http://api.zeromq.org/czmq3-0:zbeacon
7
9
  class Beacon
10
+
8
11
  include ::CZMQ::FFI
9
12
 
10
13
  # function pointer to the +zbeacon()+ function
11
14
  ZBEACON_FPTR = ::CZMQ::FFI.ffi_libraries.each do |dl|
12
- fptr = dl.find_function("zbeacon")
15
+ fptr = dl.find_function('zbeacon')
13
16
  break fptr if fptr
14
17
  end
15
18
  raise LoadError, "couldn't find zbeacon()" if ZBEACON_FPTR.nil?
@@ -28,12 +31,14 @@ module CZTop
28
31
  @actor.terminate
29
32
  end
30
33
 
34
+
31
35
  # Enable verbose logging of commands and activity.
32
36
  # @return [void]
33
37
  def verbose!
34
- @actor << "VERBOSE"
38
+ @actor << 'VERBOSE'
35
39
  end
36
40
 
41
+
37
42
  # Run the beacon on the specified UDP port.
38
43
  #
39
44
  # @param port [Integer] port number to
@@ -43,7 +48,7 @@ module CZTop
43
48
  # interrupted
44
49
  # @raise [NotImplementedError] if the system doesn't support UDP broadcasts
45
50
  def configure(port)
46
- @actor.send_picture("si", :string, "CONFIGURE", :int, port)
51
+ @actor.send_picture('si', :string, 'CONFIGURE', :int, port)
47
52
  ptr = Zstr.recv(@actor)
48
53
 
49
54
  # NULL if context terminated or interrupted
@@ -64,42 +69,49 @@ module CZTop
64
69
  # @raise [ArgumentError] if data is longer than {MAX_BEACON_DATA} bytes
65
70
  # @return [void]
66
71
  def publish(data, interval)
67
- raise ArgumentError, "data too long" if data.bytesize > MAX_BEACON_DATA
68
- @actor.send_picture("sbi", :string, "PUBLISH", :string, data,
69
- :int, data.bytesize, :int, interval)
72
+ raise ArgumentError, 'data too long' if data.bytesize > MAX_BEACON_DATA
73
+
74
+ @actor.send_picture('sbi', :string, 'PUBLISH', :string, data,
75
+ :int, data.bytesize, :int, interval)
70
76
  end
71
77
 
78
+
72
79
  # Stop broadcasting the beacon.
73
80
  # @return [void]
74
81
  def silence
75
- @actor << "SILENCE"
82
+ @actor << 'SILENCE'
76
83
  end
77
84
 
85
+
78
86
  # Start listening to beacons from peers.
79
87
  # @param filter [String] do a prefix match on received beacons
80
88
  # @return [void]
81
89
  def subscribe(filter)
82
- @actor.send_picture("sb", :string, "SUBSCRIBE",
90
+ @actor.send_picture('sb', :string, 'SUBSCRIBE',
83
91
  :string, filter, :int, filter.bytesize)
84
92
  end
85
93
 
94
+
86
95
  # Just like {#subscribe}, but subscribe to all peer beacons.
87
96
  # @return [void]
88
97
  def listen
89
- @actor.send_picture("sb", :string, "SUBSCRIBE",
98
+ @actor.send_picture('sb', :string, 'SUBSCRIBE',
90
99
  :string, nil, :int, 0)
91
100
  end
92
101
 
102
+
93
103
  # Stop listening to other peers.
94
104
  # @return [void]
95
105
  def unsubscribe
96
- @actor << "UNSUBSCRIBE"
106
+ @actor << 'UNSUBSCRIBE'
97
107
  end
98
108
 
109
+
99
110
  # Receive next beacon from a peer.
100
111
  # @return [Message] 2-frame message with ([ipaddr, data])
101
112
  def receive
102
113
  @actor.receive
103
114
  end
115
+
104
116
  end
105
117
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'set'
2
4
 
3
5
  module CZTop
4
-
5
6
  # A store for CURVE security certificates, either backed by files on disk or
6
7
  # in-memory.
7
8
  #
8
9
  # @see http://api.zeromq.org/czmq3-0:zcertstore
9
10
  class CertStore
11
+
10
12
  include ::CZMQ::FFI
11
13
  include HasFFIDelegate
12
14
  extend CZTop::HasFFIDelegate::ClassMethods
@@ -21,6 +23,7 @@ module CZTop
21
23
  attach_ffi_delegate(Zcertstore.new(location))
22
24
  end
23
25
 
26
+
24
27
  # Looks up a certificate in the store by its public key.
25
28
  #
26
29
  # @param pubkey [String] the public key in question, in Z85 format
@@ -29,9 +32,11 @@ module CZTop
29
32
  def lookup(pubkey)
30
33
  ptr = ffi_delegate.lookup(pubkey)
31
34
  return nil if ptr.null?
35
+
32
36
  Certificate.from_ffi_delegate(ptr)
33
37
  end
34
38
 
39
+
35
40
  # Inserts a new certificate into the store.
36
41
  #
37
42
  # @note The same public key must not be inserted more than once.
@@ -43,11 +48,12 @@ module CZTop
43
48
  raise ArgumentError unless cert.is_a?(Certificate)
44
49
 
45
50
  @_inserted_pubkeys ||= Set.new
46
- pubkey = cert.public_key
51
+ pubkey = cert.public_key
47
52
  raise ArgumentError if @_inserted_pubkeys.include? pubkey
48
53
 
49
54
  ffi_delegate.insert(cert.ffi_delegate)
50
55
  @_inserted_pubkeys << pubkey
51
56
  end
57
+
52
58
  end
53
59
  end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  # Represents a CZMQ::FFI::Zcert.
3
5
  class Certificate
6
+
4
7
  include HasFFIDelegate
5
8
  extend CZTop::HasFFIDelegate::ClassMethods
6
9
  include ::CZMQ::FFI
@@ -9,9 +12,11 @@ module CZTop
9
12
  # @return [void]
10
13
  def self.check_curve_availability
11
14
  return if Zsys.has_curve
15
+
12
16
  warn "CZTop: CURVE isn't available. Consider installing libsodium."
13
17
  end
14
18
 
19
+
15
20
  # Loads a certificate from a file.
16
21
  # @param filename [String, Pathname, #to_s] path to certificate file
17
22
  # @return [Certificate] the loaded certificate
@@ -20,6 +25,7 @@ module CZTop
20
25
  from_ffi_delegate(ptr)
21
26
  end
22
27
 
28
+
23
29
  # Creates a new certificate from the given keys (either binary or in Z85
24
30
  # format).
25
31
  # @param public_key [String] binary public key (32 or 40 bytes)
@@ -29,25 +35,28 @@ module CZTop
29
35
  # @raise [ArgumentError] if keys passed are invalid
30
36
  # @raise [SystemCallError] if this fails
31
37
  def self.new_from(public_key, secret_key = nil)
32
- raise ArgumentError, "no public key given" unless public_key
38
+ raise ArgumentError, 'no public key given' unless public_key
39
+
33
40
  secret_key ||= "\x00" * 32 # no secret key given, provide 32 null bytes
34
41
 
35
42
  # convert Z85 => binary
36
43
  public_key = Z85.decode(public_key) if public_key.bytesize == 40
37
44
  secret_key = Z85.decode(secret_key) if secret_key.bytesize == 40
38
45
 
39
- raise ArgumentError, "invalid public key size" if public_key.bytesize != 32
40
- raise ArgumentError, "invalid secret key size" if secret_key.bytesize != 32
46
+ raise ArgumentError, 'invalid public key size' if public_key.bytesize != 32
47
+ raise ArgumentError, 'invalid secret key size' if secret_key.bytesize != 32
41
48
 
42
49
  ptr = Zcert.new_from(public_key, secret_key)
43
50
  from_ffi_delegate(ptr)
44
51
  end
45
52
 
53
+
46
54
  # Initialize a new in-memory certificate with random keys.
47
55
  def initialize
48
56
  attach_ffi_delegate(Zcert.new)
49
57
  end
50
58
 
59
+
51
60
  # Returns the public key either as Z85-encoded ASCII string (default) or
52
61
  # binary string.
53
62
  # @param format [Symbol] +:z85+ for Z85, +:binary+ for binary
@@ -59,10 +68,11 @@ module CZTop
59
68
  when :binary
60
69
  ffi_delegate.public_key.read_string(32)
61
70
  else
62
- raise ArgumentError, "invalid format: %p" % format
71
+ raise ArgumentError, format('invalid format: %p', format)
63
72
  end
64
73
  end
65
74
 
75
+
66
76
  # Returns the secret key either as Z85-encoded ASCII string (default) or
67
77
  # binary string.
68
78
  # @param format [Symbol] +:z85+ for Z85, +:binary+ for binary
@@ -73,16 +83,17 @@ module CZTop
73
83
  case format
74
84
  when :z85
75
85
  key = ffi_delegate.secret_txt.force_encoding(Encoding::ASCII)
76
- return nil if key.count("0") == 40
86
+ return nil if key.count('0') == 40
77
87
  when :binary
78
88
  key = ffi_delegate.secret_key.read_string(32)
79
89
  return nil if key.count("\0") == 32
80
90
  else
81
- raise ArgumentError, "invalid format: %p" % format
91
+ raise ArgumentError, format('invalid format: %p', format)
82
92
  end
83
93
  key
84
94
  end
85
95
 
96
+
86
97
  # Get metadata.
87
98
  # @param key [String] metadata key
88
99
  # @return [String] value for meta key
@@ -90,32 +101,38 @@ module CZTop
90
101
  def [](key)
91
102
  ffi_delegate.meta(key)
92
103
  end
104
+
105
+
93
106
  # Set metadata.
94
107
  # @param key [String] metadata key
95
108
  # @param value [String] metadata value
96
109
  # @return [value]
97
110
  def []=(key, value)
98
111
  if value
99
- ffi_delegate.set_meta(key, "%s", :string, value)
112
+ ffi_delegate.set_meta(key, '%s', :string, value)
100
113
  else
101
114
  ffi_delegate.unset_meta(key)
102
115
  end
103
116
  end
104
117
 
118
+
105
119
  # Returns meta keys set.
106
120
  # @return [Array<String>]
107
121
  def meta_keys
108
- zlist = ffi_delegate.meta_keys
122
+ zlist = ffi_delegate.meta_keys
109
123
  first_key = zlist.first
110
124
  return [] if first_key.null?
125
+
111
126
  keys = [first_key.read_string]
112
- while key = zlist.next
127
+ while (key = zlist.next)
113
128
  break if key.null?
129
+
114
130
  keys << key.read_string
115
131
  end
116
132
  keys
117
133
  end
118
134
 
135
+
119
136
  # Save full certificate (public + secret) to files.
120
137
  # @param filename [String, #to_s] path/filename to public file
121
138
  # @return [void]
@@ -126,55 +143,67 @@ module CZTop
126
143
  def save(filename)
127
144
  # see https://github.com/zeromq/czmq/issues/1244
128
145
  raise ArgumentError, "filename can't be empty" if filename.to_s.empty?
146
+
129
147
  rc = ffi_delegate.save(filename.to_s)
130
- return if rc == 0
131
- raise_zmq_err("error while saving to file %p" % filename)
148
+ return if rc.zero?
149
+
150
+ raise_zmq_err(format('error while saving to file %p', filename))
132
151
  end
133
152
 
153
+
134
154
  # Saves the public key to file in ZPL ({Config}) format.
135
155
  # @param filename [String, #to_s] path/filename to public file
136
156
  # @return [void]
137
157
  # @raise [SystemCallError] if this fails
138
158
  def save_public(filename)
139
159
  rc = ffi_delegate.save_public(filename.to_s)
140
- return if rc == 0
141
- raise_zmq_err("error while saving to the file %p" % filename)
160
+ return if rc.zero?
161
+
162
+ raise_zmq_err(format('error while saving to the file %p', filename))
142
163
  end
143
164
 
165
+
144
166
  # Saves the secret key to file in ZPL ({Config}) format.
145
167
  # @param filename [String, #to_s] path/filename to secret file
146
168
  # @return [void]
147
169
  # @raise [SystemCallError] if this fails
148
170
  def save_secret(filename)
149
171
  rc = ffi_delegate.save_secret(filename.to_s)
150
- return if rc == 0
151
- raise_zmq_err("error while saving to the file %p" % filename)
172
+ return if rc.zero?
173
+
174
+ raise_zmq_err(format('error while saving to the file %p', filename))
152
175
  end
153
176
 
177
+
154
178
  # Applies this certificate on a {Socket} or {Actor}.
155
179
  # @param zocket [Socket, Actor] path/filename to secret file
156
180
  # @return [void]
157
181
  # @raise [SystemCallError] if secret key is undefined
158
182
  def apply(zocket)
159
- raise ArgumentError, "invalid zocket argument %p" % zocket unless zocket
183
+ raise ArgumentError, format('invalid zocket argument %p', zocket) unless zocket
160
184
  return ffi_delegate.apply(zocket) unless secret_key.nil?
161
- raise_zmq_err("secret key is undefined")
185
+
186
+ raise_zmq_err('secret key is undefined')
162
187
  end
163
188
 
189
+
164
190
  # Duplicates the certificate.
165
191
  # @return [Certificate]
166
192
  # @raise [SystemCallError] if this fails
167
193
  def dup
168
194
  ptr = ffi_delegate.dup
169
195
  return from_ffi_delegate(ptr) unless ptr.null?
170
- raise_zmq_err("unable to duplicate certificate")
196
+
197
+ raise_zmq_err('unable to duplicate certificate')
171
198
  end
172
199
 
200
+
173
201
  # Compares this certificate to another.
174
202
  # @param other [Cert] other certificate
175
203
  # @return [Boolean] whether they have the same keys
176
204
  def ==(other)
177
205
  ffi_delegate.eq(other.ffi_delegate)
178
206
  end
207
+
179
208
  end
180
209
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  class Config
3
5
 
@@ -7,11 +9,13 @@ module CZTop
7
9
  # are accessible.
8
10
  # @return [CommentsAccessor]
9
11
  def comments
10
- return CommentsAccessor.new(self)
12
+ CommentsAccessor.new(self)
11
13
  end
12
14
 
15
+
13
16
  # Used to access a {Config}'s comments.
14
17
  class CommentsAccessor
18
+
15
19
  include Enumerable
16
20
 
17
21
  # @param config [Config]
@@ -19,26 +23,30 @@ module CZTop
19
23
  @config = config
20
24
  end
21
25
 
26
+
22
27
  # Adds a new comment.
23
28
  # @param new_comment [String]
24
29
  # @return [self]
25
30
  def <<(new_comment)
26
- @config.ffi_delegate.set_comment("%s", :string, new_comment)
27
- return self
31
+ @config.ffi_delegate.set_comment('%s', :string, new_comment)
32
+ self
28
33
  end
29
34
 
35
+
30
36
  # Deletes all comments for this {Config} item.
31
37
  # @return [void]
32
38
  def delete_all
33
39
  @config.ffi_delegate.set_comment(nil)
34
40
  end
35
41
 
42
+
36
43
  # Yields all comments for this {Config} item.
37
44
  # @yieldparam comment [String]
38
45
  # @return [void]
39
46
  def each
40
47
  while comment = _zlist.next
41
48
  break if comment.null?
49
+
42
50
  yield comment.read_string
43
51
  end
44
52
  rescue CZMQ::FFI::Zlist::DestroyedError
@@ -46,6 +54,7 @@ module CZTop
46
54
  nil
47
55
  end
48
56
 
57
+
49
58
  # Returns the number of comments for this {Config} item.
50
59
  # @return [Integer] number of comments
51
60
  def size
@@ -61,6 +70,8 @@ module CZTop
61
70
  def _zlist
62
71
  @config.ffi_delegate.comments
63
72
  end
73
+
64
74
  end
75
+
65
76
  end
66
77
  end
@@ -1,19 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Methods used around serialization of {CZTop::Config} items.
2
4
  module CZTop::Config::Serialization
5
+
3
6
  # Serialize to a string in the ZPL format.
4
7
  # @return [String]
5
8
  def to_s
6
9
  ffi_delegate.str_save.read_string
7
10
  end
8
11
 
12
+
9
13
  # Returns the path/filename of the file this {Config} tree was loaded from.
10
14
  # @return [String]
11
15
  def filename
12
16
  ffi_delegate.filename
13
17
  end
14
18
 
19
+
15
20
  # Some class methods for {Config} related to serialization.
16
21
  module ClassMethods
22
+
17
23
  # Loads a {Config} tree from a string.
18
24
  # @param string [String] the tree
19
25
  # @return [Config]
@@ -21,6 +27,7 @@ module CZTop::Config::Serialization
21
27
  from_ffi_delegate CZMQ::FFI::Zconfig.str_load(string)
22
28
  end
23
29
 
30
+
24
31
  # Loads a {Config} tree from a file.
25
32
  # @param path [String, Pathname, #to_s] the path to the ZPL config file
26
33
  # @raise [SystemCallError] if this fails
@@ -28,10 +35,13 @@ module CZTop::Config::Serialization
28
35
  def load(path)
29
36
  ptr = CZMQ::FFI::Zconfig.load(path.to_s)
30
37
  return from_ffi_delegate(ptr) unless ptr.null?
38
+
31
39
  CZTop::HasFFIDelegate.raise_zmq_err(
32
- "error while reading the file %p" % path.to_s)
40
+ format('error while reading the file %p', path.to_s)
41
+ )
33
42
  end
34
43
 
44
+
35
45
  # Loads a {Config} tree from a marshalled string.
36
46
  # @note This method is automatically used by Marshal.load.
37
47
  # @param string [String] marshalled {Config}
@@ -39,18 +49,22 @@ module CZTop::Config::Serialization
39
49
  def _load(string)
40
50
  from_string(string)
41
51
  end
52
+
42
53
  end
43
54
 
55
+
44
56
  # Saves the Config tree to a file.
45
57
  # @param path [String, Pathname, #to_s] the path to the ZPL config file
46
58
  # @return [void]
47
59
  # @raise [SystemCallError] if this fails
48
60
  def save(path)
49
61
  rc = ffi_delegate.save(path.to_s)
50
- return if rc == 0
51
- raise_zmq_err("error while saving to the file %s" % path)
62
+ return if rc.zero?
63
+
64
+ raise_zmq_err(format('error while saving to the file %s', path))
52
65
  end
53
66
 
67
+
54
68
  # Reload config tree from same file that it was previously loaded from.
55
69
  # @raise [TypeError] if this is an in-memory config
56
70
  # @raise [SystemCallError] if this fails (no existing data will be
@@ -62,11 +76,13 @@ module CZTop::Config::Serialization
62
76
  # swap out the FFI delegate.
63
77
  filename = filename() or
64
78
  raise TypeError, "can't reload in-memory config"
65
- ptr = CZMQ::FFI::Zconfig.load(filename)
79
+ ptr = CZMQ::FFI::Zconfig.load(filename)
66
80
  return attach_ffi_delegate(ptr) unless ptr.null?
67
- raise_zmq_err("error while reloading from the file %p" % filename)
81
+
82
+ raise_zmq_err(format('error while reloading from the file %p', filename))
68
83
  end
69
84
 
85
+
70
86
  # Serialize (marshal) this Config and all its children.
71
87
  #
72
88
  # @note This method is automatically used by Marshal.dump.
@@ -74,9 +90,13 @@ module CZTop::Config::Serialization
74
90
  def _dump(_level)
75
91
  to_s
76
92
  end
93
+
77
94
  end
78
95
 
96
+
79
97
  class CZTop::Config
98
+
80
99
  include Serialization
81
100
  extend Serialization::ClassMethods
101
+
82
102
  end