github.com/xiaoxu5271/can-go@v1.0.1/internal/generate/file.go (about)

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