io-like 0.3.1 → 0.4.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 (71) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -1
  3. data/NEWS.md +14 -1
  4. data/README.md +75 -94
  5. data/lib/io/like.rb +1916 -1314
  6. data/lib/io/like_helpers/abstract_io.rb +512 -0
  7. data/lib/io/like_helpers/blocking_io.rb +86 -0
  8. data/lib/io/like_helpers/buffered_io.rb +555 -0
  9. data/lib/io/like_helpers/character_io/basic_reader.rb +122 -0
  10. data/lib/io/like_helpers/character_io/converter_reader.rb +252 -0
  11. data/lib/io/like_helpers/character_io.rb +529 -0
  12. data/lib/io/like_helpers/delegated_io.rb +250 -0
  13. data/lib/io/like_helpers/duplexed_io.rb +259 -0
  14. data/lib/io/like_helpers/io.rb +21 -0
  15. data/lib/io/like_helpers/io_wrapper.rb +290 -0
  16. data/lib/io/like_helpers/pipeline.rb +77 -0
  17. data/lib/io/like_helpers/ruby_facts.rb +33 -0
  18. data/lib/io/like_helpers.rb +14 -0
  19. metadata +107 -224
  20. data/.yardopts +0 -1
  21. data/Rakefile +0 -228
  22. data/ruby.1.8.mspec +0 -7
  23. data/spec/binmode_spec.rb +0 -29
  24. data/spec/close_read_spec.rb +0 -64
  25. data/spec/close_spec.rb +0 -36
  26. data/spec/close_write_spec.rb +0 -61
  27. data/spec/closed_spec.rb +0 -16
  28. data/spec/each_byte_spec.rb +0 -38
  29. data/spec/each_line_spec.rb +0 -11
  30. data/spec/each_spec.rb +0 -11
  31. data/spec/eof_spec.rb +0 -11
  32. data/spec/fixtures/classes.rb +0 -96
  33. data/spec/fixtures/gets.txt +0 -9
  34. data/spec/fixtures/numbered_lines.txt +0 -5
  35. data/spec/fixtures/one_byte.txt +0 -1
  36. data/spec/fixtures/paragraphs.txt +0 -7
  37. data/spec/fixtures/readlines.txt +0 -6
  38. data/spec/flush_spec.rb +0 -8
  39. data/spec/getc_spec.rb +0 -44
  40. data/spec/gets_spec.rb +0 -212
  41. data/spec/isatty_spec.rb +0 -6
  42. data/spec/lineno_spec.rb +0 -84
  43. data/spec/output_spec.rb +0 -47
  44. data/spec/pos_spec.rb +0 -53
  45. data/spec/print_spec.rb +0 -97
  46. data/spec/printf_spec.rb +0 -24
  47. data/spec/putc_spec.rb +0 -57
  48. data/spec/puts_spec.rb +0 -99
  49. data/spec/read_spec.rb +0 -162
  50. data/spec/readchar_spec.rb +0 -49
  51. data/spec/readline_spec.rb +0 -60
  52. data/spec/readlines_spec.rb +0 -140
  53. data/spec/readpartial_spec.rb +0 -92
  54. data/spec/rewind_spec.rb +0 -56
  55. data/spec/seek_spec.rb +0 -72
  56. data/spec/shared/each.rb +0 -204
  57. data/spec/shared/eof.rb +0 -116
  58. data/spec/shared/pos.rb +0 -39
  59. data/spec/shared/tty.rb +0 -12
  60. data/spec/shared/write.rb +0 -53
  61. data/spec/sync_spec.rb +0 -56
  62. data/spec/sysread_spec.rb +0 -87
  63. data/spec/sysseek_spec.rb +0 -68
  64. data/spec/syswrite_spec.rb +0 -60
  65. data/spec/tell_spec.rb +0 -7
  66. data/spec/to_io_spec.rb +0 -19
  67. data/spec/tty_spec.rb +0 -6
  68. data/spec/ungetc_spec.rb +0 -118
  69. data/spec/write_spec.rb +0 -61
  70. data/spec_helper.rb +0 -49
  71. /data/{LICENSE-rubyspec → rubyspec/LICENSE} +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ca93e63077fc81e1bf0bd7d8427525abf8b596f688b6e77c74435c97b0ee2b9e
