github.com/blueinnovationsgroup/can-go@v0.0.0-20230518195432-d0567cda0028/internal/generate/file.go (about) 1 package generate 2 3 import ( 4 "bytes" 5 "fmt" 6 "go/format" 7 "go/types" 8 "regexp" 9 10 "github.com/blueinnovationsgroup/can-go/pkg/descriptor" 11 "github.com/shurcooL/go-goon" 12 ) 13 14 type File struct { 15 buf bytes.Buffer 16 err error 17 } 18 19 func NewFile() *File { 20 f := &File{} 21 f.buf.Grow(1e5) // 100K 22 return f 23 } 24 25 func (f *File) Write(p []byte) (int, error) { 26 if f.err != nil { 27 return 0, f.err 28 } 29 n, err := f.buf.Write(p) 30 f.err = err 31 return n, err 32 } 33 34 func (f *File) P(v ...interface{}) { 35 for _, x := range v { 36 _, _ = fmt.Fprint(f, x) 37 } 38 _, _ = fmt.Fprintln(f) 39 } 40 41 func (f *File) Dump(v interface{}) { 42 _, _ = goon.Fdump(f, v) 43 } 44 45 func (f *File) Content() ([]byte, error) { 46 if f.err != nil { 47 return nil, fmt.Errorf("file content: %w", f.err) 48 } 49 formatted, err := format.Source(f.buf.Bytes()) 50 if err != nil { 51 return nil, fmt.Errorf("file content: %s: %w", f.buf.String(), err) 52 } 53 return formatted, nil 54 } 55 56 func Database(d *descriptor.Database) ([]byte, error) { 57 f := NewFile() 58 Package(f, d) 59 Imports(f) 60 for _, m := range d.Messages { 61 MessageType(f, m) 62 for _, s := range m.Signals { 63 if hasCustomType(s) { 64 SignalCustomType(f, m, s) 65 } 66 } 67 MarshalFrame(f, m) 68 UnmarshalFrame(f, m) 69 } 70 if hasSendType(d) { // only code-generate nodes for schemas with send types specified 71 for _, n := range d.Nodes { 72 Node(f, d, n) 73 } 74 } 75 Descriptors(f, d) 76 return f.Content() 77 } 78 79 func Package(f *File, d *descriptor.Database) { 80 f.P("// Package ", d.PackageName, " provides primitives for encoding and decoding ", d.Name(), " CAN messages.") 81 f.P("//") 82 f.P("// Source: ", d.SourceFile) 83 f.P("package ", d.PackageName) 84 f.P() 85 } 86 87 func Imports(f *File) { 88 f.P("import (") 89 f.P(`"context"`) 90 f.P(`"fmt"`) 91 f.P(`"net"`) 92 f.P(`"net/http"`) 93 f.P(`"sync"`) 94 f.P(`"time"`) 95 f.P() 96 f.P(`"github.com/blueinnovationsgroup/can-go"`) 97 f.P(`"github.com/blueinnovationsgroup/can-go/pkg/socketcan"`) 98 f.P(`"github.com/blueinnovationsgroup/can-go/pkg/candebug"`) 99 f.P(`"github.com/blueinnovationsgroup/can-go/pkg/canrunner"`) 100 f.P(`"github.com/blueinnovationsgroup/can-go/pkg/descriptor"`) 101 f.P(`"github.com/blueinnovationsgroup/can-go/pkg/generated"`) 102 f.P(`"github.com/blueinnovationsgroup/can-go/pkg/cantext"`) 103 f.P(")") 104 f.P() 105 // we could use goimports for this, but it significantly slows down code generation 106 f.P("// prevent unused imports") 107 f.P("var (") 108 f.P("_ = context.Background") 109 f.P("_ = fmt.Print") 110 f.P("_ = net.Dial") 111 f.P("_ = http.Error") 112 f.P("_ = sync.Mutex{}") 113 f.P("_ = time.Now") 114 f.P("_ = socketcan.Dial") 115 f.P("_ = candebug.ServeMessagesHTTP") 116 f.P("_ = canrunner.Run") 117 f.P(")") 118 f.P() 119 f.P("// Generated code. DO NOT EDIT.") 120 } 121 122 var nonAlphaNumericRegexp = regexp.MustCompile("[^a-zA-Z0-9]+") 123 124 func slugifyString(s string) string { 125 return nonAlphaNumericRegexp.ReplaceAllString(s, "") 126 } 127 128 func SignalCustomType(f *File, m *descriptor.Message, s *descriptor.Signal) { 129 f.P("// ", signalType(m, s), " models the ", s.Name, " signal of the ", m.Name, " message.") 130 f.P("type ", signalType(m, s), " ", signalPrimitiveType(s)) 131 f.P() 132 f.P("// Value descriptions for the ", s.Name, " signal of the ", m.Name, " message.") 133 f.P("const (") 134 for _, vd := range s.ValueDescriptions { 135 desc := slugifyString(vd.Description) 136 switch { 137 case s.Length == 1 && vd.Value == 1: 138 f.P(signalType(m, s), "_", desc, " ", signalType(m, s), " = true") 139 case s.Length == 1 && vd.Value == 0: 140 f.P(signalType(m, s), "_", desc, " ", signalType(m, s), " = false") 141 default: 142 f.P(signalType(m, s), "_", desc, " ", signalType(m, s), " = ", vd.Value) 143 } 144 } 145 f.P(")") 146 f.P() 147 f.P("func (v ", signalType(m, s), ") String() string {") 148 if s.Length == 1 { 149 f.P("switch bool(v) {") 150 for _, vd := range s.ValueDescriptions { 151 if vd.Value == 1 { 152 f.P("case true:") 153 } else { 154 f.P("case false:") 155 } 156 f.P(`return "`, vd.Description, `"`) 157 } 158 f.P("}") 159 f.P(`return fmt.Sprintf("`, signalType(m, s), `(%t)", v)`) 160 } else { 161 f.P("switch v {") 162 for _, vd := range s.ValueDescriptions { 163 f.P("case ", vd.Value, ":") 164 f.P(`return "`, vd.Description, `"`) 165 } 166 f.P("default:") 167 f.P(`return fmt.Sprintf("`, signalType(m, s), `(%d)", v)`) 168 f.P("}") 169 } 170 f.P("}") 171 } 172 173 func MessageType(f *File, m *descriptor.Message) { 174 f.P("// ", messageReaderInterface(m), " provides read access to a ", m.Name, " message.") 175 f.P("type ", messageReaderInterface(m), " interface {") 176 for _, s := range m.Signals { 177 if hasPhysicalRepresentation(s) { 178 f.P("// ", s.Name, " returns the physical value of the ", s.Name, " signal.") 179 f.P(s.Name, "() float64") 180 if len(s.ValueDescriptions) > 0 { 181 f.P() 182 f.P("// ", s.Name, " returns the raw (encoded) value of the ", s.Name, " signal.") 183 f.P("Raw", s.Name, "() ", signalType(m, s)) 184 } 185 } else { 186 f.P("// ", s.Name, " returns the value of the ", s.Name, " signal.") 187 f.P(s.Name, "()", signalType(m, s)) 188 } 189 } 190 f.P("}") 191 f.P() 192 f.P("// ", messageWriterInterface(m), " provides write access to a ", m.Name, " message.") 193 f.P("type ", messageWriterInterface(m), " interface {") 194 f.P("// CopyFrom copies all values from ", messageReaderInterface(m), ".") 195 f.P("CopyFrom(", messageReaderInterface(m), ") *", messageStruct(m)) 196 for _, s := range m.Signals { 197 if hasPhysicalRepresentation(s) { 198 f.P("// Set", s.Name, " sets the physical value of the ", s.Name, " signal.") 199 f.P("Set", s.Name, "(float64) *", messageStruct(m)) 200 if len(s.ValueDescriptions) > 0 { 201 f.P() 202 f.P("// SetRaw", s.Name, " sets the raw (encoded) value of the ", s.Name, " signal.") 203 f.P("SetRaw", s.Name, "(", signalType(m, s), ") *", messageStruct(m)) 204 } 205 } else { 206 f.P("// Set", s.Name, " sets the value of the ", s.Name, " signal.") 207 f.P("Set", s.Name, "(", signalType(m, s), ") *", messageStruct(m)) 208 } 209 } 210 f.P("}") 211 f.P() 212 f.P("type ", messageStruct(m), " struct {") 213 for _, s := range m.Signals { 214 f.P(signalField(s), " ", signalType(m, s)) 215 } 216 f.P("}") 217 f.P() 218 f.P("func New", messageStruct(m), "() *", messageStruct(m), " {") 219 f.P("m := &", messageStruct(m), "{}") 220 f.P("m.Reset()") 221 f.P("return m") 222 f.P("}") 223 f.P() 224 f.P("func (m *", messageStruct(m), ") Reset() {") 225 for _, s := range m.Signals { 226 switch { 227 case s.Length == 1 && s.DefaultValue == 1: 228 f.P("m.", signalField(s), " = true") 229 case s.Length == 1: 230 f.P("m.", signalField(s), " = false") 231 default: 232 f.P("m.", signalField(s), " = ", s.DefaultValue) 233 } 234 } 235 f.P("}") 236 f.P() 237 f.P("func (m *", messageStruct(m), ") CopyFrom(o ", messageReaderInterface(m), ") *", messageStruct(m), "{") 238 for _, s := range m.Signals { 239 if hasPhysicalRepresentation(s) { 240 f.P("m.Set", s.Name, "(o.", s.Name, "())") 241 } else { 242 f.P("m.", signalField(s), " = o.", s.Name, "()") 243 } 244 } 245 f.P("return m") 246 f.P("}") 247 f.P() 248 f.P("// Descriptor returns the ", m.Name, " descriptor.") 249 f.P("func (m *", messageStruct(m), ") Descriptor() *descriptor.Message {") 250 f.P("return ", messageDescriptor(m), ".Message") 251 f.P("}") 252 f.P() 253 f.P("// String returns a compact string representation of the message.") 254 f.P("func(m *", messageStruct(m), ") String() string {") 255 f.P("return cantext.MessageString(m)") 256 f.P("}") 257 f.P() 258 for _, s := range m.Signals { 259 if !hasPhysicalRepresentation(s) { 260 f.P("func (m *", messageStruct(m), ") ", s.Name, "() ", signalType(m, s), " {") 261 f.P("return m.", signalField(s)) 262 f.P("}") 263 f.P() 264 f.P("func (m *", messageStruct(m), ") Set", s.Name, "(v ", signalType(m, s), ") *", messageStruct(m), " {") 265 if s.Length == 1 { 266 f.P("m.", signalField(s), " = v") 267 } else { 268 f.P( 269 "m.", signalField(s), " = ", signalType(m, s), "(", 270 signalDescriptor(m, s), ".SaturatedCast", signalSuperType(s), "(", 271 signalPrimitiveSuperType(s), "(v)))", 272 ) 273 } 274 f.P("return m") 275 f.P("}") 276 f.P() 277 continue 278 } 279 f.P("func (m *", messageStruct(m), ") ", s.Name, "() float64 {") 280 f.P("return ", signalDescriptor(m, s), ".ToPhysical(float64(m.", signalField(s), "))") 281 f.P("}") 282 f.P() 283 f.P("func (m *", messageStruct(m), ") Set", s.Name, "(v float64) *", messageStruct(m), " {") 284 f.P("m.", signalField(s), " = ", signalType(m, s), "(", signalDescriptor(m, s), ".FromPhysical(v))") 285 f.P("return m") 286 f.P("}") 287 f.P() 288 if len(s.ValueDescriptions) > 0 { 289 f.P("func (m *", messageStruct(m), ") Raw", s.Name, "() ", signalType(m, s), " {") 290 f.P("return m.", signalField(s)) 291 f.P("}") 292 f.P() 293 f.P("func (m *", messageStruct(m), ") SetRaw", s.Name, "(v ", signalType(m, s), ") *", messageStruct(m), "{") 294 f.P( 295 "m.", signalField(s), " = ", signalType(m, s), "(", 296 signalDescriptor(m, s), ".SaturatedCast", signalSuperType(s), "(", 297 signalPrimitiveSuperType(s), "(v)))", 298 ) 299 f.P("return m") 300 f.P("}") 301 f.P() 302 } 303 } 304 } 305 306 func Descriptors(f *File, d *descriptor.Database) { 307 f.P("// Nodes returns the ", d.Name(), " node descriptors.") 308 f.P("func Nodes() *NodesDescriptor {") 309 f.P("return nd") 310 f.P("}") 311 f.P() 312 f.P("// NodesDescriptor contains all ", d.Name(), " node descriptors.") 313 f.P("type NodesDescriptor struct{") 314 for _, n := range d.Nodes { 315 f.P(n.Name, " *descriptor.Node") 316 } 317 f.P("}") 318 f.P() 319 f.P("// Messages returns the ", d.Name(), " message descriptors.") 320 f.P("func Messages() *MessagesDescriptor {") 321 f.P("return md") 322 f.P("}") 323 f.P() 324 f.P("// MessagesDescriptor contains all ", d.Name(), " message descriptors.") 325 f.P("type MessagesDescriptor struct{") 326 for _, m := range d.Messages { 327 f.P(m.Name, " *", m.Name, "Descriptor") 328 } 329 f.P("}") 330 f.P() 331 f.P("// UnmarshalFrame unmarshals the provided ", d.Name(), " CAN frame.") 332 f.P("func (md *MessagesDescriptor) UnmarshalFrame(f can.Frame) (generated.Message, error) {") 333 f.P("switch f.ID {") 334 for _, m := range d.Messages { 335 f.P("case md.", m.Name, ".ID:") 336 f.P("var msg ", messageStruct(m)) 337 f.P("if err := msg.UnmarshalFrame(f); err != nil {") 338 f.P(`return nil, fmt.Errorf("unmarshal `, d.Name(), ` frame: %w", err)`) 339 f.P("}") 340 f.P("return &msg, nil") 341 } 342 f.P("default:") 343 f.P(`return nil, fmt.Errorf("unmarshal `, d.Name(), ` frame: ID not in database: %d", f.ID)`) 344 f.P("}") 345 f.P("}") 346 f.P() 347 for _, m := range d.Messages { 348 f.P("type ", m.Name, "Descriptor struct{") 349 f.P("*descriptor.Message") 350 for _, s := range m.Signals { 351 f.P(s.Name, " *descriptor.Signal") 352 } 353 f.P("}") 354 f.P() 355 } 356 f.P("// Database returns the ", d.Name(), " database descriptor.") 357 f.P("func (md *MessagesDescriptor) Database() *descriptor.Database {") 358 f.P("return d") 359 f.P("}") 360 f.P() 361 f.P("var nd = &NodesDescriptor{") 362 for ni, n := range d.Nodes { 363 f.P(n.Name, ": d.Nodes[", ni, "],") 364 } 365 f.P("}") 366 f.P() 367 f.P("var md = &MessagesDescriptor{") 368 for mi, m := range d.Messages { 369 f.P(m.Name, ": &", m.Name, "Descriptor{") 370 f.P("Message: d.Messages[", mi, "],") 371 for si, s := range m.Signals { 372 f.P(s.Name, ": d.Messages[", mi, "].Signals[", si, "],") 373 } 374 f.P("},") 375 } 376 f.P("}") 377 f.P() 378 f.P("var d = ") 379 f.Dump(d) 380 f.P() 381 } 382 383 func MarshalFrame(f *File, m *descriptor.Message) { 384 f.P("// Frame returns a CAN frame representing the message.") 385 f.P("func (m *", messageStruct(m), ") Frame() can.Frame {") 386 f.P("md := ", messageDescriptor(m)) 387 f.P("f := can.Frame{ID: md.ID, IsExtended: md.IsExtended, Length: md.Length}") 388 for _, s := range m.Signals { 389 if s.IsMultiplexed { 390 continue 391 } 392 f.P( 393 "md.", s.Name, ".Marshal", signalSuperType(s), 394 "(&f.Data, ", signalPrimitiveSuperType(s), "(m.", signalField(s), "))", 395 ) 396 } 397 if mux, ok := m.MultiplexerSignal(); ok { 398 for _, s := range m.Signals { 399 if !s.IsMultiplexed { 400 continue 401 } 402 f.P("if m.", signalField(mux), " == ", s.MultiplexerValue, " {") 403 f.P( 404 "md.", s.Name, ".Marshal", signalSuperType(s), "(&f.Data, ", signalPrimitiveSuperType(s), 405 "(m.", signalField(s), "))", 406 ) 407 f.P("}") 408 } 409 } 410 f.P("return f") 411 f.P("}") 412 f.P() 413 f.P("// MarshalFrame encodes the message as a CAN frame.") 414 f.P("func (m *", messageStruct(m), ") MarshalFrame() (can.Frame, error) {") 415 f.P("return m.Frame(), nil") 416 f.P("}") 417 f.P() 418 } 419 420 func UnmarshalFrame(f *File, m *descriptor.Message) { 421 f.P("// UnmarshalFrame decodes the message from a CAN frame.") 422 f.P("func (m *", messageStruct(m), ") UnmarshalFrame(f can.Frame) error {") 423 f.P("md := ", messageDescriptor(m)) 424 // generate frame checks 425 id := func(isExtended bool) string { 426 if isExtended { 427 return "extended ID" 428 } 429 return "standard ID" 430 } 431 f.P("switch {") 432 f.P("case f.ID != md.ID:") 433 f.P(`return fmt.Errorf(`) 434 f.P(`"unmarshal `, m.Name, `: expects ID `, m.ID, ` (got %s with ID %d)", f.String(), f.ID,`) 435 f.P(`)`) 436 f.P("case f.Length != md.Length:") 437 f.P(`return fmt.Errorf(`) 438 f.P(`"unmarshal `, m.Name, `: expects length `, m.Length, ` (got %s with length %d)", f.String(), f.Length,`) 439 f.P(`)`) 440 f.P("case f.IsRemote:") 441 f.P(`return fmt.Errorf(`) 442 f.P(`"unmarshal `, m.Name, `: expects non-remote frame (got remote frame %s)", f.String(),`) 443 f.P(`)`) 444 f.P("case f.IsExtended != md.IsExtended:") 445 f.P(`return fmt.Errorf(`) 446 f.P(`"unmarshal `, m.Name, `: expects `, id(m.IsExtended), ` (got %s with `, id(!m.IsExtended), `)", f.String(),`) 447 f.P(`)`) 448 f.P("}") 449 if len(m.Signals) == 0 { 450 f.P("return nil") 451 f.P("}") 452 return 453 } 454 // generate non-multiplexed signal unmarshaling 455 for _, s := range m.Signals { 456 if s.IsMultiplexed { 457 continue 458 } 459 f.P("m.", signalField(s), " = ", signalType(m, s), "(md.", s.Name, ".Unmarshal", signalSuperType(s), "(f.Data))") 460 } 461 // generate multiplexed signal unmarshaling 462 if mux, ok := m.MultiplexerSignal(); ok { 463 for _, s := range m.Signals { 464 if !s.IsMultiplexed { 465 continue 466 } 467 f.P("if m.", signalField(mux), " == ", s.MultiplexerValue, " {") 468 f.P("m.", signalField(s), " = ", signalType(m, s), "(md.", s.Name, ".Unmarshal", signalSuperType(s), "(f.Data))") 469 f.P("}") 470 } 471 } 472 f.P("return nil") 473 f.P("}") 474 f.P() 475 } 476 477 func Node(f *File, d *descriptor.Database, n *descriptor.Node) { 478 rxMessages := collectRxMessages(d, n) 479 txMessages := collectTxMessages(d, n) 480 f.P("type ", nodeInterface(n), " interface {") 481 f.P("sync.Locker") 482 f.P("Tx() ", txGroupInterface(n)) 483 f.P("Rx() ", rxGroupInterface(n)) 484 f.P("Run(ctx context.Context) error") 485 f.P("}") 486 f.P() 487 f.P("type ", rxGroupInterface(n), " interface {") 488 f.P("http.Handler // for debugging") 489 for _, m := range rxMessages { 490 f.P(m.Name, "() ", rxMessageInterface(n, m)) 491 } 492 f.P("}") 493 f.P() 494 f.P("type ", txGroupInterface(n), " interface {") 495 f.P("http.Handler // for debugging") 496 for _, m := range txMessages { 497 f.P(m.Name, "() ", txMessageInterface(n, m)) 498 } 499 f.P("}") 500 f.P() 501 for _, m := range rxMessages { 502 f.P("type ", rxMessageInterface(n, m), " interface {") 503 f.P(messageReaderInterface(m)) 504 f.P("ReceiveTime() time.Time") 505 f.P("SetAfterReceiveHook(h func(context.Context) error)") 506 f.P("}") 507 f.P() 508 } 509 for _, m := range txMessages { 510 f.P("type ", txMessageInterface(n, m), " interface {") 511 f.P(messageReaderInterface(m)) 512 f.P(messageWriterInterface(m)) 513 f.P("TransmitTime() time.Time") 514 f.P("Transmit(ctx context.Context) error") 515 f.P("SetBeforeTransmitHook(h func(context.Context) error)") 516 if m.SendType == descriptor.SendTypeCyclic { 517 f.P("// SetCyclicTransmissionEnabled enables/disables cyclic transmission.") 518 f.P("SetCyclicTransmissionEnabled(bool)") 519 f.P("// IsCyclicTransmissionEnabled returns whether cyclic transmission is enabled/disabled.") 520 f.P("IsCyclicTransmissionEnabled() bool") 521 } 522 f.P("}") 523 f.P() 524 } 525 f.P("type ", nodeStruct(n), " struct {") 526 f.P("sync.Mutex // protects all node state") 527 f.P("network string") 528 f.P("address string") 529 f.P("rx ", rxGroupStruct(n)) 530 f.P("tx ", txGroupStruct(n)) 531 f.P("}") 532 f.P() 533 f.P("var _ ", nodeInterface(n), " = &", nodeStruct(n), "{}") 534 f.P("var _ canrunner.Node = &", nodeStruct(n), "{}") 535 f.P() 536 f.P("func New", nodeInterface(n), "(network, address string) ", nodeInterface(n), " {") 537 f.P("n := &", nodeStruct(n), "{network: network, address: address}") 538 f.P("n.rx.parentMutex = &n.Mutex") 539 f.P("n.tx.parentMutex = &n.Mutex") 540 for _, m := range rxMessages { 541 f.P("n.rx.", messageField(m), ".init()") 542 f.P("n.rx.", messageField(m), ".Reset()") 543 } 544 for _, m := range txMessages { 545 f.P("n.tx.", messageField(m), ".init()") 546 f.P("n.tx.", messageField(m), ".Reset()") 547 } 548 f.P("return n") 549 f.P("}") 550 f.P() 551 f.P("func (n *", nodeStruct(n), ") Run(ctx context.Context) error {") 552 f.P("return canrunner.Run(ctx, n)") 553 f.P("}") 554 f.P() 555 f.P("func (n *", nodeStruct(n), ") Rx() ", rxGroupInterface(n), " {") 556 f.P("return &n.rx") 557 f.P("}") 558 f.P() 559 f.P("func (n *", nodeStruct(n), ") Tx() ", txGroupInterface(n), " {") 560 f.P("return &n.tx") 561 f.P("}") 562 f.P() 563 f.P("type ", rxGroupStruct(n), " struct {") 564 f.P("parentMutex *sync.Mutex") 565 for _, m := range rxMessages { 566 f.P(messageField(m), " ", rxMessageStruct(n, m)) 567 } 568 f.P("}") 569 f.P() 570 f.P("var _ ", rxGroupInterface(n), " = &", rxGroupStruct(n), "{}") 571 f.P() 572 f.P("func (rx *", rxGroupStruct(n), ") ServeHTTP(w http.ResponseWriter, r *http.Request) {") 573 f.P("rx.parentMutex.Lock()") 574 f.P("defer rx.parentMutex.Unlock()") 575 f.P("candebug.ServeMessagesHTTP(w, r, []generated.Message{") 576 for _, m := range rxMessages { 577 f.P("&rx.", messageField(m), ",") 578 } 579 f.P("})") 580 f.P("}") 581 f.P() 582 for _, m := range rxMessages { 583 f.P("func (rx *", rxGroupStruct(n), ") ", m.Name, "() ", rxMessageInterface(n, m), " {") 584 f.P("return &rx.", messageField(m)) 585 f.P("}") 586 f.P() 587 } 588 f.P() 589 f.P("type ", txGroupStruct(n), " struct {") 590 f.P("parentMutex *sync.Mutex") 591 for _, m := range txMessages { 592 f.P(messageField(m), " ", txMessageStruct(n, m)) 593 } 594 f.P("}") 595 f.P() 596 f.P("var _ ", txGroupInterface(n), " = &", txGroupStruct(n), "{}") 597 f.P() 598 f.P("func (tx *", txGroupStruct(n), ") ServeHTTP(w http.ResponseWriter, r *http.Request) {") 599 f.P("tx.parentMutex.Lock()") 600 f.P("defer tx.parentMutex.Unlock()") 601 f.P("candebug.ServeMessagesHTTP(w, r, []generated.Message{") 602 for _, m := range txMessages { 603 f.P("&tx.", messageField(m), ",") 604 } 605 f.P("})") 606 f.P("}") 607 f.P() 608 for _, m := range txMessages { 609 f.P("func (tx *", txGroupStruct(n), ") ", m.Name, "() ", txMessageInterface(n, m), " {") 610 f.P("return &tx.", messageField(m)) 611 f.P("}") 612 f.P() 613 } 614 f.P() 615 f.P("func (n *", nodeStruct(n), ") Descriptor() *descriptor.Node {") 616 f.P("return ", nodeDescriptor(n)) 617 f.P("}") 618 f.P() 619 f.P("func (n *", nodeStruct(n), ") Connect() (net.Conn, error) {") 620 f.P("return socketcan.Dial(n.network, n.address)") 621 f.P("}") 622 f.P() 623 f.P("func (n *", nodeStruct(n), ") ReceivedMessage(id uint32) (canrunner.ReceivedMessage, bool) {") 624 f.P("switch id {") 625 for _, m := range rxMessages { 626 f.P("case ", m.ID, ":") 627 f.P("return &n.rx.", messageField(m), ", true") 628 } 629 f.P("default:") 630 f.P("return nil, false") 631 f.P("}") 632 f.P("}") 633 f.P() 634 f.P("func (n *", nodeStruct(n), ") TransmittedMessages() []canrunner.TransmittedMessage {") 635 f.P("return []canrunner.TransmittedMessage{") 636 for _, m := range txMessages { 637 f.P("&n.tx.", messageField(m), ",") 638 } 639 f.P("}") 640 f.P("}") 641 f.P() 642 for _, m := range rxMessages { 643 f.P("type ", rxMessageStruct(n, m), " struct {") 644 f.P(messageStruct(m)) 645 f.P("receiveTime time.Time") 646 f.P("afterReceiveHook func(context.Context) error") 647 f.P("}") 648 f.P() 649 f.P("func (m *", rxMessageStruct(n, m), ") init() {") 650 f.P("m.afterReceiveHook = func(context.Context) error { return nil }") 651 f.P("}") 652 f.P() 653 f.P("func (m *", rxMessageStruct(n, m), ") SetAfterReceiveHook(h func(context.Context) error) {") 654 f.P("m.afterReceiveHook = h") 655 f.P("}") 656 f.P() 657 f.P("func (m *", rxMessageStruct(n, m), ") AfterReceiveHook() func(context.Context) error {") 658 f.P("return m.afterReceiveHook") 659 f.P("}") 660 f.P() 661 f.P("func (m *", rxMessageStruct(n, m), ") ReceiveTime() time.Time {") 662 f.P("return m.receiveTime") 663 f.P("}") 664 f.P() 665 f.P("func (m *", rxMessageStruct(n, m), ") SetReceiveTime(t time.Time) {") 666 f.P("m.receiveTime = t") 667 f.P("}") 668 f.P() 669 f.P("var _ canrunner.ReceivedMessage = &", rxMessageStruct(n, m), "{}") 670 f.P() 671 } 672 for _, m := range txMessages { 673 f.P("type ", txMessageStruct(n, m), " struct {") 674 f.P(messageStruct(m)) 675 f.P("transmitTime time.Time") 676 f.P("beforeTransmitHook func(context.Context) error") 677 f.P("isCyclicEnabled bool") 678 f.P("wakeUpChan chan struct{}") 679 f.P("transmitEventChan chan struct{}") 680 f.P("}") 681 f.P() 682 f.P("var _ ", txMessageInterface(n, m), " = &", txMessageStruct(n, m), "{}") 683 f.P("var _ canrunner.TransmittedMessage = &", txMessageStruct(n, m), "{}") 684 f.P() 685 f.P("func (m *", txMessageStruct(n, m), ") init() {") 686 f.P("m.beforeTransmitHook = func(context.Context) error { return nil }") 687 f.P("m.wakeUpChan = make(chan struct{}, 1)") 688 f.P("m.transmitEventChan = make(chan struct{})") 689 f.P("}") 690 f.P() 691 f.P("func (m *", txMessageStruct(n, m), ") SetBeforeTransmitHook(h func(context.Context) error) {") 692 f.P("m.beforeTransmitHook = h") 693 f.P("}") 694 f.P() 695 f.P("func (m *", txMessageStruct(n, m), ") BeforeTransmitHook() func(context.Context) error {") 696 f.P("return m.beforeTransmitHook") 697 f.P("}") 698 f.P() 699 f.P("func (m *", txMessageStruct(n, m), ") TransmitTime() time.Time {") 700 f.P("return m.transmitTime") 701 f.P("}") 702 f.P() 703 f.P("func (m *", txMessageStruct(n, m), ") SetTransmitTime(t time.Time) {") 704 f.P("m.transmitTime = t") 705 f.P("}") 706 f.P() 707 f.P("func (m *", txMessageStruct(n, m), ") IsCyclicTransmissionEnabled() bool {") 708 f.P("return m.isCyclicEnabled") 709 f.P("}") 710 f.P() 711 f.P("func (m *", txMessageStruct(n, m), ") SetCyclicTransmissionEnabled(b bool) {") 712 f.P("m.isCyclicEnabled = b") 713 f.P("select {") 714 f.P("case m.wakeUpChan <-struct{}{}:") 715 f.P("default:") 716 f.P("}") 717 f.P("}") 718 f.P() 719 f.P("func (m *", txMessageStruct(n, m), ") WakeUpChan() <-chan struct{} {") 720 f.P("return m.wakeUpChan") 721 f.P("}") 722 f.P() 723 f.P("func (m *", txMessageStruct(n, m), ") Transmit(ctx context.Context) error {") 724 f.P("select {") 725 f.P("case m.transmitEventChan <- struct{}{}:") 726 f.P("return nil") 727 f.P("case <-ctx.Done():") 728 f.P(`return fmt.Errorf("event-triggered transmit of `, m.Name, `: %w", ctx.Err())`) 729 f.P("}") 730 f.P("}") 731 f.P() 732 f.P("func (m *", txMessageStruct(n, m), ") TransmitEventChan() <-chan struct{} {") 733 f.P("return m.transmitEventChan") 734 f.P("}") 735 f.P() 736 f.P("var _ canrunner.TransmittedMessage = &", txMessageStruct(n, m), "{}") 737 f.P() 738 } 739 } 740 741 func txGroupInterface(n *descriptor.Node) string { 742 return n.Name + "_Tx" 743 } 744 745 func txGroupStruct(n *descriptor.Node) string { 746 return "xxx_" + n.Name + "_Tx" 747 } 748 749 func rxGroupInterface(n *descriptor.Node) string { 750 return n.Name + "_Rx" 751 } 752 753 func rxGroupStruct(n *descriptor.Node) string { 754 return "xxx_" + n.Name + "_Rx" 755 } 756 757 func rxMessageInterface(n *descriptor.Node, m *descriptor.Message) string { 758 return n.Name + "_Rx_" + m.Name 759 } 760 761 func rxMessageStruct(n *descriptor.Node, m *descriptor.Message) string { 762 return "xxx_" + n.Name + "_Rx_" + m.Name 763 } 764 765 func txMessageInterface(n *descriptor.Node, m *descriptor.Message) string { 766 return n.Name + "_Tx_" + m.Name 767 } 768 769 func txMessageStruct(n *descriptor.Node, m *descriptor.Message) string { 770 return "xxx_" + n.Name + "_Tx_" + m.Name 771 } 772 773 func collectTxMessages(d *descriptor.Database, n *descriptor.Node) []*descriptor.Message { 774 tx := make([]*descriptor.Message, 0, len(d.Messages)) 775 for _, m := range d.Messages { 776 if m.SenderNode == n.Name && m.SendType != descriptor.SendTypeNone { 777 tx = append(tx, m) 778 } 779 } 780 return tx 781 } 782 783 func collectRxMessages(d *descriptor.Database, n *descriptor.Node) []*descriptor.Message { 784 rx := make([]*descriptor.Message, 0, len(d.Messages)) 785 Loop: 786 for _, m := range d.Messages { 787 for _, s := range m.Signals { 788 for _, node := range s.ReceiverNodes { 789 if node != n.Name { 790 continue 791 } 792 rx = append(rx, m) 793 continue Loop 794 } 795 } 796 } 797 return rx 798 } 799 800 func hasPhysicalRepresentation(s *descriptor.Signal) bool { 801 hasScale := s.Scale != 0 && s.Scale != 1 802 hasOffset := s.Offset != 0 803 hasRange := s.Min != 0 || s.Max != 0 804 var hasConstrainedRange bool 805 if s.IsSigned { 806 hasConstrainedRange = s.Min > float64(s.MinSigned()) || s.Max < float64(s.MaxSigned()) 807 } else { 808 hasConstrainedRange = s.Min > 0 || s.Max < float64(s.MaxUnsigned()) 809 } 810 return hasScale || hasOffset || hasRange && hasConstrainedRange 811 } 812 813 func hasCustomType(s *descriptor.Signal) bool { 814 return len(s.ValueDescriptions) > 0 815 } 816 817 func hasSendType(d *descriptor.Database) bool { 818 for _, m := range d.Messages { 819 if m.SendType != descriptor.SendTypeNone { 820 return true 821 } 822 } 823 return false 824 } 825 826 func signalType(m *descriptor.Message, s *descriptor.Signal) string { 827 if hasCustomType(s) { 828 return m.Name + "_" + s.Name 829 } 830 return signalPrimitiveType(s).String() 831 } 832 833 func signalPrimitiveType(s *descriptor.Signal) types.Type { 834 var t types.BasicKind 835 switch { 836 case s.Length == 1: 837 t = types.Bool 838 case s.Length <= 8 && s.IsSigned: 839 t = types.Int8 840 case s.Length <= 8: 841 t = types.Uint8 842 case s.Length <= 16 && s.IsSigned: 843 t = types.Int16 844 case s.Length <= 16: 845 t = types.Uint16 846 case s.Length <= 32 && s.IsSigned: 847 t = types.Int32 848 case s.Length <= 32: 849 t = types.Uint32 850 case s.Length <= 64 && s.IsSigned: 851 t = types.Int64 852 default: 853 t = types.Uint64 854 } 855 return types.Typ[t] 856 } 857 858 func signalPrimitiveSuperType(s *descriptor.Signal) types.Type { 859 var t types.BasicKind 860 switch { 861 case s.Length == 1: 862 t = types.Bool 863 case s.IsSigned: 864 t = types.Int64 865 default: 866 t = types.Uint64 867 } 868 return types.Typ[t] 869 } 870 871 func signalSuperType(s *descriptor.Signal) string { 872 switch { 873 case s.Length == 1: 874 return "Bool" 875 case s.IsSigned: 876 return "Signed" 877 default: 878 return "Unsigned" 879 } 880 } 881 882 func nodeInterface(n *descriptor.Node) string { 883 return n.Name 884 } 885 886 func nodeStruct(n *descriptor.Node) string { 887 return "xxx_" + n.Name 888 } 889 890 func messageStruct(m *descriptor.Message) string { 891 return m.Name 892 } 893 894 func messageReaderInterface(m *descriptor.Message) string { 895 return m.Name + "Reader" 896 } 897 898 func messageWriterInterface(m *descriptor.Message) string { 899 return m.Name + "Writer" 900 } 901 902 func messageField(m *descriptor.Message) string { 903 return "xxx_" + m.Name 904 } 905 906 func signalField(s *descriptor.Signal) string { 907 return "xxx_" + s.Name 908 } 909 910 func nodeDescriptor(n *descriptor.Node) string { 911 return "Nodes()." + n.Name 912 } 913 914 func messageDescriptor(m *descriptor.Message) string { 915 return "Messages()." + m.Name 916 } 917 918 func signalDescriptor(m *descriptor.Message, s *descriptor.Signal) string { 919 return messageDescriptor(m) + "." + s.Name 920 }