Skip to content

Commit

Permalink
Merge pull request #64 from DIMO-Network/as-2999-add-ruptela-decoder-…
Browse files Browse the repository at this point in the history
…package-to-model-garage

As 2999 add ruptela decoder package to model garage
  • Loading branch information
KevinJoiner authored Oct 3, 2024
2 parents 0dd47cd + c5e36c2 commit f209247
Show file tree
Hide file tree
Showing 23 changed files with 2,282 additions and 195 deletions.
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,14 @@ tools: tools-golangci-lint
clickhouse:
go run ./cmd/clickhouse-container

generate:
go run ./cmd/codegen -convert.package=convert -generators=convert -convert.output-file=./pkg/nativestatus/convert/vehicle-convert-funcs_gen.go
go run ./cmd/codegen -generators=custom -custom.output-file=./pkg/nativestatus/convert/vehicle-v1-convert_gen.go -custom.template-file=./pkg/nativestatus/convertv1.tmpl -custom.format=true
go run ./cmd/codegen -generators=custom -custom.output-file=./pkg/nativestatus/convert/vehicle-v2-convert_gen.go -custom.template-file=./pkg/nativestatus/convertv2.tmpl -custom.format=true
generate: generate-nativestatus generate-ruptela # Generate all files for the repository
go run ./cmd/codegen -generators=custom -custom.output-file=./pkg/vss/vehicle-structs.go -custom.template-file=./internal/generator/vehicle.tmpl -custom.format=true

generate-nativestatus: # Generate all files for nativestatus
go run ./cmd/codegen -convert.package=nativestatus -generators=convert -convert.output-file=./pkg/nativestatus/vehicle-convert-funcs_gen.go
go run ./cmd/codegen -generators=custom -custom.output-file=./pkg/nativestatus/vehicle-v1-convert_gen.go -custom.template-file=./pkg/nativestatus/convertv1.tmpl -custom.format=true
go run ./cmd/codegen -generators=custom -custom.output-file=./pkg/nativestatus/vehicle-v2-convert_gen.go -custom.template-file=./pkg/nativestatus/convertv2.tmpl -custom.format=true

