diff --git a/set/item.go b/set/item.go index d912cf8..d50f6c2 100644 --- a/set/item.go +++ b/set/item.go @@ -29,6 +29,20 @@ func Keyize(key string) Item { return &item{key, struct{}{}} } +type renamedItem struct { + Item + key string +} + +func (item *renamedItem) Key() string { + return item.key +} + +// Rename item to a new key, same underlying value. +func Rename(item Item, key string) Item { + return &renamedItem{Item: item, key: key} +} + type StringItem string func (item StringItem) Key() string { diff --git a/set/set.go b/set/set.go index 1b489ad..42ed515 100644 --- a/set/set.go +++ b/set/set.go @@ -55,6 +55,7 @@ func (s *Set) In(key string) bool { s.RUnlock() if ok && item.Value() == nil { s.cleanup(key) + ok = false } return ok } @@ -66,12 +67,13 @@ func (s *Set) Get(key string) (Item, error) { item, ok := s.lookup[key] s.RUnlock() + if ok && item.Value() == nil { + s.cleanup(key) + ok = false + } if !ok { return nil, ErrMissing } - if item.Value() == nil { - s.cleanup(key) - } return item, nil } @@ -87,10 +89,7 @@ func (s *Set) cleanup(key string) { } // Add item to this set if it does not exist already. -func (s *Set) Add(item Item) error { - if item.Value() == nil { - return ErrNil - } +func (s *Set) AddNew(item Item) error { key := s.normalize(item.Key()) s.Lock() @@ -101,7 +100,26 @@ func (s *Set) Add(item Item) error { return ErrCollision } - s.lookup[key] = item + if item.Value() == nil { + delete(s.lookup, key) + } else { + s.lookup[key] = item + } + return nil +} + +// Add to set, replacing if item already exists. +func (s *Set) Add(item Item) error { + key := s.normalize(item.Key()) + + s.Lock() + defer s.Unlock() + + if item.Value() == nil { + delete(s.lookup, key) + } else { + s.lookup[key] = item + } return nil } @@ -123,9 +141,6 @@ func (s *Set) Remove(key string) error { // Replace oldKey with a new item, which might be a new key. // Can be used to rename items. func (s *Set) Replace(oldKey string, item Item) error { - if item.Value() == nil { - return ErrNil - } newKey := s.normalize(item.Key()) oldKey = s.normalize(oldKey) @@ -140,15 +155,15 @@ func (s *Set) Replace(oldKey string, item Item) error { } // Remove oldKey - _, found = s.lookup[oldKey] - if !found { - return ErrMissing - } delete(s.lookup, oldKey) } - // Add new item - s.lookup[newKey] = item + if item.Value() == nil { + delete(s.lookup, newKey) + } else { + // Add new item + s.lookup[newKey] = item + } return nil } diff --git a/set/set_test.go b/set/set_test.go index f75192d..58c0613 100644 --- a/set/set_test.go +++ b/set/set_test.go @@ -21,10 +21,16 @@ func TestSetExpiring(t *testing.T) { t.Error("not len 1 after set") } - item := &ExpiringItem{nil, time.Now().Add(-time.Nanosecond * 1)} + item := &ExpiringItem{StringItem("expired"), time.Now().Add(-time.Nanosecond * 1)} if !item.Expired() { t.Errorf("ExpiringItem a nanosec ago is not expiring") } + if err := s.Add(item); err != nil { + t.Fatalf("failed to add item: %s", err) + } + if s.In("expired") { + t.Errorf("expired item is present") + } item = &ExpiringItem{nil, time.Now().Add(time.Minute * 5)} if item.Expired() {