Packages
msf_format
0.1.0
Provides functions for reading Multi-Stream Format (MSF) files, which are the backing format for file types such as PDB.
Current section
Files
Jump to
Current section
Files
lib/msf.ex
defmodule MSFFormat do
@moduledoc """
Describes the MSF file format and functions for deserializing it from binary or file inputs.
"""
defstruct [:device, :superblock, :directory]
@doc """
Read an MSF file from the given device. Does not read the entire file, only the data required to
read specific blocks.
"""
def read(device) do
with {:ok, superblock} <- MSFFormat.Superblock.read(device) do
MSFFormat.StreamDirectory.read(%MSFFormat{device: device, superblock: superblock})
end
end
@doc """
Attempt to read the block at the given index from the given MSF file. If a `size` parameter is given, the
specified number of bytes will be read, otherwise the entire contents of the block will be read.
"""
def read_block(%MSFFormat{superblock: %MSFFormat.Superblock{block_size: block_size}} = msf, index),
do: read_block(msf, index, block_size)
def read_block(%MSFFormat{superblock: %MSFFormat.Superblock{block_size: block_size}, device: device}, index, size) do
with {:ok, _position} <- :file.position(device, index * block_size),
data when is_binary(data) <- IO.binread(device, size) do
{:ok, data}
end
end
@doc """
Open a stream for reading. Call MSFFormat.Stream.read to read blocks from the stream in sequence.
"""
def open_stream(%MSFFormat{directory: directory} = msf, stream_id) do
case MSFFormat.StreamDirectory.length(directory, stream_id) do
{:error, :bad_stream_id} -> {:error, :bad_stream_id}
{:ok, _length} -> {:ok, MSFFormat.Stream.new(stream_id, msf)}
end
end
@doc """
Close the underlying IO device for the given MSF file.
"""
def close(%MSFFormat{device: device}),
do: File.close(device)
@doc """
Open and read the MSF file at the given path.
"""
def open(path) when is_binary(path) do
with {:ok, device} <- File.open(path, [:binary, :read]) do
read(device)
end
end
end