package main import ( "fmt" "os" "slices" "go.einride.tech/can/pkg/dbc" ) type SignalDef struct { id dbc.MessageID name string start, size uint64 isBigEndian bool isSigned bool } func newSignalDef(msg *dbc.MessageDef, sig dbc.SignalDef) SignalDef { return SignalDef{ msg.MessageID, string(sig.Name), sig.StartBit, sig.Size, sig.IsBigEndian, sig.IsSigned, } } // Extract signals from the DBC file. func parseSignals(filename string, names map[int]string) (map[int]SignalDef, error) { // Parse DBC file msgDefs, err := parseDbcFile(filename) if err != nil { return nil, err } // Search for signals signals := make(map[int]SignalDef) for _, msg := range msgDefs { for k, name := range names { i := slices.IndexFunc(msg.Signals, func(sig dbc.SignalDef) bool { return sig.Name == dbc.Identifier(name) }) if i < 0 { continue } if _, ok := signals[k]; ok { return nil, ErrDupSig{msg.Signals[i]} } fmt.Println(msg.Signals[i]) signals[k] = newSignalDef(msg, msg.Signals[i]) } } // Check all signals are present if len(signals) != len(names) { for k, name := range names { if _, ok := signals[k]; !ok { return nil, ErrNoSig{filename, name} } } } return signals, nil } func parseDbcFile(filename string) ([]*dbc.MessageDef, error) { // Read file buf, err := os.ReadFile(filename) if err != nil { return nil, err } // Parse file parser := dbc.NewParser(filename, buf) if err := parser.Parse(); err != nil { return nil, err } // Filter message definitions defs := parser.Defs() msgDefs := make([]*dbc.MessageDef, 0, len(defs)) for _, def := range defs { if msg, ok := def.(*dbc.MessageDef); ok { msgDefs = append(msgDefs, msg) } } return msgDefs, nil } func tryAssignSignal(dst **dbc.SignalDef, sig dbc.SignalDef, targetName string) error { if targetName != "" && string(sig.Name) == targetName { if *dst != nil { return fmt.Errorf("%v: duplicate signal '%s'", sig.Pos, sig.Name) } *dst = &sig } return nil }