Skip to content

Commit

Permalink
Buffered version of Frame#from_io
Browse files Browse the repository at this point in the history
That doesn't require a block. Only in the case where Body frames are
expected might the original version of `from_io` be more efficent, as
the body can be streamed directly to the destination without buffering.
  • Loading branch information
carlhoerberg committed Dec 11, 2023
1 parent 515fd9e commit eddbea6
Showing 1 changed file with 33 additions and 0 deletions.
33 changes: 33 additions & 0 deletions src/amq/protocol/frames.cr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ module AMQ
io.write_byte 206_u8
end

# Parse a frame from an IO
#
# Requires a block, because the Body is not buffered and can instead be streamed efficiently.
def self.from_io(io, format = IO::ByteFormat::NetworkEndian, & : Frame -> _)
buf = uninitialized UInt8[7]
slice = buf.to_slice
Expand Down Expand Up @@ -52,6 +55,36 @@ module AMQ
end
end

# Parse a frame from an IO
#
# Note that this method buffers `BytesBody` frames,
# only use this method if you don't require the best performance.
def self.from_io(io, format = IO::ByteFormat::NetworkEndian)
buf = uninitialized UInt8[7]
slice = buf.to_slice
io.read_fully(slice)
type = slice[0]
channel = format.decode(UInt16, slice[1, 2])
size = format.decode(UInt32, slice[3, 4])
frame =
case type
when Method::TYPE then Method.from_io(channel, size, io, format)
when Header::TYPE then Header.from_io(channel, size, io, format)
when Body::TYPE
bytes = Bytes.new(size)
io.read_fully bytes
BytesBody.new(channel, size, bytes)
when Heartbeat::TYPE then Heartbeat.new
else
raise Error::FrameDecode.new("Invalid frame type #{type}")
end

if (frame_end = io.read_byte) && frame_end != 206_u8
raise Error::InvalidFrameEnd.new("#{frame.class}-end was #{frame_end}, expected 206")
end
frame
end

def to_slice(format = IO::ByteFormat::SystemEndian) : Bytes
io = IO::Memory.new(bytesize)
to_io(io, format)
Expand Down

0 comments on commit eddbea6

Please sign in to comment.