protocol-htty 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87a3aa4c350c134deb40265ae418e15fbd1158b70a8cf4c21e1748de514ca867
4
- data.tar.gz: 506e9101a8df67e75aed817e3227919e06dc00ee5aa8d58d62c6d7139ae8d1ea
3
+ metadata.gz: 957aa78a655ceb3136db0acd1614010a25d1cda14b6e0861e6ebfb371870b739
4
+ data.tar.gz: d70de3f0375aef142f90beca94c2bd50f9986bbc6bfaf2920ea64dae13185467
5
5
  SHA512:
6
- metadata.gz: 82d2c3b0fbbd56482711a10da4dad9e0e86177168d1cbc198d126e1d0c347e27dd3123e5d3982f9884e7bc2ee8b8f1be429164f06f16d5c3dde65ff5424750e3
7
- data.tar.gz: cb61305b1df49d733cc5b4e0755d2d8962813eafc1e3fb2137122014643b7b7a90bfd44e2490edd428eb32b8bb9a7e31745bfeaa8b8b847ea1ad39d5c2f8aa25
6
+ metadata.gz: cdc24469f4d8bad151261849af0a4bd85b5ca86d2f6f007404e131cf90ab18f6fd279a82634a46565f3ffa19337c698741103c64220b7c89a8c1261d44652eea
7
+ data.tar.gz: 750995dc4c72f1eb9026bbba25795c8b5489d734d48e93edae8cabad4af12b4bc6a69746550e044f10ceaac2eab3f15fc6e2dddb08a919eccbc953c12c833ef3
checksums.yaml.gz.sig CHANGED
Binary file
@@ -3,8 +3,6 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2026, by Samuel Williams.
5
5
 
6
- require "io/stream"
7
-
8
6
  module Protocol
9
7
  module HTTY
10
8
  # Transport an opaque byte stream after the HTTY bootstrap handshake.
@@ -15,11 +13,13 @@ module Protocol
15
13
  BOOTSTRAP_PREFIX = "+H"
16
14
  RAW_MODE = "raw"
17
15
 
18
- HTTP2_FRAME_HEADER_SIZE = 9
19
-
20
16
  def self.open(input, output, bootstrap: nil, mode: RAW_MODE)
21
17
  stream = self.new(input, output)
22
18
 
19
+ # Disable buffering:
20
+ input.sync = true
21
+ output.sync = true
22
+
23
23
  case bootstrap
24
24
  when :write
25
25
  stream.write_bootstrap(mode)
@@ -39,8 +39,7 @@ module Protocol
39
39
  # @parameter output [IO] The writable endpoint.
40
40
  def initialize(input, output)
41
41
  @input = input
42
- @output = ::IO::Stream(output)
43
- @frame_remaining = nil
42
+ @output = output
44
43
  @local_closed = false
45
44
  end
46
45
 
@@ -73,27 +72,9 @@ module Protocol
73
72
  end
74
73
 
75
74
  # Read application bytes from the HTTY transport.
75
+ # The HTTP/2 framer always requests exact byte counts (header size, then payload length), so we delegate directly to the underlying input.
76
76
  def read(length = nil)
77
- if length == 0
78
- @frame_remaining = nil if @frame_remaining == 0
79
- return +"".b
80
- end
81
-
82
- requested_length = length
83
- length = [length, @frame_remaining].min if length && @frame_remaining && @frame_remaining > 0
84
- buffer = read_exact(length)
85
-
86
- if buffer && requested_length == HTTP2_FRAME_HEADER_SIZE && !@frame_remaining
87
- if buffer.bytesize == HTTP2_FRAME_HEADER_SIZE
88
- frame_length = self.class.frame_length(buffer)
89
- @frame_remaining = frame_length if frame_length > 0
90
- end
91
- elsif buffer && @frame_remaining
92
- @frame_remaining -= buffer.bytesize
93
- @frame_remaining = nil if @frame_remaining <= 0
94
- end
95
-
96
- return buffer
77
+ @input.read(length)
97
78
  end
98
79
 
99
80
  # Write application bytes after bootstrap.
@@ -140,33 +121,8 @@ module Protocol
140
121
 
141
122
  private
142
123
 
143
- def self.frame_length(buffer)
144
- length_high, length_low = buffer.unpack("Cn")
145
- return (length_high << 16) | length_low
146
- end
147
-
148
- def read_exact(length)
149
- return @input.read if length.nil?
150
-
151
- buffer = +"".b
152
-
153
- while buffer.bytesize < length
154
- chunk = read_some(length - buffer.bytesize)
155
- break unless chunk
156
-
157
- buffer << chunk.b
158
- end
159
-
160
- return nil if buffer.empty?
161
- return buffer
162
- end
163
-
164
124
  def read_some(length)
