From eb693cad8b866f6b9436f6ea06921912e7bbcb0a Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Wed, 20 May 2026 09:13:17 +0200 Subject: [PATCH] Use IO#seek when possible Saves on reading a potentially large string. Also noop of the offset is `0` (which it very often is). --- lib/marcel/magic.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/marcel/magic.rb b/lib/marcel/magic.rb index c79eeab..9d4ea86 100644 --- a/lib/marcel/magic.rb +++ b/lib/marcel/magic.rb @@ -128,11 +128,11 @@ def self.magic_match_io(io, matches, buffer) if value.is_a?(Regexp) match_regex(io, offset, value, buffer) elsif Range === offset - io.read(offset.begin, buffer) + io_seek(io, offset.begin, buffer) x = io.read(offset.end - offset.begin + value.bytesize, buffer) x && x.include?(value) else - io.read(offset, buffer) + io_seek(io, offset, buffer) io.read(value.bytesize, buffer) == value end end @@ -151,6 +151,17 @@ def self.match_regex(io, offset, regexp, buffer) data.match?(regexp) end - private_class_method :magic_match, :magic_match_io, :match_regex + def self.io_seek(io, offset, buffer) + return if offset == 0 + + if io.respond_to?(:seek) + io.seek(offset, IO::SEEK_CUR) + else + # Some IOs don't support `seek`. e.g. Rack::RewindableInput + io.read(offset, buffer) + end + end + + private_class_method :magic_match, :magic_match_io, :match_regex, :io_seek end end