diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go
index 23c12090..c2ab0c0a 100644
--- a/internal/bridge/bridge_test.go
+++ b/internal/bridge/bridge_test.go
@@ -34,7 +34,6 @@ import (
"github.com/ProtonMail/proton-bridge/v2/internal/events"
"github.com/ProtonMail/proton-bridge/v2/internal/focus"
"github.com/ProtonMail/proton-bridge/v2/internal/locations"
- "github.com/ProtonMail/proton-bridge/v2/internal/safe"
"github.com/ProtonMail/proton-bridge/v2/internal/updater"
"github.com/ProtonMail/proton-bridge/v2/internal/user"
"github.com/ProtonMail/proton-bridge/v2/internal/useragent"
@@ -168,7 +167,10 @@ func TestBridge_UserAgent(t *testing.T) {
func TestBridge_Cookies(t *testing.T) {
withEnv(t, func(ctx context.Context, s *server.Server, netCtl *liteapi.NetCtl, locator bridge.Locator, vaultKey []byte) {
- sessionIDs := safe.NewValue([]string{})
+ var (
+ sessionIDs []string
+ sessionIDsLock sync.RWMutex
+ )
// Save any session IDs we use.
s.AddCallWatcher(func(call server.Call) {
@@ -177,9 +179,10 @@ func TestBridge_Cookies(t *testing.T) {
return
}
- sessionIDs.Mod(func(sessionIDs *[]string) {
- *sessionIDs = append(*sessionIDs, cookie.Value)
- })
+ sessionIDsLock.Lock()
+ defer sessionIDsLock.Unlock()
+
+ sessionIDs = append(sessionIDs, cookie.Value)
})
// Start bridge and add a user so that API assigns us a session ID via cookie.
@@ -194,9 +197,10 @@ func TestBridge_Cookies(t *testing.T) {
})
// We should have used just one session ID.
- sessionIDs.Load(func(sessionIDs []string) {
- require.Len(t, xslices.Unique(sessionIDs), 1)
- })
+ sessionIDsLock.Lock()
+ defer sessionIDsLock.Unlock()
+
+ require.Len(t, xslices.Unique(sessionIDs), 1)
})
}
diff --git a/internal/safe/map.go b/internal/safe/map.go
deleted file mode 100644
index 0898a695..00000000
--- a/internal/safe/map.go
+++ /dev/null
@@ -1,344 +0,0 @@
-// Copyright (c) 2022 Proton AG
-//
-// This file is part of Proton Mail Bridge.
-//
-// Proton Mail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Proton Mail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Proton Mail Bridge. If not, see .
-
-package safe
-
-import (
- "sync"
-
- "github.com/bradenaw/juniper/xslices"
- "golang.org/x/exp/slices"
-)
-
-type Map[Key comparable, Val any] struct {
- data map[Key]Val
- order []Key
- sort func(a, b Key, data map[Key]Val) bool
- lock sync.RWMutex
-}
-
-func NewMap[Key comparable, Val any](sort func(a, b Key, data map[Key]Val) bool) *Map[Key, Val] {
- return &Map[Key, Val]{
- data: make(map[Key]Val),
- sort: sort,
- }
-}
-
-func NewMapFrom[Key comparable, Val any](from map[Key]Val, sort func(a, b Key, data map[Key]Val) bool) *Map[Key, Val] {
- m := NewMap(sort)
-
- for key, val := range from {
- m.Set(key, val)
- }
-
- return m
-}
-
-func (m *Map[Key, Val]) Index(idx int, fn func(Key, Val)) bool {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- if idx < 0 || idx >= len(m.order) {
- return false
- }
-
- fn(m.order[idx], m.data[m.order[idx]])
-
- return true
-}
-
-func (m *Map[Key, Val]) Has(key Key) bool {
- return m.HasFunc(func(k Key, v Val) bool {
- return k == key
- })
-}
-
-func (m *Map[Key, Val]) HasFunc(fn func(key Key, val Val) bool) bool {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- for key, val := range m.data {
- if fn(key, val) {
- return true
- }
- }
-
- return false
-}
-
-func (m *Map[Key, Val]) Get(key Key, fn func(Val)) bool {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- val, ok := m.data[key]
- if !ok {
- return false
- }
-
- fn(val)
-
- return true
-}
-
-func (m *Map[Key, Val]) GetErr(key Key, fn func(Val) error) (bool, error) {
- var err error
-
- ok := m.Get(key, func(val Val) {
- err = fn(val)
- })
-
- return ok, err
-}
-
-func (m *Map[Key, Val]) GetDelete(key Key, fn func(Val)) bool {
- m.lock.Lock()
- defer m.lock.Unlock()
-
- val, ok := m.data[key]
- if !ok {
- return false
- }
-
- fn(val)
-
- delete(m.data, key)
-
- if idx := xslices.Index(m.order, key); idx >= 0 {
- m.order = append(m.order[:idx], m.order[idx+1:]...)
- } else {
- panic("order and data out of sync")
- }
-
- return true
-}
-
-func (m *Map[Key, Val]) GetDeleteErr(key Key, fn func(Val) error) (bool, error) {
- var err error
-
- ok := m.GetDelete(key, func(val Val) {
- err = fn(val)
- })
-
- return ok, err
-}
-
-func (m *Map[Key, Val]) GetFunc(where func(Val) bool, fn func(Val)) bool {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- for _, key := range m.order {
- if where(m.data[key]) {
- fn(m.data[key])
- return true
- }
- }
-
- return false
-}
-
-func (m *Map[Key, Val]) Delete(key Key) bool {
- return m.GetDelete(key, func(val Val) {})
-}
-
-func (m *Map[Key, Val]) Set(key Key, val Val) bool {
- m.lock.Lock()
- defer m.lock.Unlock()
-
- var had bool
-
- if _, ok := m.data[key]; ok {
- had = true
- }
-
- m.data[key] = val
-
- if idx := xslices.Index(m.order, key); idx >= 0 {
- m.order[idx] = key
- } else {
- m.order = append(m.order, key)
- }
-
- if m.sort != nil {
- slices.SortFunc(m.order, func(a, b Key) bool {
- return m.sort(a, b, m.data)
- })
- }
-
- return had
-}
-
-func (m *Map[Key, Val]) SetFrom(key Key, other Key) bool {
- m.lock.Lock()
- defer m.lock.Unlock()
-
- var had bool
-
- if _, ok := m.data[key]; ok {
- had = true
- }
-
- m.data[key] = m.data[other]
-
- if idx := xslices.Index(m.order, key); idx >= 0 {
- m.order[idx] = key
- } else {
- m.order = append(m.order, key)
- }
-
- if m.sort != nil {
- slices.SortFunc(m.order, func(a, b Key) bool {
- return m.sort(a, b, m.data)
- })
- }
-
- return had
-}
-
-func (m *Map[Key, Val]) Iter(fn func(key Key, val Val)) {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- for _, key := range m.order {
- fn(key, m.data[key])
- }
-}
-
-func (m *Map[Key, Val]) IterKeys(fn func(Key)) {
- m.Iter(func(key Key, _ Val) {
- fn(key)
- })
-}
-
-func (m *Map[Key, Val]) IterKeysErr(fn func(Key) error) error {
- var err error
-
- m.IterKeys(func(key Key) {
- if err != nil {
- return
- }
-
- err = fn(key)
- })
-
- return err
-}
-
-func (m *Map[Key, Val]) IterValues(fn func(Val)) {
- m.Iter(func(_ Key, val Val) {
- fn(val)
- })
-}
-
-func (m *Map[Key, Val]) IterValuesErr(fn func(Val) error) error {
- var err error
-
- m.IterValues(func(val Val) {
- if err != nil {
- return
- }
-
- err = fn(val)
- })
-
- return err
-}
-
-func (m *Map[Key, Val]) Values(fn func(vals []Val)) {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- vals := make([]Val, len(m.order))
-
- for i, key := range m.order {
- vals[i] = m.data[key]
- }
-
- fn(vals)
-}
-
-func (m *Map[Key, Val]) ValuesErr(fn func(vals []Val) error) error {
- var err error
-
- m.Values(func(vals []Val) {
- err = fn(vals)
- })
-
- return err
-}
-
-func (m *Map[Key, Val]) Clear() {
- m.lock.Lock()
- defer m.lock.Unlock()
-
- m.data = make(map[Key]Val)
- m.order = nil
-}
-
-func (m *Map[Key, Val]) MapErr(fn func(map[Key]Val) error) error {
- m.lock.RLock()
- defer m.lock.RUnlock()
-
- return fn(m.data)
-}
-
-func MapGetRet[Key comparable, Val, Ret any](m *Map[Key, Val], key Key, fn func(Val) Ret) (Ret, bool) {
- var ret Ret
-
- ok := m.Get(key, func(val Val) {
- ret = fn(val)
- })
-
- return ret, ok
-}
-
-func MapGetRetErr[Key comparable, Val, Ret any](m *Map[Key, Val], key Key, fn func(Val) (Ret, error)) (Ret, bool, error) {
- var ret Ret
-
- ok, err := m.GetErr(key, func(val Val) error {
- var err error
-
- ret, err = fn(val)
-
- return err
- })
-
- return ret, ok, err
-}
-
-func MapValuesRet[Key comparable, Val, Ret any](m *Map[Key, Val], fn func([]Val) Ret) Ret {
- var ret Ret
-
- m.Values(func(vals []Val) {
- ret = fn(vals)
- })
-
- return ret
-}
-
-func MapValuesRetErr[Key comparable, Val, Ret any](m *Map[Key, Val], fn func([]Val) (Ret, error)) (Ret, error) {
- var ret Ret
-
- err := m.ValuesErr(func(vals []Val) error {
- var err error
-
- ret, err = fn(vals)
-
- return err
- })
-
- return ret, err
-}
diff --git a/internal/safe/map_test.go b/internal/safe/map_test.go
deleted file mode 100644
index 96465baf..00000000
--- a/internal/safe/map_test.go
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (c) 2022 Proton AG
-//
-// This file is part of Proton Mail Bridge.
-//
-// Proton Mail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Proton Mail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Proton Mail Bridge. If not, see .
-
-package safe
-
-import "testing"
-
-func TestSafe_Map(t *testing.T) {
- m := NewMap(func(a, b string, data map[string]string) bool {
- return a < b
- })
-
- m.Set("a", "b")
-
- if !m.Has("a") {
- t.Fatal("expected to have key")
- }
-
- if m.Has("b") {
- t.Fatal("expected not to have key")
- }
-
- m.Set("b", "c")
-
- if !m.Has("b") {
- t.Fatal("expected to have key")
- }
-
- if !m.HasFunc(func(key string, val string) bool {
- return key == "b"
- }) {
- t.Fatal("expected to have key")
- }
-
- if !m.Get("b", func(val string) {
- if val != "c" {
- t.Fatal("expected to have value")
- }
- }) {
- t.Fatal("expected to have key")
- }
-
- if !m.Index(0, func(key string, val string) {
- if key != "a" || val != "b" {
- t.Fatal("expected to have key and value")
- }
- }) {
- t.Fatal("expected to have index")
- }
-
- if !m.Index(1, func(key string, val string) {
- if key != "b" || val != "c" {
- t.Fatal("expected to have key and value")
- }
- }) {
- t.Fatal("expected to have index")
- }
-
- if m.Index(2, func(key string, val string) {
- t.Fatal("expected not to have index")
- }) {
- t.Fatal("expected not to have index")
- }
-
- if !m.GetDelete("b", func(val string) {
- if val != "c" {
- t.Fatal("expected to have value")
- }
- }) {
- t.Fatal("expected to have key")
- }
-
- if m.Has("b") {
- t.Fatal("expected not to have key")
- }
-
- if m.GetDelete("b", func(val string) {
- t.Fatal("expected not to have value")
- }) {
- t.Fatal("expected not to have key")
- }
-
- if !m.Index(0, func(key string, val string) {
- if key != "a" || val != "b" {
- t.Fatal("expected to have key and value")
- }
- }) {
- t.Fatal("expected to have index")
- }
-
- m.Values(func(val []string) {
- if len(val) != 1 {
- t.Fatal("expected to have values")
- }
-
- if val[0] != "b" {
- t.Fatal("expected to have value")
- }
- })
-}
diff --git a/internal/safe/slice.go b/internal/safe/slice.go
deleted file mode 100644
index f6deaed9..00000000
--- a/internal/safe/slice.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2022 Proton AG
-//
-// This file is part of Proton Mail Bridge.
-//
-// Proton Mail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Proton Mail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Proton Mail Bridge. If not, see .
-
-package safe
-
-import (
- "sync"
-
- "github.com/bradenaw/juniper/xslices"
-)
-
-type Slice[Val comparable] struct {
- data []Val
- lock sync.RWMutex
-}
-
-func NewSlice[Val comparable](from ...Val) *Slice[Val] {
- s := &Slice[Val]{
- data: make([]Val, len(from)),
- }
-
- copy(s.data, from)
-
- return s
-}
-
-func (s *Slice[Val]) Iter(fn func(val Val)) {
- s.lock.RLock()
- defer s.lock.RUnlock()
-
- for _, val := range s.data {
- fn(val)
- }
-}
-
-func (s *Slice[Val]) Append(val Val) {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- s.data = append(s.data, val)
-}
-
-func (s *Slice[Val]) Delete(val Val) {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- s.data = xslices.Filter(s.data, func(v Val) bool {
- return v != val
- })
-}
diff --git a/internal/safe/slice_test.go b/internal/safe/slice_test.go
deleted file mode 100644
index dc6c68c2..00000000
--- a/internal/safe/slice_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2022 Proton AG
-//
-// This file is part of Proton Mail Bridge.
-//
-// Proton Mail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Proton Mail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Proton Mail Bridge. If not, see .
-
-package safe
-
-import (
- "testing"
-
- "github.com/stretchr/testify/require"
-)
-
-func TestSlice(t *testing.T) {
- s := NewSlice(1, 2, 3, 4, 5)
-
- {
- var have []int
-
- s.Iter(func(val int) {
- have = append(have, val)
- })
-
- require.Equal(t, []int{1, 2, 3, 4, 5}, have)
- }
-
- s.Append(6)
- s.Delete(3)
-
- {
- var have []int
-
- s.Iter(func(val int) {
- have = append(have, val)
- })
-
- require.Equal(t, []int{1, 2, 4, 5, 6}, have)
- }
-}
diff --git a/internal/safe/value.go b/internal/safe/value.go
deleted file mode 100644
index b072d46c..00000000
--- a/internal/safe/value.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2022 Proton AG
-//
-// This file is part of Proton Mail Bridge.
-//
-// Proton Mail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Proton Mail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Proton Mail Bridge. If not, see .
-
-package safe
-
-import "sync"
-
-type Value[T any] struct {
- data T
- lock sync.RWMutex
-}
-
-func NewValue[T any](data T) *Value[T] {
- return &Value[T]{
- data: data,
- }
-}
-
-func (s *Value[T]) Load(fn func(data T)) {
- s.lock.RLock()
- defer s.lock.RUnlock()
-
- fn(s.data)
-}
-
-func (s *Value[T]) LoadErr(fn func(data T) error) error {
- var err error
-
- s.Load(func(data T) {
- err = fn(data)
- })
-
- return err
-}
-
-func (s *Value[T]) Save(data T) {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- s.data = data
-}
-
-func (s *Value[T]) Mod(fn func(data *T)) {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- fn(&s.data)
-}
-
-func LoadRet[T, Ret any](s *Value[T], fn func(data T) Ret) Ret {
- var ret Ret
-
- s.Load(func(data T) {
- ret = fn(data)
- })
-
- return ret
-}
-
-func LoadRetErr[T, Ret any](s *Value[T], fn func(data T) (Ret, error)) (Ret, error) {
- var ret Ret
-
- err := s.LoadErr(func(data T) error {
- var err error
-
- ret, err = fn(data)
-
- return err
- })
-
- return ret, err
-}
diff --git a/internal/safe/value_test.go b/internal/safe/value_test.go
deleted file mode 100644
index 8a0c4b58..00000000
--- a/internal/safe/value_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2022 Proton AG
-//
-// This file is part of Proton Mail Bridge.
-//
-// Proton Mail Bridge is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Proton Mail Bridge is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Proton Mail Bridge. If not, see .
-
-package safe
-
-import "testing"
-
-func TestValue(t *testing.T) {
- v := NewValue("foo")
-
- v.Load(func(data string) {
- if data != "foo" {
- t.Error("expected foo")
- }
- })
-
- v.Save("bar")
-
- v.Load(func(data string) {
- if data != "bar" {
- t.Error("expected bar")
- }
- })
-
- v.Mod(func(data *string) {
- *data = "baz"
- })
-
- v.Load(func(data string) {
- if data != "baz" {
- t.Error("expected baz")
- }
- })
-
- if LoadRet(v, func(data string) string {
- return data
- }) != "baz" {
- t.Error("expected baz")
- }
-}