165
- if @input.respond_to?(:readpartial)
166
- @input.readpartial(length)
167
- else
168
- @input.read(length)
169
- end
125
+ @input.read(length)
170
126
  rescue EOFError, Errno::EIO
171
127
  return nil
172
128
  end
@@ -186,7 +142,7 @@ module Protocol
186
142
  end
187
143
 
188
144
  def consume_packet
189
- buffer = +""
145
+ buffer = String.new.b
190
146
 
191
147
  while chunk = read_some(1)
192
148
  if chunk == ESC
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module HTTY
8
- VERSION = "0.3.0"
8
+ VERSION = "0.4.0"
9
9
  end
10
10
  end
data/readme.md CHANGED
@@ -36,6 +36,11 @@ Please see the [project documentation](https://socketry.github.io/protocol-htty/
36
36
 
37
37
  Please see the [project releases](https://socketry.github.io/protocol-htty/releases/index) for all releases.
38
38
 
39
+ ### v0.4.0
40
+
41
+ - **Breaking**: Drop the `io-stream` dependency. `Stream.new` and `Stream.open` no longer coerce or wrap their `input` and `output` arguments; raw IO objects are used as-is. Callers that relied on `stream.io` returning an `IO::Stream::Buffered` should wrap the IO themselves before passing it in.
42
+ - Simplify `Stream#read` to delegate directly to the underlying input, since the HTTP/2 framer always requests exact byte counts (header size, then payload length).
43
+
39
44
  ### v0.3.0
40
45
 
41
46
  - Change `Protocol::HTTY::Stream` to take explicit input and output endpoints using `Stream.new(input, output)` and `Stream.open(input, output, **options)`.
data/releases.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Releases
2
2
 
3
+ ## v0.4.0
4
+
5
+ - **Breaking**: Drop the `io-stream` dependency. `Stream.new` and `Stream.open` no longer coerce or wrap their `input` and `output` arguments; raw IO objects are used as-is. Callers that relied on `stream.io` returning an `IO::Stream::Buffered` should wrap the IO themselves before passing it in.
6
+ - Simplify `Stream#read` to delegate directly to the underlying input, since the HTTP/2 framer always requests exact byte counts (header size, then payload length).
7
+
3
8
  ## v0.3.0
4
9
 
5
10
  - Change `Protocol::HTTY::Stream` to take explicit input and output endpoints using `Stream.new(input, output)` and `Stream.open(input, output, **options)`.
@@ -4,7 +4,6 @@
4
4
  # Copyright, 2026, by Samuel Williams.
5
5
 
6
6
  require "stringio"
7
- require "tempfile"
8
7
  require "protocol/http2/framer"
9
8
  require "protocol/htty"
10
9
 
@@ -49,7 +48,7 @@ describe Protocol::HTTY::Stream do
49
48
  end
50
49
 
51
50
  it "exposes the underlying output stream" do
52
- expect(stream.io).to be(:is_a?, ::IO::Stream::Buffered)
51
+ expect(stream.io).to be(:equal?, writer)
53
52
  end
54
53
 
55
54
  it "flushes through the underlying stream" do
@@ -86,16 +85,6 @@ describe Protocol::HTTY::Stream do
86
85
  expect(stream).to be(:readable?)
87
86
  end
88
87
 
89
- it "reads HTTP/2 frame headers and payloads without reading ahead" do
90
- header = [0, 5, 0, 0, 1].pack("CnCCN")
91
- input = StringIO.new("#{header}helloextra")
92
- reader = subject.open(input, StringIO.new)
93
-
94
- expect(reader.read(9)).to be == header
95
- expect(reader.read(16)).to be == "hello"
96
- expect(reader.read(5)).to be == "extra"
97
- end
98
-
99
88
  it "rejects writes after the local side is closed" do
100
89
  stream.close
101
90
 
@@ -103,24 +92,4 @@ describe Protocol::HTTY::Stream do
103
92
  stream.write("hello")
104
93
  end.to raise_exception(IOError)
105
94
  end
106
-
107
- it "wraps raw IO handles using IO::Stream" do
108
- Tempfile.create("protocol-htty") do |file|
109
- io_stream = subject.open(file, file).io
110
-
111
- expect(io_stream).to be(:is_a?, ::IO::Stream::Buffered)
112
- io_stream.close
113
- end
114
- end
115
-
116
- it "does not close wrapped raw IO handles when closed" do
117
- Tempfile.create("protocol-htty") do |file|
118
- wrapped_stream = subject.open(file, file)
119
-
120
- wrapped_stream.close
121
-
122
- expect(file).not.to be(:closed?)
123
- file.close
124
- end
125
- end
126
95
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-htty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: io-stream
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: 0.13.0
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: 0.13.0
69
55
  executables: []
70
56
  extensions: []
71
57
  extra_rdoc_files: []
metadata.gz.sig CHANGED
Binary file