move types into a separate package
This commit is contained in:
parent
c25857fff9
commit
e604806f81
96
internal/types/types.go
Normal file
96
internal/types/types.go
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnknownType = errors.New("Unknown type")
|
||||
)
|
||||
|
||||
//type Name string //`json:"type"`
|
||||
|
||||
type Factory[Product any] func(*url.URL) Product
|
||||
type RegistryTypeMap[Product any] map[string]Factory[Product]
|
||||
|
||||
type Types[Product any] struct {
|
||||
registry RegistryTypeMap[Product]
|
||||
}
|
||||
|
||||
func New[Product any]() *Types[Product] {
|
||||
return &Types[Product]{registry: make(map[string]Factory[Product])}
|
||||
}
|
||||
|
||||
func (t *Types[Product]) Register(names []string, factory Factory[Product]) {
|
||||
for _,name := range names {
|
||||
t.registry[name] = factory
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Types[Product]) FromExtension(path string) (Factory[Product], error) {
|
||||
elements := strings.Split(path, ".")
|
||||
numberOfElements := len(elements)
|
||||
if numberOfElements > 2 {
|
||||
if src := t.Get(strings.Join(elements[numberOfElements - 2: numberOfElements - 1], ".")); src != nil {
|
||||
return src, nil
|
||||
}
|
||||
}
|
||||
if src := t.Get(elements[numberOfElements - 1]); src != nil {
|
||||
return src, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w: %s", ErrUnknownType, path)
|
||||
}
|
||||
|
||||
func (t *Types[Product]) New(uri string) (result Product, err error) {
|
||||
u, e := url.Parse(uri)
|
||||
if u == nil || e != nil {
|
||||
err = fmt.Errorf("%w: %s", ErrUnknownType, e)
|
||||
return
|
||||
}
|
||||
|
||||
if u.Scheme == "" {
|
||||
u.Scheme = "file"
|
||||
}
|
||||
|
||||
path := filepath.Join(u.Hostname(), u.Path)
|
||||
if d, lookupErr := t.FromExtension(path); d != nil {
|
||||
return d(u), lookupErr
|
||||
}
|
||||
|
||||
if r, ok := t.registry[u.Scheme]; ok {
|
||||
return r(u), nil
|
||||
}
|
||||
err = fmt.Errorf("%w: %s", ErrUnknownType, u.Scheme)
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Types[Product]) Has(typename string) bool {
|
||||
if _, ok := t.registry[typename]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *Types[Product]) Get(typename string) Factory[Product] {
|
||||
if d, ok := t.registry[typename]; ok {
|
||||
return d
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (n *Name) UnmarshalJSON(b []byte) error {
|
||||
TypeName := strings.Trim(string(b), "\"")
|
||||
if SourceTypes.Has(TypeName) {
|
||||
*n = TypeName(TypeName)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("%w: %s", ErrUnknownType, TypeName)
|
||||
}
|
||||
*/
|
63
internal/types/types_test.go
Normal file
63
internal/types/types_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
_ "context"
|
||||
_ "encoding/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewSourceTypes(t *testing.T) {
|
||||
testTypes := New[int]()
|
||||
assert.NotNil(t, testTypes)
|
||||
}
|
||||
|
||||
func TestNewSourceTypesRegister(t *testing.T) {
|
||||
|
||||
testTypes := New[int]()
|
||||
assert.NotNil(t, testTypes)
|
||||
|
||||
testTypes.Register([]string{"foo"}, func(*url.URL) int { return 100 })
|
||||
|
||||
r, e := testTypes.New("foo://")
|
||||
assert.Nil(t, e)
|
||||
assert.Equal(t, 100, r)
|
||||
}
|
||||
|
||||
func TestTypesFromURI(t *testing.T) {
|
||||
testTypes := New[string]()
|
||||
assert.NotNil(t, testTypes)
|
||||
|
||||
testTypes.Register([]string{"foo"}, func(*url.URL) string { return "test" })
|
||||
|
||||
r, e := testTypes.New("foo://bar")
|
||||
assert.Nil(t, e)
|
||||
assert.Equal(t, "test", r)
|
||||
}
|
||||
|
||||
func TestTypesHasType(t *testing.T) {
|
||||
testTypes := New[string]()
|
||||
assert.NotNil(t, testTypes)
|
||||
|
||||
testTypes.Register([]string{"foo"}, func(*url.URL) string { return "hastest" })
|
||||
|
||||
assert.True(t, testTypes.Has("foo"))
|
||||
}
|
||||
|
||||
/*
|
||||
func TestTypeName(t *testing.T) {
|
||||
testTypes.Register([]string{"file"}, func(*url.URL) string { return "typetest" })
|
||||
|
||||
type fDocSourceName struct {
|
||||
Name TypeName `json:"type"`
|
||||
}
|
||||
fTypeName := &fDocSourceName{}
|
||||
jsonType := `{ "type": "file" }`
|
||||
e := json.Unmarshal([]byte(jsonType), &fTypeName)
|
||||
assert.Nil(t, e)
|
||||
assert.Equal(t, "file", string(fTypeName.Name))
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue
Block a user