ed-precompiled_nio4r 2.7.4-arm64-darwin

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,235 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2016, by Upekshe Jayasekera.
5
+ # Copyright, 2016-2017, by Tony Arcieri.
6
+ # Copyright, 2020, by Thomas Dziedzic.
7
+ # Copyright, 2023, by Samuel Williams.
8
+
9
+ module NIO
10
+ # Efficient byte buffers for performant I/O operations
11
+ class ByteBuffer
12
+ include Enumerable
13
+
14
+ attr_reader :position, :limit, :capacity
15
+
16
+ # Insufficient capacity in buffer
17
+ OverflowError = Class.new(IOError)
18
+
19
+ # Not enough data remaining in buffer
20
+ UnderflowError = Class.new(IOError)
21
+
22
+ # Mark has not been set
23
+ MarkUnsetError = Class.new(IOError)
24
+
25
+ # Create a new ByteBuffer, either with a specified capacity or populating
26
+ # it from a given string
27
+ #
28
+ # @param capacity [Integer] size of buffer in bytes
29
+ #
30
+ # @return [NIO::ByteBuffer]
31
+ def initialize(capacity)
32
+ raise TypeError, "no implicit conversion of #{capacity.class} to Integer" unless capacity.is_a?(Integer)
33
+
34
+ @capacity = capacity
35
+ clear
36
+ end
37
+
38
+ # Clear the buffer, resetting it to the default state
39
+ def clear
40
+ @buffer = ("\0" * @capacity).force_encoding(Encoding::BINARY)
41
+ @position = 0
42
+ @limit = @capacity
43
+ @mark = nil
44
+
45
+ self
46
+ end
47
+
48
+ # Set the position to the given value. New position must be less than limit.
49
+ # Preserves mark if it's less than the new position, otherwise clears it.
50
+ #
51
+ # @param new_position [Integer] position in the buffer
52
+ #
53
+ # @raise [ArgumentError] new position was invalid
54
+ def position=(new_position)
55
+ raise ArgumentError, "negative position given" if new_position < 0
56
+ raise ArgumentError, "specified position exceeds capacity" if new_position > @capacity
57
+
58
+ @mark = nil if @mark && @mark > new_position
59
+ @position = new_position
60
+ end
61
+
62
+ # Set the limit to the given value. New limit must be less than capacity.
63
+ # Preserves limit and mark if they're less than the new limit, otherwise
64
+ # sets position to the new limit and clears the mark.
65
+ #
66
+ # @param new_limit [Integer] position in the buffer
67
+ #
68
+ # @raise [ArgumentError] new limit was invalid
69
+ def limit=(new_limit)
70
+ raise ArgumentError, "negative limit given" if new_limit < 0
71
+ raise ArgumentError, "specified limit exceeds capacity" if new_limit > @capacity
72
+
73
+ @position = new_limit if @position > new_limit
74
+ @mark = nil if @mark && @mark > new_limit
75
+ @limit = new_limit
76
+ end
77
+
78
+ # Number of bytes remaining in the buffer before the limit
79
+ #
80
+ # @return [Integer] number of bytes remaining
81
+ def remaining
82
+ @limit - @position
83
+ end
84
+
85
+ # Does the ByteBuffer have any space remaining?
86
+ #
87
+ # @return [true, false]
88
+ def full?
89
+ remaining.zero?
90
+ end
91
+
92
+ # Obtain the requested number of bytes from the buffer, advancing the position.
93
+ # If no length is given, all remaining bytes are consumed.
94
+ #
95
+ # @raise [NIO::ByteBuffer::UnderflowError] not enough data remaining in buffer
96
+ #
97
+ # @return [String] bytes read from buffer
98
+ def get(length = remaining)
99
+ raise ArgumentError, "negative length given" if length < 0
100
+ raise UnderflowError, "not enough data in buffer" if length > @limit - @position
101
+
102
+ result = @buffer[@position...length]
103
+ @position += length
104
+ result
105
+ end
106
+
107
+ # Obtain the byte at a given index in the buffer as an Integer
108
+ #
109
+ # @raise [ArgumentError] index is invalid (either negative or larger than limit)
110
+ #
111
+ # @return [Integer] byte at the given index
112
+ def [](index)
113
+ raise ArgumentError, "negative index given" if index < 0
114
+ raise ArgumentError, "specified index exceeds limit" if index >= @limit
115
+
116
+ @buffer.bytes[index]
117
+ end
118
+
119
+ # Add a String to the buffer
120
+ #
121
+ # @param str [#to_str] data to add to the buffer
122
+ #
123
+ # @raise [TypeError] given a non-string type
124
+ # @raise [NIO::ByteBuffer::OverflowError] buffer is full
125
+ #
126
+ # @return [self]
127
+ def put(str)
128
+ raise TypeError, "expected String, got #{str.class}" unless str.respond_to?(:to_str)
129
+
130
+ str = str.to_str
131
+
132
+ raise OverflowError, "buffer is full" if str.length > @limit - @position
133
+
134
+ @buffer[@position...str.length] = str
135
+ @position += str.length
136
+ self
137
+ end
138
+ alias << put
139
+
140
+ # Perform a non-blocking read from the given IO object into the buffer
141
+ # Reads as much data as is immediately available and returns
142
+ #
143
+ # @param [IO] Ruby IO object to read from
144
+ #
145
+ # @return [Integer] number of bytes read (0 if none were available)
146
+ def read_from(io)
147
+ nbytes = @limit - @position
148
+ raise OverflowError, "buffer is full" if nbytes.zero?
149
+
150
+ bytes_read = IO.try_convert(io).read_nonblock(nbytes, exception: false)
151
+ return 0 if bytes_read == :wait_readable
152
+
153
+ self << bytes_read
154
+ bytes_read.length
155
+ end
156
+
157
+ # Perform a non-blocking write of the buffer's contents to the given I/O object
158
+ # Writes as much data as is immediately possible and returns
159
+ #
160
+ # @param [IO] Ruby IO object to write to
161
+ #
162
+ # @return [Integer] number of bytes written (0 if the write would block)
163
+ def write_to(io)
164
+ nbytes = @limit - @position
165
+ raise UnderflowError, "no data remaining in buffer" if nbytes.zero?
166
+
167
+ bytes_written = IO.try_convert(io).write_nonblock(@buffer[@position...@limit], exception: false)
168
+ return 0 if bytes_written == :wait_writable
169
+
170
+ @position += bytes_written
171
+ bytes_written
172
+ end
173
+
174
+ # Set the buffer's current position as the limit and set the position to 0
175
+ def flip
176
+ @limit = @position
177
+ @position = 0
178
+ @mark = nil
179
+ self
180
+ end
181
+
182
+ # Set the buffer's current position to 0, leaving the limit unchanged
183
+ def rewind
184
+ @position = 0
185
+ @mark = nil
186
+ self
187
+ end
188
+
189
+ # Mark a position to return to using the `#reset` method
190
+ def mark
191
+ @mark = @position
192
+ self
193
+ end
194
+
195
+ # Reset position to the previously marked location
196
+ #
197
+ # @raise [NIO::ByteBuffer::MarkUnsetError] mark has not been set (call `#mark` first)
198
+ def reset
199
+ raise MarkUnsetError, "mark has not been set" unless @mark
200
+
201
+ @position = @mark
202
+ self
203
+ end
204
+
205
+ # Move data between the position and limit to the beginning of the buffer
206
+ # Sets the position to the end of the moved data, and the limit to the capacity
207
+ def compact
208
+ @buffer[0...(@limit - @position)] = @buffer[@position...@limit]
209
+ @position = @limit - @position
210
+ @limit = capacity
211
+ self
212
+ end
213
+
214
+ # Iterate over the bytes in the buffer (as Integers)
215
+ #
216
+ # @return [self]
217
+ def each(&block)
218
+ @buffer[0...@limit].each_byte(&block)
219
+ end
220
+
221
+ # Inspect the state of the buffer
222
+ #
223
+ # @return [String] string describing the state of the buffer
224
+ def inspect
225
+ format(
226
+ "#<%s:0x%x @position=%d @limit=%d @capacity=%d>",
227
+ self.class,
228
+ object_id << 1,
229
+ @position,
230
+ @limit,
231
+ @capacity
232
+ )
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2018, by Tony Arcieri.
5
+ # Copyright, 2015, by Upekshe Jayasekera.
6
+ # Copyright, 2015, by Vladimir Kochnev.
7
+ # Copyright, 2018-2023, by Samuel Williams.
8
+ # Copyright, 2019-2020, by Gregory Longtin.
9
+
10
+ module NIO
11
+ # Monitors watch IO objects for specific events
12
+ class Monitor
13
+ attr_reader :io, :interests, :selector
14
+ attr_accessor :value, :readiness
15
+
16
+ # :nodoc:
17
+ def initialize(io, interests, selector)
18
+ unless defined?(::OpenSSL) && io.is_a?(::OpenSSL::SSL::SSLSocket)
19
+ unless io.is_a?(IO)
20
+ if IO.respond_to? :try_convert
21
+ io = IO.try_convert(io)
22
+ elsif io.respond_to? :to_io
23
+ io = io.to_io
24
+ end
25
+
26
+ raise TypeError, "can't convert #{io.class} into IO" unless io.is_a? IO
27
+ end
28
+ end
29
+
30
+ @io = io
31
+ @interests = interests
32
+ @selector = selector
33
+ @closed = false
34
+ end
35
+
36
+ # Replace the existing interest set with a new one
37
+ #
38
+ # @param interests [:r, :w, :rw, nil] I/O readiness we're interested in (read/write/readwrite)
39
+ #
40
+ # @return [Symbol] new interests
41
+ def interests=(interests)
42
+ raise EOFError, "monitor is closed" if closed?
43
+ raise ArgumentError, "bad interests: #{interests}" unless [:r, :w, :rw, nil].include?(interests)
44
+
45
+ @interests = interests
46
+ end
47
+
48
+ # Add new interests to the existing interest set
49
+ #
50
+ # @param interests [:r, :w, :rw] new I/O interests (read/write/readwrite)
51
+ #
52
+ # @return [self]
53
+ def add_interest(interest)
54
+ case interest
55
+ when :r
56
+ case @interests
57
+ when :r then @interests = :r
58
+ when :w then @interests = :rw
59
+ when :rw then @interests = :rw
60
+ when nil then @interests = :r
61
+ end
62
+ when :w
63
+ case @interests
64
+ when :r then @interests = :rw
65
+ when :w then @interests = :w
66
+ when :rw then @interests = :rw
67
+ when nil then @interests = :w
68
+ end
69
+ when :rw
70
+ @interests = :rw
71
+ else raise ArgumentError, "bad interests: #{interest}"
72
+ end
73
+ end
74
+
75
+ # Remove interests from the existing interest set
76
+ #
77
+ # @param interests [:r, :w, :rw] I/O interests to remove (read/write/readwrite)
78
+ #
79
+ # @return [self]
80
+ def remove_interest(interest)
81
+ case interest
82
+ when :r
83
+ case @interests
84
+ when :r then @interests = nil
85
+ when :w then @interests = :w
86
+ when :rw then @interests = :w
87
+ when nil then @interests = nil
88
+ end
89
+ when :w
90
+ case @interests
91
+ when :r then @interests = :r
92
+ when :w then @interests = nil
93
+ when :rw then @interests = :r
94
+ when nil then @interests = nil
95
+ end
96
+ when :rw
97
+ @interests = nil
98
+ else raise ArgumentError, "bad interests: #{interest}"
99
+ end
100
+ end
101
+
102
+ # Is the IO object readable?
103
+ def readable?
104
+ readiness == :r || readiness == :rw
105
+ end
106
+
107
+ # Is the IO object writable?
108
+ def writable?
109
+ readiness == :w || readiness == :rw
110
+ end
111
+ alias writeable? writable?
112
+
113
+ # Is this monitor closed?
114
+ def closed?
115
+ @closed
116
+ end
117
+
118
+ # Deactivate this monitor
119
+ def close(deregister = true)
120
+ @closed = true
121
+ @selector.deregister(io) if deregister
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2017, by Tony Arcieri.
5
+ # Copyright, 2012, by Logan Bowers.
6
+ # Copyright, 2013, by Sadayuki Furuhashi.
7
+ # Copyright, 2013, by Stephen von Takach.
8
+ # Copyright, 2013, by Tim Carey-Smith.
9
+ # Copyright, 2013, by Ravil Bayramgalin.
10
+ # Copyright, 2014, by Sergey Avseyev.
11
+ # Copyright, 2014, by John Thornton.
12
+ # Copyright, 2015, by Vladimir Kochnev.
13
+ # Copyright, 2015, by Upekshe Jayasekera.
14
+ # Copyright, 2019-2020, by Gregory Longtin.
15
+ # Copyright, 2020-2021, by Joao Fernandes.
16
+ # Copyright, 2023, by Samuel Williams.
17
+
18
+ require "set"
19
+
20
+ module NIO
21
+ # Selectors monitor IO objects for events of interest
22
+ class Selector
23
+ # Return supported backends as symbols
24
+ #
25
+ # See `#backend` method definition for all possible backends
26
+ def self.backends
27
+ [:ruby]
28
+ end
29
+
30
+ # Create a new NIO::Selector
31
+ def initialize(backend = :ruby)
32
+ raise ArgumentError, "unsupported backend: #{backend}" unless [:ruby, nil].include?(backend)
33
+
34
+ @selectables = {}
35
+ @lock = Mutex.new
36
+
37
+ # Other threads can wake up a selector
38
+ @wakeup, @waker = IO.pipe
39
+ @closed = false
40
+ end
41
+
42
+ # Return a symbol representing the backend I/O multiplexing mechanism used.
43
+ # Supported backends are:
44
+ # * :ruby - pure Ruby (i.e IO.select)
45
+ # * :java - Java NIO on JRuby
46
+ # * :epoll - libev w\ Linux epoll
47
+ # * :poll - libev w\ POSIX poll
48
+ # * :kqueue - libev w\ BSD kqueue
49
+ # * :select - libev w\ SysV select
50
+ # * :port - libev w\ I/O completion ports
51
+ # * :linuxaio - libev w\ Linux AIO io_submit (experimental)
52
+ # * :io_uring - libev w\ Linux io_uring (experimental)
53
+ # * :unknown - libev w\ unknown backend
54
+ def backend
55
+ :ruby
56
+ end
57
+
58
+ # Register interest in an IO object with the selector for the given types
59
+ # of events. Valid event types for interest are:
60
+ # * :r - is the IO readable?
61
+ # * :w - is the IO writeable?
62
+ # * :rw - is the IO either readable or writeable?
63
+ def register(io, interest)
64
+ unless defined?(::OpenSSL) && io.is_a?(::OpenSSL::SSL::SSLSocket)
65
+ io = IO.try_convert(io)
66
+ end
67
+
68
+ @lock.synchronize do
69
+ raise IOError, "selector is closed" if closed?
70
+
71
+ monitor = @selectables[io]
72
+ raise ArgumentError, "already registered as #{monitor.interests.inspect}" if monitor
73
+
74
+ monitor = Monitor.new(io, interest, self)
75
+ @selectables[monitor.io] = monitor
76
+
77
+ monitor
78
+ end
79
+ end
80
+
81
+ # Deregister the given IO object from the selector
82
+ def deregister(io)
83
+ @lock.synchronize do
84
+ monitor = @selectables.delete IO.try_convert(io)
85
+ monitor.close(false) if monitor && !monitor.closed?
86
+ monitor
87
+ end
88
+ end
89
+
90
+ # Is the given IO object registered with the selector?
91
+ def registered?(io)
92
+ @lock.synchronize { @selectables.key? io }
93
+ end
94
+
95
+ # Select which monitors are ready
96
+ def select(timeout = nil)
97
+ selected_monitors = Set.new
98
+
99
+ @lock.synchronize do
100
+ readers = [@wakeup]
101
+ writers = []
102
+
103
+ @selectables.each do |io, monitor|
104
+ readers << io if monitor.interests == :r || monitor.interests == :rw
105
+ writers << io if monitor.interests == :w || monitor.interests == :rw
106
+ monitor.readiness = nil
107
+ end
108
+
109
+ ready_readers, ready_writers = Kernel.select(readers, writers, [], timeout)
110
+ return unless ready_readers # timeout
111
+
112
+ ready_readers.each do |io|
113
+ if io == @wakeup
114
+ # Clear all wakeup signals we've received by reading them
115
+ # Wakeups should have level triggered behavior
116
+ @wakeup.read(@wakeup.stat.size)
117
+ else
118
+ monitor = @selectables[io]
119
+ monitor.readiness = :r
120
+ selected_monitors << monitor
121
+ end
122
+ end
123
+
124
+ ready_writers.each do |io|
125
+ monitor = @selectables[io]
126
+ monitor.readiness = monitor.readiness == :r ? :rw : :w
127
+ selected_monitors << monitor
128
+ end
129
+ end
130
+
131
+ if block_given?
132
+ selected_monitors.each { |m| yield m }
133
+ selected_monitors.size
134
+ else
135
+ selected_monitors.to_a
136
+ end
137
+ end
138
+
139
+ # Wake up a thread that's in the middle of selecting on this selector, if
140
+ # any such thread exists.
141
+ #
142
+ # Invoking this method more than once between two successive select calls
143
+ # has the same effect as invoking it just once. In other words, it provides
144
+ # level-triggered behavior.
145
+ def wakeup
146
+ # Send the selector a signal in the form of writing data to a pipe
147
+ begin
148
+ @waker.write_nonblock "\0"
149
+ rescue IO::WaitWritable
150
+ # This indicates the wakeup pipe is full, which means the other thread
151
+ # has already received many wakeup calls, but not processed them yet.
152
+ # The other thread will completely drain this pipe when it wakes up,
153
+ # so it's ok to ignore this exception if it occurs: we know the other
154
+ # thread has already been signaled to wake up
155
+ end
156
+
157
+ nil
158
+ end
159
+
160
+ # Close this selector and free its resources
161
+ def close
162
+ @lock.synchronize do
163
+ return if @closed
164
+
165
+ begin
166
+ @wakeup.close
167
+ rescue IOError
168
+ end
169
+
170
+ begin
171
+ @waker.close
172
+ rescue IOError
173
+ end
174
+
175
+ @closed = true
176
+ end
177
+ end
178
+
179
+ # Is this selector closed?
180
+ def closed?
181
+ @closed
182
+ end
183
+
184
+ def empty?
185
+ @selectables.empty?
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2018, by Tony Arcieri.
5
+ # Copyright, 2018-2024, by Samuel Williams.
6
+ # Copyright, 2023, by Tsimnuj Hawj.
7
+
8
+ module NIO
9
+ VERSION = "2.7.4"
10
+ end
data/lib/nio.rb ADDED
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2011-2017, by Tony Arcieri.
5
+ # Copyright, 2013, by Stephen von Takach.
6
+ # Copyright, 2013, by Per Lundberg.
7
+ # Copyright, 2014, by Marek Kowalcze.
8
+ # Copyright, 2016, by Upekshe Jayasekera.
9
+ # Copyright, 2019-2023, by Samuel Williams.
10
+ # Copyright, 2021, by Jun Jiang.
11
+
12
+ require "socket"
13
+ require "nio/version"
14
+
15
+ # New I/O for Ruby
16
+ module NIO
17
+ # NIO implementation, one of the following (as a string):
18
+ # * select: in pure Ruby using Kernel.select
19
+ # * libev: as a C extension using libev
20
+ # * java: using Java NIO
21
+ def self.engine
22
+ ENGINE
23
+ end
24
+
25
+ def self.pure?(env = ENV)
26
+ # The user has explicitly opted in to non-native implementation:
27
+ if env["NIO4R_PURE"] == "true"
28
+ return true
29
+ end
30
+
31
+ # Native Ruby on Windows is not supported:
32
+ if (Gem.win_platform? && !defined?(JRUBY_VERSION))
33
+ return true
34
+ end
35
+
36
+ # M1 native extension is crashing on M1 (arm64):
37
+ # if RUBY_PLATFORM =~ /darwin/ && RUBY_PLATFORM =~ /arm64/
38
+ # return true
39
+ # end
40
+
41
+ return false
42
+ end
43
+ end
44
+
45
+ if NIO.pure?
46
+ require "nio/monitor"
47
+ require "nio/selector"
48
+ require "nio/bytebuffer"
49
+ NIO::ENGINE = "ruby"
50
+ else
51
+ begin
52
+ ruby_version = /(\d+\.\d+)/.match(::RUBY_VERSION)
53
+ require "#{ruby_version}/nio4r_ext"
54
+ rescue LoadError
55
+ require "nio4r_ext"
56
+ end
57
+
58
+ if defined?(JRUBY_VERSION)
59
+ require "java"
60
+ require "jruby"
61
+ org.nio4r.Nio4r.new.load(JRuby.runtime, false)
62
+ NIO::ENGINE = "java"
63
+ else
64
+ NIO::ENGINE = "libev"
65
+ end
66
+ end
data/lib/nio4r.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Phillip Aldridge.
5
+ # Copyright, 2023, by Samuel Williams.
6
+
7
+ require_relative "nio"
data/license.md ADDED
@@ -0,0 +1,80 @@
1
+ # MIT License
2
+
3
+ Copyright, 2011-2020, by Tony Arcieri.
4
+ Copyright, 2012, by Bernd Ahlers.
5
+ Copyright, 2012, by Logan Bowers.
6
+ Copyright, 2012, by Dirkjan Bussink.
7
+ Copyright, 2013, by Sadayuki Furuhashi.
8
+ Copyright, 2013, by Shannon Skipper.
9
+ Copyright, 2013, by Stephen von Takach.
10
+ Copyright, 2013, by Tim Carey-Smith.
11
+ Copyright, 2013, by Per Lundberg.
12
+ Copyright, 2013, by Ravil Bayramgalin.
13
+ Copyright, 2013, by Luis Lavena.
14
+ Copyright, 2014, by Anatol Pomozov.
15
+ Copyright, 2014, by Hiroshi Shibata.
16
+ Copyright, 2014, by Marek Kowalcze.
17
+ Copyright, 2014, by Sergey Avseyev.
18
+ Copyright, 2014, by John Thornton.
19
+ Copyright, 2015-2017, by Tiago Cardoso.
20
+ Copyright, 2015, by Daniel Berger.
21
+ Copyright, 2015-2016, by Upekshe Jayasekera.
22
+ Copyright, 2015, by Vladimir Kochnev.
23
+ Copyright, 2016-2018, by Jun Aruga.
24
+ Copyright, 2016, by Omer Katz.
25
+ Copyright, 2016, by Denis Washington.
26
+ Copyright, 2016-2021, by Olle Jonsson.
27
+ Copyright, 2017, by Tao Luo.
28
+ Copyright, 2017, by Usaku Nakamura.
29
+ Copyright, 2017-2022, by Gregory Longtin.
30
+ Copyright, 2017, by Lars Kanis.
31
+ Copyright, 2017, by Tomoya Ishida.
32
+ Copyright, 2018-2024, by Samuel Williams.
33
+ Copyright, 2019, by Cédric Boutillier.
34
+ Copyright, 2019-2020, by Benoit Daloze.
35
+ Copyright, 2019, by Jesús Burgos Maciá.
36
+ Copyright, 2019, by Thomas Kuntz.
37
+ Copyright, 2019, by Orien Madgwick.
38
+ Copyright, 2019, by Zhang Kang.
39
+ Copyright, 2020, by Thomas Dziedzic.
40
+ Copyright, 2020, by Elad Eyal.
41
+ Copyright, 2020, by Pedro Paiva.
42
+ Copyright, 2020, by Boaz Segev.
43
+ Copyright, 2020, by Charles Oliver Nutter.
44
+ Copyright, 2020-2021, by Joao Fernandes.
45
+ Copyright, 2021, by Jun Jiang.
46
+ Copyright, 2021, by Pavel Lobashov.
47
+ Copyright, 2021, by Jeffrey Martin.
48
+ Copyright, 2023-2024, by Pavel Rosický.
49
+ Copyright, 2023, by Tsimnuj Hawj.
50
+ Copyright, 2023, by Phillip Aldridge.
51
+ Copyright, 2023, by Maxime Demolin.
52
+ Copyright, 2023-2024, by Vít Ondruch.
53
+ Copyright, 2023, by Jean Boussier.
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining a copy
56
+ of this software and associated documentation files (the "Software"), to deal
57
+ in the Software without restriction, including without limitation the rights
58
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
59
+ copies of the Software, and to permit persons to whom the Software is
60
+ furnished to do so, subject to the following conditions:
61
+
62
+ The above copyright notice and this permission notice shall be included in all
63
+ copies or substantial portions of the Software.
64
+
65
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
66
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
67
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
69
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
70
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
71
+ SOFTWARE.
72
+
73
+ ## libev
74
+
75
+ Released under the BSD-2-Clause OR GPL-2.0-or-later license.
76
+ See [ext/libev/LICENSE] for details.
77
+
78
+ Copyright, 2007-2019, by Marc Alexander Lehmann.
79
+
80
+ [ext/libev/LICENSE]: https://github.com/socketry/nio4r/blob/master/ext/libev/LICENSE