4
+ data.tar.gz: 7a6db01e11f4c3801f55b6979cd20a996f4de0bd48d23e4712411c011bd8f64a
5
+ SHA512:
6
+ metadata.gz: 5953bc03797b4ed77f36471422a218c31fc3c974433e4fd73c22447f8febcda78be50bb7008b10521020ddea7a28c46fc18fa4633face34700ecb667dd0dda05
7
+ data.tar.gz: fbc480607dd5bb87c6c3697ea72df10af4c4fc3a5c2b1c6f6353f4a39b7f04e8d62ed5847c7dadd4a4dede2d6c1e0e0a39bbc77b599db171d7a6c2d1985bb013
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  (The MIT License)
2
2
 
3
- Copyright (c) 2020 Jeremy Bopp
3
+ Copyright (c) 2024 Jeremy Bopp
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining
6
6
  a copy of this software and associated documentation files (the
data/NEWS.md CHANGED
@@ -3,7 +3,20 @@
3
3
  This file lists noteworthy changes which may affect users of this project. More
4
4
  detailed information is available in the rest of the documentation.
5
5
 
6
- <b>NOTE:</b> Date stamps in the following entries are in YYYY/MM/DD format.
6
+ **NOTE:** Date stamps in the following entries are in YYYY/MM/DD format.
7
+
8
+
9
+ ## v0.4.0.pre1 (2025/05/07)
10
+ * Reimplemented all version specific IO::Like modules as a single class
11
+ * **WARNING:** Breaks API compatibility with prior versions
12
+ * Dropped support for Ruby less than 2.7
13
+ * Added full API compatibility for Ruby 2.7 through 3.4
14
+ * Support for character encodings
15
+ * Asynchronous/nonblocking methods
16
+ * Many missing helper methods
17
+ * Reworked spec handling to make it easier to import rubyspec snapshots almost
18
+ trivially (Grant Gardner, Jeremy Bopp)
19
+ * Added code coverage tooling
7
20
 
8
21
 
9
22
  ## v0.3.1 (2020/02/09)
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # IO::Like - in the Likeness of IO
2
2
 
3
- A module which provides the functionality of an IO object to any including class
4
- which provides a couple of simple methods.
3
+ A composable implementation of IO methods.
5
4
 
6
5
  ## LINKS
7
6
 
@@ -11,27 +10,19 @@ which provides a couple of simple methods.
11
10
 
12
11
  ## DESCRIPTION
13
12
 
14
- The IO::Like module provides all of the methods of typical IO implementations
15
- such as File; most importantly the read, write, and seek series of methods. A
16
- class which includes IO::Like needs to provide only a few methods in order to
17
- enable the higher level methods. Buffering is automatically provided by default
18
- for the methods which normally provide it in IO.
13
+ This gem makes it possible to build filters or pipelines for processing data
14
+ into or out of streams of bytes while maintaining compatibility with native Ruby
15
+ IO classes. Ruby IO classes may function as both sources and sinks, or entirely
16
+ new IO implementations may be created.
19
17
 
20
18
  ## FEATURES
21
19
 
22
- * All standard Ruby 1.8.6 IO operations.
23
- * Buffered operations.
24
- * Configurable buffer size.
20
+ * All standard Ruby 2.7 to 3.4 IO methods
21
+ * Primitive IO interfaces to facilitate creating IO filters/pipelines
25
22
 
26
23
  ## KNOWN BUGS/LIMITATIONS
27
24
 
28
- * Only up to version 1.8.6 of Ruby's IO interface is implemented.
29
- * Ruby's finalization capabilities fall a bit short in a few respects, and as a
30
- result, it is impossible to cause the close, close_read, or close_write
31
- methods to be called automatically when an including class is garbage
32
- collected. Define a class open method in the manner of File.open which
33
- guarantees that an appropriate close method will be called after executing a
34
- block. Other than that, be diligent about calling the close methods.
25
+ * None at this time
35
26
 
36
27
  ## SYNOPSIS
37
28
 
@@ -42,96 +33,96 @@ A simple ROT13 codec:
42
33
 
43
34
  ```ruby
44
35
  require 'io/like'
36
+ require 'io/like_helpers/delegated_io'
37
+ require 'io/like_helpers/io_wrapper'
45
38
 
46
- class ROT13Filter
47
- include IO::Like
39
+ include IO::LikeHelpers
48
40
 
49
- def self.open(delegate_io)
50
- filter = new(delegate_io)
51
- return filter unless block_given?
41
+ class ROT13IO < IO::Like
42
+ def initialize(delegate, autoclose: true, **kwargs)
43
+ delegate = delegate.rot13_filter if self.class === delegate
44
+ @rot13_filter = ROT13Filter.new(delegate, autoclose: autoclose)
52
45
 
53
- begin
54
- yield(filter)
55
- ensure
56
- filter.close unless filter.closed?
57
- end
46
+ super(@rot13_filter, autoclose: true, **kwargs)
58
47
  end
59
48
 
60
- def initialize(delegate_io)
61
- @delegate_io = delegate_io
62
- end
49
+ protected
63
50
 
64
- private
65
-
66
- def encode_rot13(string)
67
- result = string.dup
68
- 0.upto(result.length) do |i|
69
- case result[i]
70
- when 65..90
71
- result[i] = (result[i] - 52) % 26 + 65
72
- when 97..122
73
- result[i] = (result[i] - 84) % 26 + 97
74
- end
75
- end
76
- result
51
+ def rot13_filter
52
+ flush if writable?
53
+ @rot13_filter
77
54
  end
55
+ end
78
56
 
79
- def unbuffered_read(length)
80
- encode_rot13(@delegate_io.sysread(length))
81
- end
57
+ class ROT13Filter < DelegatedIO
58
+ def initialize(delegate, autoclose: true, **kwargs)
59
+ if IO === delegate
60
+ delegate = IOWrapper.new(delegate, autoclose: autoclose)
61
+ autoclose = true
62
+ end
82
63
 
83
- def unbuffered_seek(offset, whence = IO::SEEK_SET)
84
- @delegate_io.sysseek(offset, whence)
64
+ super(delegate, autoclose: autoclose, **kwargs)
85
65
  end
86
66
 
87
- def unbuffered_write(string)
88
- @delegate_io.syswrite(encode_rot13(string))
67
+ def read(length, buffer: nil, buffer_offset: 0)
68
+ result = super
69
+ if buffer.nil?
70
+ encode_rot13(result)
71
+ else
72
+ encode_rot13(buffer, buffer_offset: buffer_offset)
73
+ end
74
+ result
89
75
  end
90
- end
91
-
92
- File.open('normal_file.txt', 'w') do |f|
93
- f.puts('This is a test')
94
- end
95
76
 
96
- File.open('rot13_file.txt', 'w') do |f|
97
- ROT13Filter.open(f) do |rot13|
98
- rot13.puts('This is a test')
77
+ def write(buffer, length: buffer.bytesize)
78
+ super(encode_rot13(buffer[0, length]), length: length)
99
79
  end
100
- end
101
80
 
102
- File.open('normal_file.txt') do |f|
103
- ROT13Filter.open(f) do |rot13|
104
- puts(rot13.read) # -> Guvf vf n grfg
105
- end
106
- end
81
+ private
107
82
 
108
- File.open('rot13_file.txt') do |f|
109
- ROT13Filter.open(f) do |rot13|
110
- puts(rot13.read) # -> This is a test
83
+ def encode_rot13(buffer, buffer_offset: 0)
84
+ buffer_offset.upto(buffer.length - 1) do |i|
85
+ ord = buffer[i].ord
86
+ case ord
87
+ when 65..90
88
+ buffer[i] = ((ord - 52) % 26 + 65).chr
89
+ when 97..122
90
+ buffer[i] = ((ord - 84) % 26 + 97).chr
91
+ end
92
+ end
93
+ buffer
111
94
  end
112
95
  end
113
96
 
114
- File.open('normal_file.txt') do |f|
115
- ROT13Filter.open(f) do |rot13|
116
- rot13.pos = 5
117
- puts(rot13.read) # -> vf n grfg
97
+ if $0 == __FILE__
98
+ # Write encoded content to stdout, leaving stdout open after completion.
99
+ ROT13IO.open(STDOUT, autoclose: false) do |rot13|
100
+ rot13.puts('This is a test. 1234!') # -> Guvf vf n grfg. 1234!
118
101
  end
119
- end
120
102
 
121
- File.open('rot13_file.txt') do |f|
122
- ROT13Filter.open(f) do |rot13|
123
- rot13.pos = 5
124
- puts(rot13.read) # -> is a test
103
+ # Decode content from an input stream and read as lines.
104
+ IO.pipe do |r, w|
105
+ w.puts('This is a test. 1234!')
106
+ w.puts('Guvf vf n grfg. 4567!')
107
+ w.close
108
+ ROT13IO.open(r) do |rot13|
109
+ puts(rot13.each_line.to_a.inspect) # -> ["Guvf vf n grfg. 1234!\n", "This is a test. 4567!\n"]
110
+ end
125
111
  end
126
- end
127
112
 
128
- File.open('normal_file.txt') do |f|
129
- ROT13Filter.open(f) do |rot13|
130
- ROT13Filter.open(rot13) do |rot26| # ;-)
131
- puts(rot26.read) # -> This is a test
113
+ # Double decode content (noop) and dump to stdout using IO.copy_stream.
114
+ IO.pipe do |r, w|
115
+ w.puts('This is a test. 1234!')
116
+ w.close
117
+ ROT13IO.open(r) do |rot13|
118
+ ROT13IO.open(rot13) do |rot26|
119
+ IO.copy_stream(rot26, STDOUT) # -> This is a test. 1234!
120
+ end
132
121
  end
133
122
  end
134
123
  end
124
+
125
+ # vim: ts=2 sw=2 et
135
126
  ```
136
127
 
137
128
  ## REQUIREMENTS
@@ -140,18 +131,8 @@ end
140
131
 
141
132
  ## INSTALL
142
133
 
143
- Download the GEM file and install it with:
144
-
145
- $ gem install io-like-VERSION.gem
146
-
147
- or directly with:
148
-
149
134
  $ gem install io-like
150
135
 
151
- Removal is the same in either case:
152
-
153
- $ gem uninstall io-like
154
-
155
136
  ## DEVELOPERS
156
137
 
157
138
  After checking out the source, run:
@@ -216,7 +197,7 @@ be more easily accepted if they are consistent with the rest of the code.
216
197
  ```
217
198
  (The MIT License)
218
199
 
219
- Copyright (c) 2020 Jeremy Bopp
200
+ Copyright (c) 2024 Jeremy Bopp
220
201
 
221
202
  Permission is hereby granted, free of charge, to any person obtaining
222
203
  a copy of this software and associated documentation files (the
@@ -240,8 +221,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
240
221
 
241
222
  ## RUBYSPEC LICENSE
242
223
 
243
- Files under the `rubyspec` directory are copied whole or in part from the
244
- Rubyspec project.
224
+ Files under the `rubyspec` directory are copied in whole from the Rubyspec
225
+ project.
245
226
 
246
227
  ```
247
228
  Copyright (c) 2008 Engine Yard, Inc. All rights reserved.