From c19a5117492f2ca3d15f04c4fc74a004837efa43 Mon Sep 17 00:00:00 2001 From: Kuba Suder Date: Sun, 18 Jan 2026 18:36:01 +0200 Subject: [PATCH] decode CAR sections lazily The CAR includes several "sections", but unless someone wants to process the MST data, you only really need one of those sections that includes the record data. This section is usually one of the first few ones. If we parse them only on demand and only get to the one we need, skipping the rest, we can often save half or more of the work. --- lib/skyfall/car_archive.rb | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/skyfall/car_archive.rb b/lib/skyfall/car_archive.rb index d05fd8a..7c56952 100644 --- a/lib/skyfall/car_archive.rb +++ b/lib/skyfall/car_archive.rb @@ -32,15 +32,25 @@ module Skyfall def initialize(data) @sections = [] + @buffer = StringIO.new(data) - buffer = StringIO.new(data) - read_header(buffer) - read_section(buffer) until buffer.eof? + read_header(@buffer) end def section_with_cid(cid) - section = @sections.detect { |s| s.cid == cid } - section && section.body + if section = @sections.detect { |s| s.cid == cid } + return section.body + end + + if @buffer + while !@buffer.eof? + section = read_section(@buffer) + return section.body if section.cid == cid + end + end + + @buffer = nil + nil end def self.convert_data(object) @@ -118,7 +128,10 @@ module Skyfall cid = CID.new(prefix + cid_data) body_data = sbuffer.read - @sections << CarSection.new(cid, body_data) + new_section = CarSection.new(cid, body_data) + + @sections << new_section + new_section end end end -- 2.51.2