generate-ruptela: # Generate all files for ruptela
go run ./cmd/codegen -convert.package=ruptela -generators=convert -convert.output-file=./pkg/ruptela/vehicle-convert-funcs_gen.go -definitions=./pkg/ruptela/ruptela-definitions.yaml
go run ./cmd/codegen -generators=custom -custom.output-file=./pkg/ruptela/vehicle-v1-convert_gen.go -custom.template-file=./pkg/ruptela/convertv1.tmpl -custom.format=true -definitions=./pkg/ruptela/ruptela-definitions.yaml
26 changes: 25 additions & 1 deletion internal/generator/convert/convertFunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,31 @@ func writeConvertFuncs(convertFunc []funcTmplData, existingFuncs map[string]Func
var convertBuff bytes.Buffer
convertBuff.WriteString(fmt.Sprintf(header, packageName))
slices.SortStableFunc(convertFunc, func(a, b funcTmplData) int {
return cmp.Compare(a.FuncName, b.FuncName)
// split funcName to get digits at the end and compare the name then by the digit value
// get the function name without the digits at the end
aFuncName := a.FuncName
aDigits := 0
bFuncName := b.FuncName
bDigits := 0
for i := len(aFuncName) - 1; i >= 0; i-- {
if aFuncName[i] < '0' || aFuncName[i] > '9' {
aFuncName = aFuncName[:i+1]
aDigits, _ = strconv.Atoi(a.FuncName[i+1:])
break
}
}
for i := len(bFuncName) - 1; i >= 0; i-- {
if bFuncName[i] < '0' || bFuncName[i] > '9' {
bFuncName = bFuncName[:i+1]
bDigits, _ = strconv.Atoi(b.FuncName[i+1:])
break
}
}
val := cmp.Compare(aFuncName, bFuncName)
if val != 0 {
return val
}
return cmp.Compare(aDigits, bDigits)
})

// Add or update existing functions
Expand Down
9 changes: 9 additions & 0 deletions pkg/nativestatus/convert/errors.go → pkg/convert/errors.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Package convert provides common functions for handling signal conversion.
package convert

import (
"errors"
"fmt"
"strconv"
"strings"
Expand Down Expand Up @@ -63,3 +65,10 @@ func (e ConversionError) Error() string {
func (e ConversionError) Unwrap() []error {
return e.Errors
}

var errInvalidType = errors.New("invalid type")

// InvalidTypeError is returned when a field is not of the expected type or not found.
func InvalidTypeError() error {
return errInvalidType
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package convert_test
package nativestatus_test

import (
"context"
"testing"

"github.com/DIMO-Network/model-garage/pkg/nativestatus/convert"
"github.com/DIMO-Network/model-garage/pkg/nativestatus"
)

func BenchmarkConvertFromV1DataConversion(b *testing.B) {
getter := &tokenGetter{}
inputData := []byte(fullInputJSON)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := convert.SignalsFromV1Payload(context.Background(), getter, inputData)
_, err := nativestatus.SignalsFromV1Payload(context.Background(), getter, inputData)
if err != nil {
b.Fatalf("error converting full input data: %v", err)
}
Expand All @@ -23,7 +23,7 @@ func BenchmarkConvertFromV2DataConversion(b *testing.B) {
inputData := []byte(fullV2InputJSON)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := convert.SignalsFromV2Payload(inputData)
_, err := nativestatus.SignalsFromV2Payload(inputData)
if err != nil {
b.Fatalf("error converting full input data: %v", err)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/nativestatus/convertv1.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Code generated by github.com/DIMO-Network/model-garage DO NOT EDIT.
package convert
package nativestatus

var errNotFound = errors.New("field not found")

Expand Down Expand Up @@ -54,7 +54,7 @@ func {{ $sig.GOName }}FromV1Data(jsonData []byte) (ret {{ $sig.GOType }}, err er
if ok{
slice{{ $sig.GOName}}[i] = v
} else {
errs = errors.Join(errs, fmt.Errorf("%w, field 'data.{{ $conv.OriginalName }}' array element %d is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", errInvalidType, i, res.Value(), res.Value()))
errs = errors.Join(errs, fmt.Errorf("%w, field 'data.{{ $conv.OriginalName }}' array element %d is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", convert.InvalidTypeError(), i, res.Value(), res.Value()))
}
}
retVal, err = To{{ $sig.GOName }}{{ $j }}(jsonData, slice{{ $sig.GOName}})
Expand All @@ -63,7 +63,7 @@ func {{ $sig.GOName }}FromV1Data(jsonData []byte) (ret {{ $sig.GOType }}, err er
}
errs = errors.Join(errs, fmt.Errorf("failed to convert 'data.{{ $sig.Conversion.OriginalName }}': %w", err))
} else {
errs = errros.Join(errs, fmt.Errorf("%w, field 'data.{{ $conv.OriginalName }}' is not an array", errInvalidType))
errs = errros.Join(errs, fmt.Errorf("%w, field 'data.{{ $conv.OriginalName }}' is not an array", convert.InvalidTypeError()))
}
{{ else -}}
val, ok := result.Value().({{ $conv.OriginalType }})
Expand All @@ -74,7 +74,7 @@ func {{ $sig.GOName }}FromV1Data(jsonData []byte) (ret {{ $sig.GOType }}, err er
}
errs = errors.Join(errs, fmt.Errorf("failed to convert 'data.{{ $conv.OriginalName }}': %w", err))
} else {
errs = errors.Join(errs, fmt.Errorf("%w, field 'data.{{ $conv.OriginalName }}' is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", errInvalidType, result.Value(), result.Value()))
errs = errors.Join(errs, fmt.Errorf("%w, field 'data.{{ $conv.OriginalName }}' is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", convert.InvalidTypeError(), result.Value(), result.Value()))
}
{{- end }}
}
Expand Down
17 changes: 4 additions & 13 deletions pkg/nativestatus/convertv2.tmpl
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
// Code generated by github.com/DIMO-Network/model-garage DO NOT EDIT.
package convert

// errInvalidType is returned when a field is not of the expected type or not found.
var errInvalidType = errors.New("invalid type")


// IsInvalidType returns true if the error is of type errInvalidType.
func IsInvalidType(err error) bool {
return errors.Is(err, errInvalidType)
}
package nativestatus


// SignalsFromData converts the given JSON data to a slice of signals.
Expand Down Expand Up @@ -59,7 +50,7 @@ func {{ .GOName }}FromV2Data(originalDoc []byte, result gjson.Result) (ret {{ .B
if ok{
slice{{ $sig.GOName}}[i] = v
} else {
errs = errors.Join(errs, fmt.Errorf("%w, field '{{ $conv.OriginalName }}' array element %d is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", errInvalidType, i, res.Value(), res.Value()))
errs = errors.Join(errs, fmt.Errorf("%w, field '{{ $conv.OriginalName }}' array element %d is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", convert.InvalidTypeError(), i, res.Value(), res.Value()))
}
}
ret, err = To{{ $sig.GOName }}{{ $j }}(originalDoc, slice{{ $sig.GOName}})
Expand All @@ -68,7 +59,7 @@ func {{ .GOName }}FromV2Data(originalDoc []byte, result gjson.Result) (ret {{ .B
}
errs = errors.Join(errs, fmt.Errorf("failed to convert '{{ $sig.Conversion.OriginalName }}': %w", err))
} else {
errs = errros.Join(errs, fmt.Errorf("%w, field '{{ $conv.OriginalName }}' is not an array", errInvalidType))
errs = errros.Join(errs, fmt.Errorf("%w, field '{{ $conv.OriginalName }}' is not an array", convert.InvalidTypeError()))
}
{{ else -}}
val{{ $j }}, ok := result.Value().({{ $conv.OriginalType }})
Expand All @@ -79,7 +70,7 @@ func {{ .GOName }}FromV2Data(originalDoc []byte, result gjson.Result) (ret {{ .B
}
errs = errors.Join(errs, fmt.Errorf("failed to convert '{{ $conv.OriginalName }}': %w", err))
} else {
errs = errors.Join(errs, fmt.Errorf("%w, field '{{ $conv.OriginalName }}' is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", errInvalidType, result.Value(), result.Value()))
errs = errors.Join(errs, fmt.Errorf("%w, field '{{ $conv.OriginalName }}' is not of type '{{ $conv.OriginalType }}' got '%v' of type '%T'", convert.InvalidTypeError(), result.Value(), result.Value()))
}
{{- end }}
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package convert_test
package nativestatus_test

import (
"context"
Expand All @@ -7,7 +7,8 @@ import (
"testing"
"time"

"github.com/DIMO-Network/model-garage/pkg/nativestatus/convert"
"github.com/DIMO-Network/model-garage/pkg/convert"
"github.com/DIMO-Network/model-garage/pkg/nativestatus"
"github.com/DIMO-Network/model-garage/pkg/vss"
)

Expand Down Expand Up @@ -149,7 +150,7 @@ func TestVersionComparison(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
signals, err := convert.SignalsFromPayload(context.Background(), tokenGetter, test.jsonData)
signals, err := nativestatus.SignalsFromPayload(context.Background(), tokenGetter, test.jsonData)
if !reflect.DeepEqual(signals, test.expected) {
t.Errorf("Unexpected signals. Expected: %v, Got: %v", test.expected, signals)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package convert
package nativestatus

import (
"context"
Expand All @@ -7,6 +7,7 @@ import (
"math"
"strings"

"github.com/DIMO-Network/model-garage/pkg/convert"
"github.com/DIMO-Network/model-garage/pkg/vss"
"github.com/tidwall/gjson"
"golang.org/x/mod/semver"
Expand All @@ -31,7 +32,7 @@ func SignalsFromPayload(ctx context.Context, tokenGetter TokenIDGetter, jsonData
case semver.Compare(StatusV2, version) == 0:
return SignalsFromV2Payload(jsonData)
default:
return nil, VersionError{Version: version}
return nil, convert.VersionError{Version: version}
}
}

Expand All @@ -51,7 +52,7 @@ func TokenIDFromData(jsonData []byte) (uint32, error) {
lookupKey := "vehicleTokenId"
tokenID := gjson.GetBytes(jsonData, lookupKey)
if !tokenID.Exists() {
return 0, FieldNotFoundError{Field: "tokenID", Lookup: lookupKey}
return 0, convert.FieldNotFoundError{Field: "tokenID", Lookup: lookupKey}
}
id, ok := tokenID.Value().(float64)
if !ok {
Expand All @@ -65,7 +66,7 @@ func SourceFromData(jsonData []byte) (string, error) {
lookupKey := "source"
source := gjson.GetBytes(jsonData, lookupKey)
if !source.Exists() {
return "", FieldNotFoundError{Field: "source", Lookup: lookupKey}
return "", convert.FieldNotFoundError{Field: "source", Lookup: lookupKey}
}
src, ok := source.Value().(string)
if !ok {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Package convert provides a function to generate conversion functions for a vehicle struct.
package convert
// Package nativestatus provides a function to generate conversion functions for a vehicle struct.
package nativestatus

import (
"context"
"errors"
"fmt"
"time"

"github.com/DIMO-Network/model-garage/pkg/convert"
"github.com/DIMO-Network/model-garage/pkg/vss"
"github.com/tidwall/gjson"
)
Expand All @@ -20,20 +21,20 @@ type TokenIDGetter interface {
func SignalsFromV1Payload(ctx context.Context, tokenGetter TokenIDGetter, jsonData []byte) ([]vss.Signal, error) {
ts, err := TimestampFromV1Data(jsonData)
if err != nil {
return nil, ConversionError{
return nil, convert.ConversionError{
Errors: []error{fmt.Errorf("error getting timestamp: %w", err)},
}
}
tokenID, err := TokenIDFromV1Data(ctx, jsonData, tokenGetter)
if err != nil {
return nil, ConversionError{
return nil, convert.ConversionError{
Errors: []error{fmt.Errorf("error getting tokenId: %w", err)},
}
}

source, err := SourceFromData(jsonData)
if err != nil {
return nil, ConversionError{
return nil, convert.ConversionError{
TokenID: tokenID,
Errors: []error{fmt.Errorf("error getting source: %w", err)},
}
Expand All @@ -45,7 +46,7 @@ func SignalsFromV1Payload(ctx context.Context, tokenGetter TokenIDGetter, jsonDa
}
sigs, errs := SignalsFromV1Data(baseSignal, jsonData)
if errs != nil {
return nil, ConversionError{
return nil, convert.ConversionError{
TokenID: tokenID,
Source: source,
DecodedSignals: sigs,
Expand All @@ -59,7 +60,7 @@ func SignalsFromV1Payload(ctx context.Context, tokenGetter TokenIDGetter, jsonDa
func SubjectFromV1Data(jsonData []byte) (string, error) {
result := gjson.GetBytes(jsonData, "subject")
if !result.Exists() {
return "", FieldNotFoundError{Field: "subject", Lookup: "subject"}
return "", convert.FieldNotFoundError{Field: "subject", Lookup: "subject"}
}
sub, ok := result.Value().(string)
if !ok {
Expand All @@ -72,7 +73,7 @@ func SubjectFromV1Data(jsonData []byte) (string, error) {
func TimestampFromV1Data(jsonData []byte) (time.Time, error) {
result := gjson.GetBytes(jsonData, "time")
if !result.Exists() {
return time.Time{}, FieldNotFoundError{Field: "timestamp", Lookup: "time"}
return time.Time{}, convert.FieldNotFoundError{Field: "timestamp", Lookup: "time"}
}

timeStr, ok := result.Value().(string)
Expand All @@ -98,7 +99,7 @@ func TokenIDFromV1Data(ctx context.Context, jsonData []byte, tokenGetter TokenID
if err == nil {
return tokenID, nil
}
if !errors.As(err, &FieldNotFoundError{}) {
if !errors.As(err, &convert.FieldNotFoundError{}) {
return 0, err
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package convert_test
package nativestatus_test

import (
"cmp"
Expand All @@ -7,7 +7,7 @@ import (
"testing"
"time"

"github.com/DIMO-Network/model-garage/pkg/nativestatus/convert"
"github.com/DIMO-Network/model-garage/pkg/nativestatus"
"github.com/DIMO-Network/model-garage/pkg/vss"
"github.com/stretchr/testify/require"
)
Expand All @@ -21,7 +21,7 @@ func (*tokenGetter) TokenIDFromSubject(context.Context, string) (uint32, error)
func TestFullFromDataConversion(t *testing.T) {
t.Parallel()
getter := &tokenGetter{}
actualSignals, err := convert.SignalsFromPayload(context.Background(), getter, []byte(fullInputJSON))
actualSignals, err := nativestatus.SignalsFromPayload(context.Background(), getter, []byte(fullInputJSON))
require.NoErrorf(t, err, "error converting full input data: %v", err)

// sort the signals so diffs are easier to read
Expand Down Expand Up @@ -124,7 +124,7 @@ var (
func TestSkipNulls(t *testing.T) {
t.Parallel()
getter := &tokenGetter{}
actualSignals, err := convert.SignalsFromPayload(context.Background(), getter, []byte(inputJSONWithNull))
actualSignals, err := nativestatus.SignalsFromPayload(context.Background(), getter, []byte(inputJSONWithNull))
require.NoErrorf(t, err, "error converting input data: %v", err)
require.ElementsMatchf(t, expectedSignalsWithoutNull, actualSignals, "converted vehicle does not match expected vehicle")
}
Expand Down Expand Up @@ -152,7 +152,7 @@ var (

func TestWithTokenId(t *testing.T) {
t.Parallel()
actualSignals, err := convert.SignalsFromPayload(context.Background(), nil, []byte(inputJSONWithTokenID))
actualSignals, err := nativestatus.SignalsFromPayload(context.Background(), nil, []byte(inputJSONWithTokenID))
require.NoErrorf(t, err, "error converting input data: %v", err)
require.ElementsMatchf(t, expectedSignalsWithFromTokenID, actualSignals, "converted vehicle does not match expected vehicle")
}
Expand Down
Loading

0 comments on commit f209247

Please sign in to comment.