Skip to content

Commit

Permalink
buffer wraps string (#65)
Browse files Browse the repository at this point in the history
* buffer wraps string

* remove buffer creation in specs

* Set rubocop version
  • Loading branch information
georgeu2000 authored and igrigorik committed Oct 13, 2016
1 parent e0160af commit bf4b930
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ group :test do
gem 'pry-byebug', platform: :mri
gem 'rspec', '~> 3.4.0'
gem 'rspec-autotest'
gem 'rubocop', '~> 0.43'
gem 'rubocop', '0.43.0'
end

gemspec
56 changes: 42 additions & 14 deletions lib/http/2/buffer.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,61 @@
require 'forwardable'

module HTTP2
# Simple binary buffer backed by string.
#
# TODO: Refactor, it would be better if Buffer were not a String subclass,
# but rather wrap a string and only expose the mutating API needed so that
# the possible surface for things to go wrong stays controllable.
# - https://github.com/igrigorik/http-2/pull/46
# Binary buffer wraps String.
#
class Buffer < String
class Buffer
extend Forwardable

def_delegators :@buffer, :ord, :encoding, :setbyte, :unpack,
:size, :each_byte, :to_str, :length, :inspect,
:[], :[]=, :empty?, :bytesize, :include?

UINT32 = 'N'.freeze
private_constant :UINT32

# Forces binary encoding on the string
def initialize(*)
super.force_encoding(Encoding::BINARY)
def initialize(str = '')
str = str.dup if str.frozen?
@buffer = str.force_encoding(Encoding::BINARY)
end

# Emulate StringIO#read: slice first n bytes from the buffer.
#
# @param n [Integer] number of bytes to slice from the buffer
def read(n)
Buffer.new(slice!(0, n))
Buffer.new(@buffer.slice!(0, n))
end

# Alias getbyte to readbyte
alias readbyte getbyte

# Emulate StringIO#getbyte: slice first byte from buffer.
def getbyte
read(1).ord
end

def slice!(*args)
Buffer.new(@buffer.slice!(*args))
end

def slice(*args)
Buffer.new(@buffer.slice(*args))
end

def force_encoding(*args)
@buffer = @buffer.force_encoding(*args)
end

def ==(other)
@buffer == other
end

def +(other)
@buffer += other
end

# Emulate String#getbyte: return nth byte from buffer.
def readbyte(n)
@buffer[n].ord
end

# Slice unsigned 32-bit integer from buffer.
# @return [Integer]
def read_uint32
Expand All @@ -41,7 +67,9 @@ def read_uint32
[:<<, :prepend].each do |mutating_method|
define_method(mutating_method) do |string|
string = string.dup if string.frozen?
super(string.force_encoding(Encoding::BINARY))
@buffer.send mutating_method, string.force_encoding(Encoding::BINARY)

self
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/http/2/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ def connection_settings(frame)
#
# @param frame [Hash]
def decode_headers(frame)
if frame[:payload].is_a? String
if frame[:payload].is_a? Buffer
frame[:payload] = @decompressor.decode(frame[:payload])
end

Expand All @@ -588,7 +588,7 @@ def decode_headers(frame)
# @return [Array of Frame]
def encode_headers(frame)
payload = frame[:payload]
payload = @compressor.encode(payload) unless payload.is_a? String
payload = @compressor.encode(payload) unless payload.is_a? Buffer

frames = []

Expand Down
6 changes: 3 additions & 3 deletions spec/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@
it 'should raise error on PUSH_PROMISE against non-idle stream' do
expect do
s = @client.new_stream
s.send HEADERS
s.send HEADERS.dup

@client << set_stream_id(f.generate(PUSH_PROMISE), s.id)
@client << set_stream_id(f.generate(PUSH_PROMISE), s.id)
@client << set_stream_id(f.generate(PUSH_PROMISE.dup), s.id)
@client << set_stream_id(f.generate(PUSH_PROMISE.dup), s.id)
end.to raise_error(ProtocolError)
end

Expand Down
1 change: 0 additions & 1 deletion spec/connection_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@
]
headers = []
@conn.on(:frame) do |bytes|
# bytes[3]: frame's type field
headers << f.parse(bytes) if [1, 5, 9].include?(bytes[3].ord)
end

Expand Down

0 comments on commit bf4b930

Please sign in to comment.