qmp-testing-suite/golang-producer-consumer/vendor/gitlab-app.eng.qops.net/golang/qmp/qsl/reader.go

75 lines
2.3 KiB
Go
Executable File

package qsl
import (
"fmt"
"strings"
"github.com/linkedin/goavro"
"gitlab-app.eng.qops.net/golang/qmp/qsl/internal/qm"
"gitlab-app.eng.qops.net/golang/qmp/qsl/internal/schema"
"gitlab-app.eng.qops.net/golang/qmp/qsl/internal/schema/registry"
)
// qmReader implements the qsl.Reader interface.
type qmReader struct {
readerSchemaSpec string
manager readerSchemaManager
}
type readerSchemaManager interface {
Get(string) (string, error)
}
// newReader creats a new Message reader generator.
func newReader(readerSchemaSpec string, schemaManager readerSchemaManager) *qmReader {
return &qmReader{
readerSchemaSpec: readerSchemaSpec,
manager: schemaManager,
}
}
// NewMessage creates a new Message from the input
// avro binary using the qmReader's schema.
func (q *qmReader) NewMessage(encodedAvroValue []byte) (Message, error) {
// get short envelope schema spec to extract the encodedAvroValue's schema ID
envelopeSchema, err := q.manager.Get(schema.EnvelopeSchemaID)
if err != nil {
return nil, err
}
codec, err := goavro.NewCodec(envelopeSchema)
if err != nil {
return nil, err
}
var envelopeNative interface{}
// If the schema spec is a union (complex schema with declarations), the
// first bit is the index of the union. Remove that so we can get the
// schema spec ID.
if s := strings.TrimSpace(q.readerSchemaSpec); s != "" && s[0] == '[' && len(encodedAvroValue) > 0 {
envelopeNative, _, err = codec.NativeFromBinary(encodedAvroValue[1:])
} else {
envelopeNative, _, err = codec.NativeFromBinary(encodedAvroValue)
}
if err != nil {
return nil, err
}
envelopeMap, ok := envelopeNative.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("standard %s schema spec didn't parse bytes as a map", schema.EnvelopeSchemaID)
}
schemaIDValue, ok := envelopeMap[registry.SchemaID]
if !ok {
return nil, fmt.Errorf("standard %s schema spec didn't parse %s from bytes", schema.EnvelopeSchemaID, registry.SchemaID)
}
schemaID, ok := schemaIDValue.(string)
if !ok {
return nil, fmt.Errorf("standard %s schema spec parsed %s as non-string", schema.EnvelopeSchemaID, registry.SchemaID)
}
// fetch writer schema spec from schemaID named in encodedAvroValue
writerSchemaSpec, err := q.manager.Get(schemaID)
if err != nil {
return nil, err
}
return qm.NewReadingMessage(writerSchemaSpec, q.readerSchemaSpec, encodedAvroValue)
}