-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from sonirico/feature/model-registry
feat: multimodels
- Loading branch information
Showing
7 changed files
with
303 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
"log" | ||
|
||
"github.com/sonirico/parco" | ||
) | ||
|
||
type ( | ||
Animal struct { | ||
Age uint8 | ||
Specie string | ||
} | ||
|
||
Flat struct { | ||
Price float32 | ||
Address string | ||
} | ||
) | ||
|
||
const ( | ||
AnimalType int = 0 | ||
FlatType = 1 | ||
) | ||
|
||
func (a Animal) ParcoID() int { | ||
return AnimalType | ||
} | ||
|
||
func (a Flat) ParcoID() int { | ||
return FlatType | ||
} | ||
|
||
func main() { | ||
animalBuilder := parco.Builder[Animal](parco.ObjectFactory[Animal]()). | ||
SmallVarchar( | ||
func(a *Animal) string { return a.Specie }, | ||
func(a *Animal, specie string) { a.Specie = specie }, | ||
). | ||
UInt8( | ||
func(a *Animal) uint8 { return a.Age }, | ||
func(a *Animal, age uint8) { a.Age = age }, | ||
) | ||
|
||
flatBuilder := parco.Builder[Flat](parco.ObjectFactory[Flat]()). | ||
Float32( | ||
binary.LittleEndian, | ||
func(f *Flat) float32 { return f.Price }, | ||
func(f *Flat, price float32) { f.Price = price }, | ||
). | ||
SmallVarchar( | ||
func(f *Flat) string { return f.Address }, | ||
func(f *Flat, address string) { f.Address = address }, | ||
) | ||
|
||
parCo := parco.MultiBuilder(parco.UInt8Header()). // Register up to 255 different models | ||
MustRegister(AnimalType, animalBuilder). | ||
MustRegister(FlatType, flatBuilder) | ||
|
||
buf := bytes.NewBuffer(nil) | ||
|
||
// `Compile` API may be used if your models satisfy the `serializable` interface: | ||
// type seriazable[T comparable] interface{ ParcoID() int } | ||
_ = parCo.Compile(Animal{Age: 10, Specie: "monkeys"}, buf) | ||
_ = parCo.Compile(Flat{Price: 42, Address: "Plaza mayor"}, buf) | ||
|
||
// Or, the `CompileAny` can be employed instead by specifying each model ID. | ||
_ = parCo.CompileAny(AnimalType, Animal{Age: 7, Specie: "felix catus"}, buf) | ||
|
||
id, something, _ := parCo.Parse(buf) | ||
Print(id, something) | ||
id, something, _ = parCo.Parse(buf) | ||
Print(id, something) | ||
id, something, _ = parCo.Parse(buf) | ||
Print(id, something) | ||
} | ||
|
||
func Print(id int, x any) { | ||
switch id { | ||
case AnimalType: | ||
animal := x.(Animal) | ||
log.Println("animal:", animal) | ||
case FlatType: | ||
flat := x.(Flat) | ||
log.Println("flat", flat) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package parco | ||
|
||
import ( | ||
"fmt" | ||
"github.com/pkg/errors" | ||
"io" | ||
) | ||
|
||
type ( | ||
serializable[T comparable] interface { | ||
ParcoID() T | ||
} | ||
|
||
parserAny interface { | ||
ParseAny(io.Reader) (any, error) | ||
} | ||
|
||
compilerAny interface { | ||
CompileAny(any, io.Writer) error | ||
} | ||
|
||
builderAny interface { | ||
parserAny | ||
compilerAny | ||
} | ||
|
||
ModelMultiBuilder[T comparable] struct { | ||
header Type[T] | ||
|
||
parsers map[T]parserAny | ||
|
||
compilers map[T]compilerAny | ||
} | ||
) | ||
|
||
func MultiBuilder[T comparable](header Type[T]) *ModelMultiBuilder[T] { | ||
return &ModelMultiBuilder[T]{ | ||
header: header, | ||
parsers: make(map[T]parserAny), | ||
compilers: make(map[T]compilerAny), | ||
} | ||
} | ||
|
||
func (b *ModelMultiBuilder[T]) Register(id T, builder builderAny) (*ModelMultiBuilder[T], error) { | ||
if _, ok := b.parsers[id]; !ok { | ||
b.parsers[id] = builder | ||
b.compilers[id] = builder | ||
return b, nil | ||
} | ||
return b, errors.Wrapf(ErrAlreadyRegistered, "id: %v", id) | ||
} | ||
|
||
func (b *ModelMultiBuilder[T]) MustRegister(id T, builder builderAny) *ModelMultiBuilder[T] { | ||
if _, ok := b.parsers[id]; !ok { | ||
b.parsers[id] = builder | ||
b.compilers[id] = builder | ||
return b | ||
} | ||
panic(fmt.Sprintf("this id is registered already: %v", id)) | ||
} | ||
|
||
func (b *ModelMultiBuilder[T]) Parse(r io.Reader) (id T, res any, err error) { | ||
id, err = b.header.Parse(r) | ||
if err != nil { | ||
return | ||
} | ||
|
||
p, ok := b.parsers[id] | ||
|
||
if !ok { | ||
err = errors.Wrapf(ErrUnknownType, "%v", id) | ||
return | ||
} | ||
|
||
res, err = p.ParseAny(r) | ||
return | ||
} | ||
|
||
func (b *ModelMultiBuilder[T]) Compile(item serializable[T], w io.Writer) (err error) { | ||
return b.compile(item.ParcoID(), item, w) | ||
} | ||
|
||
func (b *ModelMultiBuilder[T]) CompileAny(id T, item any, w io.Writer) (err error) { | ||
return b.compile(id, item, w) | ||
} | ||
|
||
func (b *ModelMultiBuilder[T]) compile(id T, item any, w io.Writer) (err error) { | ||
err = b.header.Compile(id, w) | ||
|
||
if err != nil { | ||
return | ||
} | ||
|
||
c, ok := b.compilers[id] | ||
|
||
if !ok { | ||
err = errors.Wrapf(ErrUnknownType, "%v", id) | ||
return | ||
} | ||
|
||
err = c.CompileAny(item, w) | ||
return | ||
} |