DASL.CAR.DRISL (dasl v0.1.0)

View Source

A DRISL-aware CAR variant.

Wraps DASL.CAR with transparent DRISL encoding and decoding of block data. Blocks are stored as decoded Elixir terms keyed by their DASL.CID. CIDs are computed over the DRISL-encoded form of each term using the :drisl codec.

For a lower-level CAR that stores raw binaries, see DASL.CAR.

Summary

Functions

DRISL-encodes term, computes its CID using the :drisl codec, adds the CID to the blocks (storing the original term, not the encoded binary), 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.DRISL struct.

Encodes a DASL.CAR.DRISL 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, with block data DRISL-decoded into Elixir terms.

Types

t()

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

Functions

add_block(car, term)

@spec add_block(t(), any()) :: {:ok, {t(), DASL.CID.t()}} | {:error, atom()}

DRISL-encodes term, computes its CID using the :drisl codec, adds the CID to the blocks (storing the original term, not the encoded binary), and returns the updated struct alongside the computed CID.

Returns {:error, reason} if DRISL encoding fails.

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.DRISL struct.

Each block's raw binary is decoded as a DRISL term after CID verification.

Options

  • :verify — boolean, default true. Verifies each block's raw data against its CID before DRISL decoding. Returns {:error, :block, :cid_mismatch} on failure.

encode(drisl, opts \\ [])

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

Each block's term value is DRISL-encoded before writing.

Options

  • :verify — boolean, default true. Verifies each DRISL-encoded block binary against its CID before writing. 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.

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, with block data DRISL-decoded into Elixir terms.

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, term} — emitted per block; term is the DRISL-decoded Elixir value

Raises on parse errors (invalid header, truncated stream, CID mismatch, or DRISL decoding failure).

Options

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

Examples

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