75 lines
2.3 KiB
Go
Executable File
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)
|
|
}
|