DASL.CAR (dasl v0.1.0)

View Source

Struct and entry points for DASL CAR files.

Blocks are stored as raw binaries keyed by their DASL.CID. For a higher-level variant that transparently encodes/decodes block data as DRISL, see DASL.CAR.DRISL.

Spec: https://dasl.ing/car.html

Summary

Functions

Computes the CID for data, adds it to the CAR's blocks, and returns the updated struct alongside the computed CID.

Adds a CID to the CAR's roots after verifying it exists in the blocks.

Decodes a CAR binary stream into a DASL.CAR struct.

Encodes a DASL.CAR struct into a CAR binary stream.

Removes a CID from the CAR's blocks.

Removes a CID from the CAR's roots. No-op if the CID is not a root.

Transforms a stream of binary chunks into a stream of decoded CAR items.

Types

t()

@type t() :: %DASL.CAR{
  blocks: %{required(DASL.CID.t()) => binary()},
  roots: [DASL.CID.t()],
  version: pos_integer()
}

Functions

add_block(car, data)

@spec add_block(t(), binary()) :: {t(), DASL.CID.t()}

Computes the CID for data, adds it to the CAR's blocks, and returns the updated struct alongside the computed CID.

The CID is computed using the :raw codec.

add_root(car, cid)

@spec add_root(t(), DASL.CID.t()) :: {:ok, t()} | {:error, :not_in_blocks}

Adds a CID to the CAR's roots after verifying it exists in the blocks.

Returns {:ok, updated_car} on success, {:ok, car} unchanged if the CID is already a root (no-op), or {:error, :not_in_blocks} if the CID is not present in the blocks.

decode(binary, opts \\ [])

Decodes a CAR binary stream into a DASL.CAR struct.

Options

  • :verify — boolean, default true. Verifies each block's raw data against its CID digest using DASL.CID.verify?/2. Returns {:error, :block, :cid_mismatch} on failure.

encode(car, opts \\ [])

Encodes a DASL.CAR struct into a CAR binary stream.

Options

  • :verify — boolean, default true. Verifies each block binary against its CID digest using DASL.CID.verify?/2. Returns {:error, :block, :cid_mismatch} on failure.

remove_block(car, cid)

@spec remove_block(t(), DASL.CID.t()) :: {:ok, t()} | {:error, :is_a_root}

Removes a CID from the CAR's blocks.

Returns {:ok, updated_car} on success (including when the CID is absent — no-op), or {:error, :is_a_root} if the CID is currently listed as a root. Call remove_root/2 first to remove it from roots before removing the block.

remove_root(car, cid)

@spec remove_root(t(), DASL.CID.t()) :: t()

Removes a CID from the CAR's roots. No-op if the CID is not a root.

stream_decode(chunk_stream, opts \\ [])

@spec stream_decode(
  Enumerable.t(),
  keyword()
) :: Enumerable.t()

Transforms a stream of binary chunks into a stream of decoded CAR items.

Each element of chunk_stream must be a binary of any size. Items are emitted as soon as a complete frame has been buffered:

  • {:header, version, roots} — emitted once when the header is parsed
  • {:block, cid, data} — emitted per block; data is the raw binary

Raises on parse errors (invalid header, truncated stream, CID mismatch).

Options

  • :verify — boolean, default true. Verifies each block against its CID.

Examples

File.stream!("large.car", [], 65_536)
|> DASL.CAR.stream_decode()
|> Enum.each(fn
  {:header, _version, roots} -> IO.inspect(roots)
  {:block, cid, _data}       -> IO.inspect(cid)
end)