linefeed 0.2.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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +93 -0
- data/examples/01_logger.rb +16 -0
- data/examples/02_canonicalize.rb +28 -0
- data/examples/03_escaped.rb +23 -0
- data/examples/04_line_digest.rb +24 -0
- data/examples/05_chunk_digest.rb +24 -0
- data/examples/06_canonicalized_digest.rb +12 -0
- data/examples/07_null.rb +27 -0
- data/examples/consumer.rb +16 -0
- data/examples/demo.rb +25 -0
- data/examples/demo_helper.rb +31 -0
- data/lib/linefeed/version.rb +5 -0
- data/lib/linefeed.rb +47 -0
- data/test/test_linefeed.rb +95 -0
- metadata +99 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8e42d833b1d76721fb8906bdc579c93f0b5ab46071d2f0168adb3ffdef69f39b
|
|
4
|
+
data.tar.gz: 5e63818116b3d40432460f2cb90b516f0617a6dbaa67556ce0b8b4637da80161
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6767fa2a9741565af3dc7e92fe96f474a58d4aa250f8db67ab1b619c886fce099f0565b9c87a29d9cb9bbffd78ac5a2ec569b6749be88b30d5f391ddaca751a3
|
|
7
|
+
data.tar.gz: a58bba06bd570e0225f130c757ea7993809791b8cedd51ccb4f9ab59b77c68d6c941cd0e1e00e3bafc9ea61f94207e7bfdbf266bc3295470e675a08c4ad0e4a3
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 inopinatus
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Linefeed
|
|
2
|
+
|
|
3
|
+
Linefeed turns a push-style byte stream, of any chunk size, into individually yielded lines.
|
|
4
|
+
|
|
5
|
+
* https://github.com/inopinatus/linefeed
|
|
6
|
+
|
|
7
|
+
## Why?
|
|
8
|
+
|
|
9
|
+
When you're downstream of the read on a binary-mode chunked stream and can't easily turn that into a nice efficient `IO#readlines`.
|
|
10
|
+
|
|
11
|
+
Also, it has nice properties if you chain them together.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```console
|
|
16
|
+
gem install linefeed
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or add it to your Gemfile:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
gem "linefeed"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Protocol
|
|
26
|
+
|
|
27
|
+
Including `linefeed` supplies two methods, `#<<` and `#close`. The idea is for external
|
|
28
|
+
producers to drive processing by calls to these methods.
|
|
29
|
+
|
|
30
|
+
- `#<<` accepts an arbitrary-size chunk of incoming data and yields each LF-terminated line
|
|
31
|
+
to a handler set by `linefeed { |line| ... }` as an 8-bit ASCII string. Lines yielded
|
|
32
|
+
will include the trailing LF.
|
|
33
|
+
|
|
34
|
+
- `#close` marks end-of-incoming-data; if any data persists in the buffer, this yields a
|
|
35
|
+
final unterminated string to the same handler.
|
|
36
|
+
|
|
37
|
+
These method names are intentionally IO-ish so that you can mingle regular output files
|
|
38
|
+
& IO streams with `linefeed` objects.
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
require "linefeed"
|
|
44
|
+
|
|
45
|
+
class Collector
|
|
46
|
+
include Linefeed
|
|
47
|
+
|
|
48
|
+
def initialize
|
|
49
|
+
@lines = []
|
|
50
|
+
linefeed { |line| @lines << line }
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
collector = Collector.new
|
|
55
|
+
collector << "hello\nwor"
|
|
56
|
+
collector << "ld\n"
|
|
57
|
+
collector.close
|
|
58
|
+
|
|
59
|
+
# @lines => ["hello\n", "world\n"]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Write custom `#<<` and `#close` handlers by passing blocks to `super` blocks:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
def <<(chunk)
|
|
66
|
+
super(chunk) do |line|
|
|
67
|
+
puts escape(line)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def close
|
|
72
|
+
super do |line|
|
|
73
|
+
puts escape(line) + "\n"
|
|
74
|
+
end
|
|
75
|
+
puts " -- all done."
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
See `examples/` for more, like daisy-chaining, or updating a digest.
|
|
80
|
+
|
|
81
|
+
## Examples
|
|
82
|
+
|
|
83
|
+
Run `examples/demo.rb` and review the numbered examples it includes.
|
|
84
|
+
|
|
85
|
+
If testing with cooked interactive input at the console, note that `linefeed`'s examples necessarily read in binary mode, so ^D may not be instant EOF.
|
|
86
|
+
|
|
87
|
+
## License
|
|
88
|
+
|
|
89
|
+
MIT. Copyright (c) 2025 inopinatus.
|
|
90
|
+
|
|
91
|
+
## Contributing
|
|
92
|
+
|
|
93
|
+
At https://github.com/inopinatus/linefeed.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
|
|
4
|
+
# Simplest possible example
|
|
5
|
+
module Demo
|
|
6
|
+
class Logger
|
|
7
|
+
include Linefeed
|
|
8
|
+
|
|
9
|
+
def initialize(output)
|
|
10
|
+
line_no = 0
|
|
11
|
+
linefeed do |line|
|
|
12
|
+
output << "%.3d => %s" % [line_no += 1, line]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
|
|
4
|
+
# Per-line processing with headers & trailers
|
|
5
|
+
module Demo
|
|
6
|
+
class Canonicalize < Consumer
|
|
7
|
+
def initialize(*)
|
|
8
|
+
super
|
|
9
|
+
@output << "---------- START\r\n"
|
|
10
|
+
@output << "Canonicalized: yes\r\n"
|
|
11
|
+
@output << "\r\n"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def process_line(line)
|
|
15
|
+
canonicalize(line)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def canonicalize(line)
|
|
19
|
+
line.chomp.sub(/[ \t]+$/, "") + "\r\n"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def close
|
|
23
|
+
super
|
|
24
|
+
@output << "---------- END\r\n"
|
|
25
|
+
@output.close
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
|
|
4
|
+
# Handling the protocol via super
|
|
5
|
+
module Demo
|
|
6
|
+
class Escaped < Consumer
|
|
7
|
+
def escape(line)
|
|
8
|
+
line.sub(/^(-|From )/, "- \\1")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def <<(chunk)
|
|
12
|
+
super(chunk) do |line|
|
|
13
|
+
@output << escape(line)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def close
|
|
18
|
+
super do |line|
|
|
19
|
+
@output << escape(line) + "\n"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
# Only outputs at close
|
|
6
|
+
module Demo
|
|
7
|
+
class LineDigest
|
|
8
|
+
include Linefeed
|
|
9
|
+
|
|
10
|
+
def initialize(output)
|
|
11
|
+
@output = output
|
|
12
|
+
@line_digest = Digest("SHA256").new
|
|
13
|
+
|
|
14
|
+
linefeed do |line|
|
|
15
|
+
@line_digest.update(line)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def close
|
|
20
|
+
super
|
|
21
|
+
@output << @line_digest.hexdigest
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
require "digest"
|
|
4
|
+
|
|
5
|
+
# Not actually using Linefeed, but speaking the same protocol,
|
|
6
|
+
# consuming entire chunks.
|
|
7
|
+
#
|
|
8
|
+
# Should give the same digest as LineDigest.
|
|
9
|
+
module Demo
|
|
10
|
+
class ChunkDigest
|
|
11
|
+
def initialize(output)
|
|
12
|
+
@output = output
|
|
13
|
+
@digest = Digest("SHA256").new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def <<(chunk)
|
|
17
|
+
@digest << chunk
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def close
|
|
21
|
+
@output << @digest.hexdigest
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
require "delegate"
|
|
4
|
+
|
|
5
|
+
# Easy chaining
|
|
6
|
+
module Demo
|
|
7
|
+
class CanonicalizedDigest < DelegateClass(Consumer)
|
|
8
|
+
def initialize(output)
|
|
9
|
+
super(Canonicalize.new(LineDigest.new(output)))
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/examples/07_null.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'demo'
|
|
3
|
+
|
|
4
|
+
# Intentionally fails to setup the feed and suffers for it.
|
|
5
|
+
# Don't do this.
|
|
6
|
+
module Demo
|
|
7
|
+
class Null
|
|
8
|
+
include Linefeed
|
|
9
|
+
|
|
10
|
+
def initialize(output)
|
|
11
|
+
@output = output
|
|
12
|
+
@count = 0
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def <<(*)
|
|
16
|
+
super
|
|
17
|
+
rescue ArgumentError
|
|
18
|
+
@count += 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def close
|
|
22
|
+
super
|
|
23
|
+
rescue ArgumentError
|
|
24
|
+
@output << "rescued #{@count += 1} time(s)"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/examples/demo.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative "../lib/linefeed"
|
|
3
|
+
require_relative "demo_helper"
|
|
4
|
+
|
|
5
|
+
if $0 == __FILE__
|
|
6
|
+
example_files = Dir[File.join(__dir__, "[0-9][0-9]_*.rb")].sort
|
|
7
|
+
example_files.each do |path|
|
|
8
|
+
require_relative File.basename(path)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
recipients = Demo.setup_examples
|
|
14
|
+
maxlen = 8192
|
|
15
|
+
chunk = "".b
|
|
16
|
+
|
|
17
|
+
while $stdin.read(maxlen, chunk)
|
|
18
|
+
recipients.each do |r|
|
|
19
|
+
r << chunk
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
recipients.each(&:close)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
at_exit { run } unless @at_exit_installed; @at_exit_installed = true
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require_relative 'consumer'
|
|
3
|
+
|
|
4
|
+
module Demo
|
|
5
|
+
# IO trap
|
|
6
|
+
class Output
|
|
7
|
+
def initialize(klass)=@prefix = klass.to_s
|
|
8
|
+
def <<(o)=puts "#{@prefix}: #{o.inspect}"
|
|
9
|
+
def close()=puts "#{@prefix} closed."
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Example registry
|
|
13
|
+
@example_classes = []
|
|
14
|
+
class << self
|
|
15
|
+
def const_added(const_name)
|
|
16
|
+
super
|
|
17
|
+
if const_get(const_name, false) in Class => klass
|
|
18
|
+
register(klass)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def register(klass)
|
|
23
|
+
@example_classes << klass
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def setup_examples
|
|
27
|
+
@example_classes.map { |k| k.new(Output.new(k)) }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
data/lib/linefeed.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "linefeed/version"
|
|
4
|
+
|
|
5
|
+
module Linefeed
|
|
6
|
+
class Error < StandardError; end
|
|
7
|
+
|
|
8
|
+
def linefeed(&default_proc)
|
|
9
|
+
@__linefeed_default = default_proc
|
|
10
|
+
__linefeed_reset
|
|
11
|
+
self
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def __linefeed_reset
|
|
15
|
+
@__linefeed_buffer = +"".b
|
|
16
|
+
@__linefeed_closed = false
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Called by push-type source to write to us.
|
|
21
|
+
def <<(chunk, &per_line)
|
|
22
|
+
per_line ||= @__linefeed_default
|
|
23
|
+
raise Error, "already closed" if @__linefeed_closed
|
|
24
|
+
raise ArgumentError, "no line handler" unless per_line
|
|
25
|
+
|
|
26
|
+
@__linefeed_buffer ||= +"".b
|
|
27
|
+
@__linefeed_buffer << chunk
|
|
28
|
+
|
|
29
|
+
while (eol = @__linefeed_buffer.index("\n"))
|
|
30
|
+
per_line.call(@__linefeed_buffer.slice!(0..eol)) # includes the "\n"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Called at end-of-stream.
|
|
37
|
+
def close(&per_line)
|
|
38
|
+
per_line ||= @__linefeed_default
|
|
39
|
+
raise Error, "already closed" if @__linefeed_closed
|
|
40
|
+
raise ArgumentError, "no line handler" unless per_line
|
|
41
|
+
@__linefeed_closed = true
|
|
42
|
+
return self if !@__linefeed_buffer || @__linefeed_buffer.empty?
|
|
43
|
+
|
|
44
|
+
per_line.call(@__linefeed_buffer.slice!(0, @__linefeed_buffer.bytesize)) # final unterminated line
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest/autorun"
|
|
4
|
+
require_relative "../lib/linefeed"
|
|
5
|
+
|
|
6
|
+
class LinefeedTest < Minitest::Test
|
|
7
|
+
class StandardReceiver
|
|
8
|
+
include Linefeed
|
|
9
|
+
attr_reader :lines
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@lines = []
|
|
13
|
+
linefeed { |line| @lines << line }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class CustomReceiver
|
|
18
|
+
include Linefeed
|
|
19
|
+
attr_reader :lines
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@lines = []
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def <<(chunk)
|
|
26
|
+
super do |line|
|
|
27
|
+
@lines << "line:#{line}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def close
|
|
32
|
+
super do |line|
|
|
33
|
+
@lines << "eof:#{line}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_basic_yield
|
|
39
|
+
receiver = StandardReceiver.new
|
|
40
|
+
receiver << "a\nb\n"
|
|
41
|
+
|
|
42
|
+
assert_equal ["a\n", "b\n"], receiver.lines
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_works_across_chunks
|
|
46
|
+
receiver = StandardReceiver.new
|
|
47
|
+
receiver << "a"
|
|
48
|
+
receiver << "\n"
|
|
49
|
+
receiver << "b"
|
|
50
|
+
receiver << "\n"
|
|
51
|
+
|
|
52
|
+
assert_equal ["a\n", "b\n"], receiver.lines
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_flush_unterminated
|
|
56
|
+
receiver = StandardReceiver.new
|
|
57
|
+
receiver << "tail"
|
|
58
|
+
receiver.close
|
|
59
|
+
|
|
60
|
+
assert_equal ["tail"], receiver.lines
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_empty_close_does_nothing
|
|
64
|
+
receiver = StandardReceiver.new
|
|
65
|
+
receiver.close
|
|
66
|
+
|
|
67
|
+
assert_equal [], receiver.lines
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def test_you_forget_the_handlers
|
|
71
|
+
obj = Object.new
|
|
72
|
+
obj.extend(Linefeed)
|
|
73
|
+
|
|
74
|
+
assert_raises(ArgumentError) { obj << "a\n" }
|
|
75
|
+
assert_raises(ArgumentError) { obj.close }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_raise_after_close
|
|
79
|
+
receiver = StandardReceiver.new
|
|
80
|
+
receiver.close
|
|
81
|
+
|
|
82
|
+
assert_raises(Linefeed::Error) { receiver << "a\n" }
|
|
83
|
+
assert_raises(Linefeed::Error) { receiver.close }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_custom_handlers
|
|
87
|
+
receiver = CustomReceiver.new
|
|
88
|
+
|
|
89
|
+
receiver << "a"
|
|
90
|
+
receiver << "\n"
|
|
91
|
+
receiver << "b"
|
|
92
|
+
receiver.close
|
|
93
|
+
assert_equal ["line:a\n", "eof:b"], receiver.lines
|
|
94
|
+
end
|
|
95
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: linefeed
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Joshua Goodall
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: minitest
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rake
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: irb
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
description: Linefeed turns a push-style byte stream, of any chunk size, into individually
|
|
55
|
+
yielded lines.
|
|
56
|
+
email: inopinatus@hey.com
|
|
57
|
+
executables: []
|
|
58
|
+
extensions: []
|
|
59
|
+
extra_rdoc_files: []
|
|
60
|
+
files:
|
|
61
|
+
- LICENSE
|
|
62
|
+
- README.md
|
|
63
|
+
- examples/01_logger.rb
|
|
64
|
+
- examples/02_canonicalize.rb
|
|
65
|
+
- examples/03_escaped.rb
|
|
66
|
+
- examples/04_line_digest.rb
|
|
67
|
+
- examples/05_chunk_digest.rb
|
|
68
|
+
- examples/06_canonicalized_digest.rb
|
|
69
|
+
- examples/07_null.rb
|
|
70
|
+
- examples/consumer.rb
|
|
71
|
+
- examples/demo.rb
|
|
72
|
+
- examples/demo_helper.rb
|
|
73
|
+
- lib/linefeed.rb
|
|
74
|
+
- lib/linefeed/version.rb
|
|
75
|
+
- test/test_linefeed.rb
|
|
76
|
+
homepage: https://github.com/inopinatus/linefeed
|
|
77
|
+
licenses:
|
|
78
|
+
- MIT
|
|
79
|
+
metadata:
|
|
80
|
+
homepage_uri: https://github.com/inopinatus/linefeed
|
|
81
|
+
source_code_uri: https://github.com/inopinatus/linefeed
|
|
82
|
+
rdoc_options: []
|
|
83
|
+
require_paths:
|
|
84
|
+
- lib
|
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '3.4'
|
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - ">="
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '0'
|
|
95
|
+
requirements: []
|
|
96
|
+
rubygems_version: 4.0.3
|
|
97
|
+
specification_version: 4
|
|
98
|
+
summary: Yield lines from arbitrarily chunked byte streams
|
|
99
|
+
test_files: []
|