converter.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // Copyright 2022-2023 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package protobuf
  15. import (
  16. "fmt"
  17. "github.com/jhump/protoreflect/desc"
  18. "github.com/jhump/protoreflect/desc/protoparse"
  19. kconf "github.com/lf-edge/ekuiper/internal/conf"
  20. "github.com/lf-edge/ekuiper/internal/converter/static"
  21. "github.com/lf-edge/ekuiper/pkg/message"
  22. )
  23. type Converter struct {
  24. descriptor *desc.MessageDescriptor
  25. fc *FieldConverter
  26. }
  27. var protoParser *protoparse.Parser
  28. func init() {
  29. etcDir, _ := kconf.GetLoc("etc/schemas/protobuf/")
  30. dataDir, _ := kconf.GetLoc("data/schemas/protobuf/")
  31. protoParser = &protoparse.Parser{ImportPaths: []string{etcDir, dataDir}}
  32. }
  33. func NewConverter(schemaFile string, soFile string, messageName string) (message.Converter, error) {
  34. if soFile != "" {
  35. return static.LoadStaticConverter(soFile, messageName)
  36. } else {
  37. if fds, err := protoParser.ParseFiles(schemaFile); err != nil {
  38. return nil, fmt.Errorf("parse schema file %s failed: %s", schemaFile, err)
  39. } else {
  40. messageDescriptor := fds[0].FindMessage(messageName)
  41. if messageDescriptor == nil {
  42. return nil, fmt.Errorf("message type %s not found in schema file %s", messageName, schemaFile)
  43. }
  44. return &Converter{
  45. descriptor: messageDescriptor,
  46. fc: GetFieldConverter(),
  47. }, nil
  48. }
  49. }
  50. }
  51. func (c *Converter) Encode(d interface{}) ([]byte, error) {
  52. switch m := d.(type) {
  53. case map[string]interface{}:
  54. msg, err := c.fc.encodeMap(c.descriptor, m)
  55. if err != nil {
  56. return nil, err
  57. }
  58. return msg.Marshal()
  59. default:
  60. return nil, fmt.Errorf("unsupported type %v, must be a map", d)
  61. }
  62. }
  63. func (c *Converter) Decode(b []byte) (interface{}, error) {
  64. result := mf.NewDynamicMessage(c.descriptor)
  65. err := result.Unmarshal(b)
  66. if err != nil {
  67. return nil, err
  68. }
  69. return c.fc.DecodeMessage(result, c.descriptor), nil
  70. }