package storage
import (
"errors"
"net/url"
"path/filepath"
"strings"
"sync"
"github.com/navidrome/navidrome/utils/slice"
)
const LocalSchemaID = "file"
type constructor func(url.URL) Storage
var (
registry = map[string]constructor{}
lock sync.RWMutex
)
func Register(schema string, c constructor) {
lock.Lock()
defer lock.Unlock()
registry[schema] = c
}
func For(uri string) (Storage, error) {
lock.RLock()
defer lock.RUnlock()
parts := strings.Split(uri, "://")
if len(parts) < 2 {
uri, _ = filepath.Abs(uri)
uri = filepath.ToSlash(uri)
pathParts := strings.Split(uri, "/")
escapedParts := slice.Map(pathParts, func(s string) string {
return url.PathEscape(s)
})
uri = LocalSchemaID + "://" + strings.Join(escapedParts, "/")
}
u, err := url.Parse(uri)
if err != nil {
return nil, err
}
c, ok := registry[u.Scheme]
if !ok {
return nil, errors.New("schema '" + u.Scheme + "' not registered")
}
return c(*u), nil
}