In-memory VFS.Mountable backend.
Files live in a tree map (%{path => binary}); explicitly-created
empty directories live in a dirs MapSet; mtimes tracks
modification times.
Directories are recognized in two ways:
- Explicit — created via
mkdir/3, recorded indirs. - Implicit — at least one file or explicit dir under them.
Both kinds satisfy stat/2 and readdir/2. Removing the last child of an
implicit directory makes it disappear; an explicit directory persists
until removed via rm/3 with recursive: true.
Construction
iex> mem = VFS.Memory.new(%{"/foo/bar" => "hello"})
iex> {:ok, "hello", _mem} = VFS.read_file(mem, "/foo/bar")
iex> :ok
:okUse the helpers in VFS (e.g. VFS.read_file/2, VFS.walk/3) for
telemetry-instrumented access. Direct protocol calls bypass instrumentation.
Summary
Functions
Build a fresh in-memory FS, optionally seeded with files.
Types
@type t() :: %VFS.Memory{ dirs: MapSet.t(VFS.Path.t()), mtimes: %{required(VFS.Path.t()) => DateTime.t()}, tree: %{required(VFS.Path.t()) => binary()} }
Functions
Build a fresh in-memory FS, optionally seeded with files.
Raises ArgumentError if the seed is malformed:
- Every key must be a path binary and every value a binary —
anything else fails here, at construction, instead of deferring
the crash to the first
stat/read. - The literal
"/"cannot be a file (root is always a directory). - No two paths can be in a strict path-segment-prefix relationship
(e.g.
%{"/a" => "...", "/a/b" => "..."}is rejected —/acannot simultaneously be a regular file and a directory).
Validation runs at construction so the resulting backend is internally
consistent: stat, readdir, and read_file agree on every path.
Without validation, externally-provided seeds (config files, DB dumps,
LLM-generated inputs) could put the FS into a state that no sequence
of writes could ever produce.
Examples
iex> mem = VFS.Memory.new()
iex> mem.tree
%{}
iex> mem = VFS.Memory.new(%{"/a.txt" => "hi"})
iex> Map.fetch!(mem.tree, "/a.txt")
"hi"
iex> VFS.Memory.new(%{"/a" => "f", "/a/b" => "c"})
** (ArgumentError) VFS.Memory seed has conflicting paths: "/a" is a file but "/a/b" places a child under it. A path cannot be both a file and a directory.