decoder.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package exporter
  2. import (
  3. "bytes"
  4. "compress/gzip"
  5. "encoding"
  6. "fmt"
  7. "io"
  8. "github.com/opencost/opencost/core/pkg/util/json"
  9. "google.golang.org/protobuf/proto"
  10. )
  11. type Decoder[T any] func([]byte) (*T, error)
  12. // BinaryMarshalerPtr[T] is a generic constraint to ensure types passed to the encoder implement
  13. // encoding.BinaryMarshaler and are pointers to T.
  14. type BinaryUnmarshalerPtr[T any] interface {
  15. encoding.BinaryUnmarshaler
  16. *T
  17. }
  18. func BingenDecoder[T any, U BinaryUnmarshalerPtr[T]](data []byte) (*T, error) {
  19. var set U = new(T)
  20. err := set.UnmarshalBinary(data)
  21. if err != nil {
  22. return nil, fmt.Errorf("failed to decode bingen: %w", err)
  23. }
  24. return set, nil
  25. }
  26. func JSONDecoder[T any](data []byte) (*T, error) {
  27. var instance = new(T)
  28. err := json.Unmarshal(data, instance)
  29. if err != nil {
  30. return nil, fmt.Errorf("failed to decode json: %w", err)
  31. }
  32. return instance, nil
  33. }
  34. func ProtobufDecoder[T any, U ProtoMessagePtr[T]](data []byte) (*T, error) {
  35. var message U = new(T)
  36. err := proto.Unmarshal(data, message)
  37. if err != nil {
  38. return nil, fmt.Errorf("failed to decode protobuf message: %w", err)
  39. }
  40. return message, nil
  41. }
  42. func GetGzipDecoder[T any](decoder Decoder[T]) Decoder[T] {
  43. return func(data []byte) (*T, error) {
  44. // Check for gzip compression. Ref: https://www.ietf.org/rfc/rfc1952.txt Page 5
  45. if len(data) > 2 && data[0] == 0x1F && data[1] == 0x8B {
  46. buf := bytes.NewBuffer(data)
  47. reader, err := gzip.NewReader(buf)
  48. if err != nil {
  49. return nil, fmt.Errorf("failed to decompress gzip: %w", err)
  50. }
  51. defer reader.Close()
  52. decompressed, err := io.ReadAll(reader)
  53. if err != nil {
  54. return nil, fmt.Errorf("failed to read decompressed gzip: %w", err)
  55. }
  56. data = decompressed
  57. }
  58. instance, err := decoder(data)
  59. if err != nil {
  60. return nil, fmt.Errorf("failed to decode decompress gzip data: %w", err)
  61. }
  62. return instance, nil
  63. }
  64. }