| name | design_patterns-genre_bitfield |
| description | Use when working with object genres, adding genre filters to queries, parsing sigils like :z :t :e :k :b, or modifying genre-based dispatch. Also applies when encountering Genre byte type, genre bitwise operations, MakeGenre, or optimizedQueries maps.
|
| triggers | ["genre","Genre byte","sigil",":z :t :e :k :b","MakeGenre","genre bitfield","object genre","genre filter"] |
Genre Bitfield System
Overview
Dodder categorizes objects into genres (Zettel, Tag, Type, Repo, InventoryList,
Blob, Config) using a byte-sized enum. For set operations — "show all zettels
and tags" — a separate ids.Genre bitfield type packs multiple genres into a
single byte using power-of-two bit flags. Queries store genre-optimized
sub-queries keyed by genre for efficient dispatch.
Two Genre Types
genres.Genre (Enum)
Sequential enum values for identifying a single genre:
type Genre byte
const (
Unknown = Genre(iota)
Blob
Type
Tag
Zettel
Config
InventoryList
Repo
)
ids.Genre (Bitfield)
Bitfield for efficient set membership testing:
const (
blob = byte(1 << iota)
tipe
tag
zettel
config
inventory_list
repo
)
Conversion between enum and bitfield uses GetGenreBitInt().
Bitfield Operations
genre := ids.MakeGenre(genres.Zettel, genres.Tag)
genre.Add(genres.Type)
genre.Del(genres.Repo)
genre.Contains(genres.Zettel)
genre.ContainsOneOf(genres.Zettel)
slice := genre.Slice()
Sigil-to-Genre Mapping
Users specify genres in queries via sigil characters:
| Sigil | Genre | Aliases |
|---|
:z | Zettel | zettel |
:t | Type | type, typ |
:e | Tag | tag, etikett |
:r | Repo | repo, kasten |
:b | Blob | blob, akte |
Combined: :z,t = Zettel + Type bitfield.
Genre in ObjectId Parsing
echo/ids/main.go determines genre from syntax:
| Syntax | Genre | Example |
|---|
prefix/suffix | Zettel | one/uno |
plain-name or -name | Tag | project, -blocked |
!name | Type | !md |
/name | Repo | /my-repo |
@digest or purpose@digest | Blob | @abc123 |
sec.asec | InventoryList | 1234.5678 |
Query Optimization
Queries maintain per-genre sub-queries for fast dispatch:
for _, g := range genres {
existing, ok := query.optimizedQueries[g]
if !ok {
existing = buildState.makeQuery()
existing.Genre = ids.MakeGenre(g)
}
query.optimizedQueries[g] = existing
}
When matching, the query checks only the genre-specific sub-query:
g := genres.Must(sk.GetGenre())
q, ok := qg.optimizedQueries[g]
if !ok || !q.ContainsExternalSku(el) {
return false
}
Common Mistakes
| Mistake | Correct Approach |
|---|
| Using enum values for bitwise ops | Use GetGenreBitInt() to convert enum to bit flag |
Comparing ids.Genre with == for set membership | Use Contains() or ContainsOneOf() |
| Hardcoding genre detection instead of parsing | Use ValidateSeqAndGetGenre from echo/ids/ |