embedding/embedding.go: - Remove EmbedBatch() (never called in production, test updated to use Embed) - Remove padID field (written but never read) embedding/index.go: - Remove Index.mu mutex (Index is immutable after construction) skills/skills.go: - Remove Index.All() (never called) - Remove Index.Reload() (never called) virtfs/decl.go: - Remove RemoveNode() NodeOption (never used) - Remove RenameNode() NodeOption (never used) - Remove Alias() NodeOption (aliases set directly on struct) virtfs/tree.go: - Remove Tree.Data field (never used) - Remove Tree.Mount() (never called in production) - Remove Tree.Child() (never called in production) - Remove Tree.Children() (never called in production) - Replace indexOf() with strings.IndexByte Tests updated to directly manipulate internal children map where needed. |
||
|---|---|---|
| .. | ||
| LICENSE.md | ||
| README.md | ||
| builder.go | ||
| decl.go | ||
| decl_test.go | ||
| file.go | ||
| go.mod | ||
| help.go | ||
| tree.go | ||
| tree_test.go | ||
README.md
virtfs
A Go library for declaring synthetic filesystems. Define your namespace structure statically, populate it dynamically at runtime with closures.
Produces a *Tree usable with any filesystem protocol (9P, FUSE, etc.) or as an in-memory filesystem for testing.
Design
Handlers are plain closures that capture their state at binding time. There is no context type parameter — each handler already knows its target via closure capture.
Dynamic subtrees use Each: a bindings function returns []Binding, where each binding carries pre-bound Children (fully-wired subtrees with their own closures).
Quick Start
package main
import (
"fmt"
"ollie/virtfs"
)
type User struct {
ID string
Name string
}
var users = []*User{
{ID: "1", Name: "alice"},
{ID: "2", Name: "bob"},
}
func main() {
spec := virtfs.DirNode("/",
virtfs.FileNode("version", 0444,
virtfs.Doc("API version"),
virtfs.Read(func() ([]byte, error) {
return []byte("1.0\n"), nil
}),
),
virtfs.Each("{user}", func() ([]virtfs.Binding, error) {
var out []virtfs.Binding
for _, u := range users {
user := u // capture
out = append(out, virtfs.Binding{
Name: user.Name,
Aliases: []string{user.ID},
Children: []virtfs.FsNodeDecl{
virtfs.FileNode("id", 0444,
virtfs.Read(func() ([]byte, error) {
return []byte(user.ID + "\n"), nil
}),
),
virtfs.FileNode("name", 0444,
virtfs.Read(func() ([]byte, error) {
return []byte(user.Name + "\n"), nil
}),
),
},
})
}
return out, nil
}),
)
tree := virtfs.BuildTree(spec)
entries, _ := tree.List()
for _, e := range entries {
fmt.Println(e.Name())
}
f, _ := tree.Open("alice/name")
data, _ := f.Read()
fmt.Printf("alice/name: %s", data)
}
API
Constructors
| Function | Description |
|---|---|
DirNode(name, children/options...) |
Static directory |
FileNode(name, mode, options...) |
File with handlers |
Each(name, bindingsFn, options...) |
Dynamic directory — children come from bindings |
Options (NodeOption)
| Option | Signature | Description |
|---|---|---|
Read(fn) |
func() ([]byte, error) |
Non-blocking read |
Write(fn) |
func([]byte) error |
Write handler |
Stream(fn) |
func(context.Context, string) ([]byte, string, error) |
Blocking streaming read |
BlockOnce(fn) |
func(context.Context, string) ([]byte, string, error) |
Blocking read, returns once |
Request(fn) |
func([]byte) ([]byte, error) |
Write-then-read (rdwr) |
Doc(desc) |
string |
Human-readable description |
UID(uid) |
string |
Set owner |
GID(gid) |
string |
Set group |
StatOverride(fn) |
func() os.FileInfo |
Custom stat |
RemoveNode(fn) |
func() error |
Removal handler |
Binding
Returned by the Each bindings function. Each binding represents one dynamic child.
virtfs.Binding{
Name: "alice",
Aliases: []string{"user-id-123"},
Children: []virtfs.FsNodeDecl{ ... }, // pre-bound subtree
Remove: func() { ... }, // optional
Rename: func(newName string) error { ... }, // optional
}
Children are fully-wired — their handlers are closures that already captured the specific instance (no applier/context needed).
Tree Operations
tree := virtfs.BuildTree(spec)
tree.List() // list root entries
tree.Stat(name) // stat a path
tree.Open(name) // open file for read/write
tree.Create(name) // create file
tree.Delete(name) // remove file
tree.Rename(old, new) // rename file
tree.Readdir(path) // list subdirectory
Help Generation
help := virtfs.GenerateHelp(spec)
// Produces formatted docs from Doc() annotations
License
GPLv3