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  }