Add immutability option

This commit is contained in:
Vishal Kuo 2016-11-12 11:07:48 -05:00
parent ac919cfb98
commit f7fe0fd5da
3 changed files with 65 additions and 2 deletions

View file

@ -19,5 +19,5 @@ biMap.Size() // == 0
biMap2 := bimap.NewBiMap()
biMap2.Insert("key", 1) // Notice different types
val, ok := biMap2.Get("key") // Returns 1
val, ok = biMap2.InverseGet(1) //Return "key"
val, ok = biMap2.InverseGet(1) // Returns "key"
```

View file

@ -4,16 +4,23 @@ import "sync"
type biMap struct {
s sync.RWMutex
immutable bool
forward map[interface{}]interface{}
inverse map[interface{}]interface{}
}
func NewBiMap() *biMap {
return &biMap{forward: make(map[interface{}]interface{}), inverse: make(map[interface{}]interface{})}
return &biMap{forward: make(map[interface{}]interface{}), inverse: make(map[interface{}]interface{}), immutable:false}
}
func (b *biMap) Insert(k interface{}, v interface{}) {
b.s.RLock()
if b.immutable {
panic("Cannot modify immutable map")
}
b.s.RUnlock()
b.s.Lock()
defer b.s.Unlock()
b.forward[k] = v
@ -56,6 +63,12 @@ func (b *biMap) InverseGet(v interface{}) (interface{}, bool) {
}
func (b *biMap) Delete(k interface{}) {
b.s.RLock()
if b.immutable {
panic("Cannot modify immutable map")
}
b.s.RUnlock()
if !b.Exists(k) {
return
}
@ -67,6 +80,12 @@ func (b *biMap) Delete(k interface{}) {
}
func (b *biMap) InverseDelete(v interface{}) {
b.s.RLock()
if b.immutable {
panic("Cannot modify immutable map")
}
b.s.RUnlock()
if !b.InverseExists(v) {
return
}
@ -83,4 +102,10 @@ func (b*biMap) Size() int{
b.s.RLock()
defer b.s.RUnlock()
return len(b.forward)
}
func (b *biMap) SetImmutable() {
b.s.Lock()
defer b.s.Unlock()
b.immutable = true
}

View file

@ -154,6 +154,44 @@ func TestBiMap_WithVaryingType(t *testing.T) {
}
func TestBiMap_SetImmutable(t *testing.T) {
actual := NewBiMap()
dummyKey := "Dummy key"
dummyVal := 3
actual.Insert(dummyKey, dummyVal)
actual.SetImmutable()
assert.Panics(t, func() {
actual.Delete(dummyKey)
}, "It should panic on a mutation operation")
val, _ := actual.Get(dummyKey)
assert.Equal(t, dummyVal, val, "It should still have the value")
assert.Panics(t, func() {
actual.InverseDelete(dummyVal)
}, "It should panic on a mutation operation")
key, _ := actual.InverseGet(dummyVal)
assert.Equal(t, dummyKey, key, "It should still have the key")
size := actual.Size()
assert.Equal(t, 1, size, "Size should be one")
assert.Panics(t, func() {
actual.Insert("New", 1)
}, "It should panic on a mutation operation")
size = actual.Size()
assert.Equal(t, 1, size, "Size should be one")
}