-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathurls.go
More file actions
88 lines (78 loc) · 3.08 KB
/
urls.go
File metadata and controls
88 lines (78 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package cache
import (
"context"
"errors"
"fmt"
"net/url"
"sync"
"github.com/bartventer/gocache/internal/gcerrors"
"github.com/bartventer/gocache/pkg/driver"
"github.com/bartventer/gocache/pkg/keymod"
)
// URLOpener defines the interface for opening a cache using a URL.
type URLOpener[K driver.String] interface {
// OpenCacheURL opens a cache using a URL and options.
OpenCacheURL(ctx context.Context, u *url.URL) (*GenericCache[K], error)
}
// urlMux is a multiplexer for cache schemes.
type urlMux struct {
mu sync.RWMutex // mu is a mutex for synchronizing access to the schemes map.
schemes map[string]map[string]interface{} // schemes maps a cache scheme to a map of type strings to URLOpeners.
}
var defaultURLMux = new(urlMux)
// RegisterCache registers a [URLOpener] for a given scheme and type.
// If a [URLOpener] is already registered for the scheme and type, it panics.
// Not intended for direct application use.
func RegisterCache[K driver.String](scheme string, opener URLOpener[K]) {
defaultURLMux.mu.Lock()
defer defaultURLMux.mu.Unlock()
if defaultURLMux.schemes == nil {
defaultURLMux.schemes = make(map[string]map[string]interface{})
}
if _, exists := defaultURLMux.schemes[scheme]; !exists {
defaultURLMux.schemes[scheme] = make(map[string]interface{})
}
typeKey := getTypeKey[K]()
if _, exists := defaultURLMux.schemes[scheme][typeKey]; exists {
panic(gcerrors.New(errors.New("scheme and type already registered: " + scheme + " - " + typeKey)))
}
defaultURLMux.schemes[scheme][typeKey] = opener
}
// getTypeKey returns a string representation of the type K.
func getTypeKey[K driver.String]() string {
var k K
return fmt.Sprintf("%T", k)
}
// OpenGenericCache opens a [GenericCache] for the provided URL string and type.
// It returns an error if the URL cannot be parsed, or if no [URLOpener] is registered for the
// URL's scheme and type. Not intended for direct application use.
func OpenGenericCache[K driver.String](ctx context.Context, urlstr string) (*GenericCache[K], error) {
u, err := url.Parse(urlstr)
if err != nil {
return nil, err
}
defaultURLMux.mu.RLock()
schemeOpeners, ok := defaultURLMux.schemes[u.Scheme]
defaultURLMux.mu.RUnlock()
if !ok {
return nil, gcerrors.New(errors.New("no registered opener for scheme: " + u.Scheme))
}
typeKey := getTypeKey[K]()
opener, ok := schemeOpeners[typeKey]
if !ok {
return nil, gcerrors.New(errors.New("no registered opener for type: " + typeKey))
}
return opener.(URLOpener[K]).OpenCacheURL(ctx, u)
}
// OpenCache opens a [Cache] for the provided URL string.
// It returns an error if the URL cannot be parsed, or if no [URLOpener] is registered for the URL'
// s scheme.
func OpenCache(ctx context.Context, urlstr string) (*Cache, error) {
return OpenGenericCache[string](ctx, urlstr)
}
// OpenKeyCache opens a [KeyCache] for the provided URL string.
// It returns an error if the URL cannot be parsed, or if no [URLOpener] is registered for the
// URL's scheme.
func OpenKeyCache(ctx context.Context, urlstr string) (*KeyCache, error) {
return OpenGenericCache[keymod.Key](ctx, urlstr)
}