class
BakedFileSystem::BakedFile
- BakedFileSystem::BakedFile
- IO
- Reference
- Object
Overview
BakedFile represents a virtual file in a BakedFileSystem.
BakedFile is a read-only IO wrapper around files embedded at compile-time.
Write operations will raise ReadOnlyError since embedded files cannot be
modified at runtime.
Architecture
Files are stored compressed in the binary's read-only data section as byte slices. On first access, BakedFile creates:
- Memory IO: Wraps the compressed byte slice
- Gzip Reader: Wraps the memory IO for transparent decompression
- Wrapped IO: Either the memory IO (for .gz files) or gzip reader
This lazy-loading approach minimizes memory usage:
- Compressed data stays in read-only binary section
- Decompression happens on-demand during read
- No heap allocation unless content is explicitly stored
Streaming Behavior
BakedFile is a forward-only stream by default:
- Read operations consume the stream
- Call
#rewindto return to the beginning - Each
#rewindrecreates the decompression reader (see#rewindfor details)
Thread Safety
Each call to get() or get?() returns a new BakedFile instance with
independent state, making concurrent access safe.
Usage
file = MyFileSystem.get("hello-world.txt")
file.path # => "hello-world.txt"
file.size # => 12
file.gets_to_end # => "Hello World\n"
file.compressed? # => false
Defined in:
baked_file_system.crConstructors
Instance Method Summary
-
#close : Nil
Closes the file and releases resources.
-
#closed? : Bool
Returns true if the file has been closed.
-
#compressed? : Bool
Returns whether this file is compressed.
-
#compressed_size
Returns the compressed size of this virtual file.
-
#finalize
Ensures resources are freed when the object is garbage collected.
-
#path : String
Returns the path in the virtual file system.
-
#read(slice : Bytes)
Reads at most slice.size bytes from this
IOinto slice. -
#read
Return the data for this file as a String.
-
#rewind
Rewinds the file to the beginning for re-reading.
-
#size : Int32
Returns the size of this virtual file.
-
#to_encoded(compressed = true)
Return the data for this file as a URL-safe Base64-encoded String.
-
#to_slice(compressed)
Return the file's data as a Slice(UInt8)
-
#to_slice : Bytes
Returns a
Bytesholding the (compressed) content of this virtual file. -
#write(slice : Bytes) : Nil
Writes the contents of slice into this
IO. -
#write_to_io(io, compressed = true)
Write the file's data to the given IO, minimizing any memory copies or unnecessary conversions.
Constructor Detail
Instance Method Detail
Closes the file and releases resources. Can be called multiple times safely. After closing, read operations will raise IO::Error.
Returns whether this file is compressed. If not, it is decompressed on read.
Returns the compressed size of this virtual file.
See #size for the real size of the (uncompressed) file.
Reads at most slice.size bytes from this IO into slice.
Returns the number of bytes read, which is 0 if and only if there is no
more data to read (so checking for 0 is the way to detect end of file).
io = IO::Memory.new "hello"
slice = Bytes.new(4)
io.read(slice) # => 4
slice # => Bytes[104, 101, 108, 108]
io.read(slice) # => 1
slice # => Bytes[111, 101, 108, 108]
io.read(slice) # => 0
Return the data for this file as a String.
DEPRECATED BakedFile can be used as an IO directly. Use gets_to_end instead
Rewinds the file to the beginning for re-reading.
Implementation Note
This method recreates the gzip decompression reader instead of rewinding it
because Compress::Gzip::Reader is a forward-only stream that doesn't support
seeking backward. This is intentional and necessary for correct behavior.
Why Recreation is Required
Compress::Gzip::Readermaintains internal state during decompression- This state cannot be reset to return to the beginning
- Creating a new reader over the rewound underlying stream is the only way to re-read
Performance Implications
- Creating a new reader is fast (no decompression happens yet)
- Decompression happens on-demand during read operations
- Memory usage is minimal (same underlying byte slice is reused)
- This is the standard approach for streaming decompression
Alternatives Considered
Cache decompressed content:
- Pro: True rewind without recreation
- Con: Significant memory overhead (defeats purpose of streaming)
- Con: Not suitable for large files
- Decision: Rejected
Add seeking to Gzip::Reader:
- Pro: More intuitive API
- Con: Requires changes to Crystal standard library
- Con: Decompression algorithms are inherently forward-only
- Decision: Not feasible
Return the data for this file as a URL-safe Base64-encoded String.
DEPRECATED BakedFile can be used as an IO directly.
Return the file's data as a Slice(UInt8)
DEPRECATED BakedFile can be used as an IO directly.
Returns a Bytes holding the (compressed) content of this virtual file.
This data needs to be extracted using a Compress::Gzip::Reader unless #compressed? is true.
Writes the contents of slice into this IO.
io = IO::Memory.new
slice = Bytes.new(4) { |i| ('a'.ord + i).to_u8 }
io.write(slice)
io.to_s # => "abcd"