package index import ( "errors" "sync" ) // Entry is the minimal metadata we expose to clients. type Entry struct { Hash string `json:"hash"` Bytes int64 `json:"bytes"` StoredAt string `json:"stored_at"` // RFC3339Nano Private bool `json:"private"` // true if client marked encrypted CreatorTZ string `json:"creator_tz,omitempty"` // optional IANA TZ from client } // Index is an in-memory map from hash -> Entry, safe for concurrent use. type Index struct { mu sync.RWMutex m map[string]Entry } func New() *Index { return &Index{m: make(map[string]Entry)} } func (ix *Index) Put(e Entry) error { if e.Hash == "" { return errors.New("empty hash") } ix.mu.Lock() ix.m[e.Hash] = e ix.mu.Unlock() return nil } func (ix *Index) Delete(hash string) error { if hash == "" { return errors.New("empty hash") } ix.mu.Lock() delete(ix.m, hash) ix.mu.Unlock() return nil } func (ix *Index) Get(hash string) (Entry, bool) { ix.mu.RLock() e, ok := ix.m[hash] ix.mu.RUnlock() return e, ok } // All returns an unsorted copy of all entries. func (ix *Index) All() []Entry { ix.mu.RLock() out := make([]Entry, 0, len(ix.m)) for _, v := range ix.m { out = append(out, v) } ix.mu.RUnlock() return out }