| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- package pokemonparsing
- import (
- "sync"
- p "github.com/ajswis/go-pkparse-server/pokemon"
- "github.com/ajswis/go-pkparse-server/pokemon-parsing/gen7"
- )
- // NOTE: For unit testing simplicity, perhaps defining a parsing interface and
- // wrapper type for all parsers would make isolating tests easier.
- // Parse returns either a parsed Pokemon with all applicable struct fields
- // populated, or an error detailing what was wrong.
- func Parse(rawPokemon p.RawPokemon) (*p.Pokemon, error) {
- // TODO: Conditionally swap to different generation parsers depending on given
- // byte slice.
- return gen7.Parse(rawPokemon)
- }
- // ParseAll returns either a slice of parsed Pokemon with all applicable struct
- // fields populated, or an error detailing what was wrong with any attempt.
- //
- // Additionally, ParseAll will parallelize large data sets. This concurrency
- // might be a preemptive optimization at the moment, but once parsers are
- // fully realized, benchmarks can determine the usefulness of parallelization.
- func ParseAll(rawPokemon []p.RawPokemon) ([]*p.Pokemon, error) {
- if len(rawPokemon) >= 10 {
- return concurrentParseAll(rawPokemon)
- }
- return serialParseAll(rawPokemon)
- }
- func serialParseAll(rawPokemon []p.RawPokemon) ([]*p.Pokemon, error) {
- var pkmn = []*p.Pokemon{}
- for _, p := range rawPokemon {
- parsed, err := Parse(p)
- if err != nil {
- return nil, err
- }
- pkmn = append(pkmn, parsed)
- }
- return pkmn, nil
- }
- type parseResult struct {
- pkmn *p.Pokemon
- err error
- }
- // concurrentParseAll fans out the data set to Parse in parallel, but does not
- // end early on a failure or cancelled request. Providing done channels can
- // resolve this, but it would probably be worth waiting until handling of
- // `context.Context`s is applied.
- func concurrentParseAll(rawPokemon []p.RawPokemon) ([]*p.Pokemon, error) {
- var wg sync.WaitGroup
- pkmnc := make(chan *parseResult)
- for _, pkmn := range rawPokemon {
- wg.Add(1)
- go func(unparsed p.RawPokemon) {
- defer wg.Done()
- res, err := Parse(unparsed)
- pkmnc <- &parseResult{pkmn: res, err: err}
- }(pkmn)
- }
- go func() {
- wg.Wait()
- close(pkmnc)
- }()
- var parsedPokemon []*p.Pokemon
- for res := range pkmnc {
- if res.err != nil {
- return nil, res.err
- }
- parsedPokemon = append(parsedPokemon, res.pkmn)
- }
- return parsedPokemon, nil
- }
|