package index import ( "sort" "sync" "time" ) type Entry struct { Hash string `json:"hash"` Bytes int64 `json:"bytes"` StoredAt string `json:"stored_at"` Private bool `json:"private"` CreatorTZ string `json:"creator_tz,omitempty"` } type rec struct { Hash string Bytes int64 StoredAt time.Time Private bool CreatorTZ string } type Index struct { mu sync.RWMutex hash map[string]rec } func New() *Index { return &Index{hash: make(map[string]rec)} } func (ix *Index) Put(e Entry) error { ix.mu.Lock() defer ix.mu.Unlock() t := parseWhen(e.StoredAt) if t.IsZero() { t = time.Now().UTC() } ix.hash[e.Hash] = rec{ Hash: e.Hash, Bytes: e.Bytes, StoredAt: t, Private: e.Private, CreatorTZ: e.CreatorTZ, } return nil } func (ix *Index) Delete(hash string) error { ix.mu.Lock() defer ix.mu.Unlock() delete(ix.hash, hash) return nil } func (ix *Index) List() ([]Entry, error) { ix.mu.RLock() defer ix.mu.RUnlock() tmp := make([]rec, 0, len(ix.hash)) for _, r := range ix.hash { tmp = append(tmp, r) } sort.Slice(tmp, func(i, j int) bool { return tmp[i].StoredAt.After(tmp[j].StoredAt) }) out := make([]Entry, len(tmp)) for i, r := range tmp { out[i] = Entry{ Hash: r.Hash, Bytes: r.Bytes, StoredAt: r.StoredAt.UTC().Format(time.RFC3339Nano), Private: r.Private, CreatorTZ: r.CreatorTZ, } } return out, nil } func parseWhen(s string) time.Time { if s == "" { return time.Time{} } if t, err := time.Parse(time.RFC3339Nano, s); err == nil { return t } if t, err := time.Parse(time.RFC3339, s); err == nil { return t } return time.Time{} }